DBD-SQLite
view release on metacpan or search on metacpan
** ^This interface causes the xEntryPoint() function to be invoked for
** each new [database connection] that is created. The idea here is that
** xEntryPoint() is the entry point for a statically linked [SQLite extension]
** that is to be automatically loaded into all new database connections.
**
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects an integer result as if the signature of the
** entry point were as follows:
**
** <blockquote><pre>
** int xEntryPoint(
** sqlite3 *db,
** const char **pzErrMsg,
** const struct sqlite3_api_routines *pThunk
** );
** </pre></blockquote>)^
**
** If the xEntryPoint routine encounters an error, it should make *pzErrMsg
** point to an appropriate error message (obtained from [sqlite3_mprintf()])
** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg
** is NULL before calling the xEntryPoint(). ^SQLite will invoke
** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any
** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()],
** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail.
**
** ^Calling sqlite3_auto_extension(X) with an entry point X that is already
** on the list of automatic extensions is a harmless no-op. ^No entry point
** will be called more than once for each database connection that is opened.
**
** See also: [sqlite3_reset_auto_extension()]
** and [sqlite3_cancel_auto_extension()]
*/
SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void));
/*
** CAPI3REF: Cancel Automatic Extension Loading
**
** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
** initialization routine X that was registered using a prior call to
** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
** routine returns 1 if initialization routine X was successfully
** unregistered and it returns 0 if X was not on the list of initialization
** routines.
*/
SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));
/*
** CAPI3REF: Reset Automatic Extension Loading
**
** ^This interface disables all automatic extensions previously
** registered using [sqlite3_auto_extension()].
*/
SQLITE_API void sqlite3_reset_auto_extension(void);
/*
** Structures used by the virtual table interface
*/
typedef struct sqlite3_vtab sqlite3_vtab;
typedef struct sqlite3_index_info sqlite3_index_info;
typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
typedef struct sqlite3_module sqlite3_module;
/*
** CAPI3REF: Virtual Table Object
** KEYWORDS: sqlite3_module {virtual table module}
**
** This structure, sometimes called a "virtual table module",
** defines the implementation of a [virtual table].
** This structure consists mostly of methods for the module.
**
** ^A virtual table module is created by filling in a persistent
** instance of this structure and passing a pointer to that instance
** to [sqlite3_create_module()] or [sqlite3_create_module_v2()].
** ^The registration remains valid until it is replaced by a different
** module or until the [database connection] closes. The content
** of this structure must not change while it is registered with
** any database connection.
*/
struct sqlite3_module {
int iVersion;
int (*xCreate)(sqlite3*, void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVTab, char**);
int (*xConnect)(sqlite3*, void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVTab, char**);
int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
int (*xDisconnect)(sqlite3_vtab *pVTab);
int (*xDestroy)(sqlite3_vtab *pVTab);
int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
int (*xClose)(sqlite3_vtab_cursor*);
int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
int argc, sqlite3_value **argv);
int (*xNext)(sqlite3_vtab_cursor*);
int (*xEof)(sqlite3_vtab_cursor*);
int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
int (*xBegin)(sqlite3_vtab *pVTab);
int (*xSync)(sqlite3_vtab *pVTab);
int (*xCommit)(sqlite3_vtab *pVTab);
int (*xRollback)(sqlite3_vtab *pVTab);
int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg);
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
/* The methods above are in version 1 of the sqlite_module object. Those
** below are for version 2 and greater. */
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
/* The methods above are in versions 1 and 2 of the sqlite_module object.
** Those below are for version 3 and greater. */
int (*xShadowName)(const char*);
/* The methods above are in versions 1 through 3 of the sqlite_module object.
** Those below are for version 4 and greater. */
int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema,
const char *zTabName, int mFlags, char **pzErr);
};
/*
** CAPI3REF: Virtual Table Indexing Information
** KEYWORDS: sqlite3_index_info
**
** The sqlite3_index_info structure and its substructures is used as part
** of the [virtual table] interface to
** pass information into and receive the reply from the [xBestIndex]
** method of a [virtual table module]. The fields under **Inputs** are the
** inputs to xBestIndex and are read-only. xBestIndex inserts its
** results into the **Outputs** fields.
**
** ^(The aConstraint[] array records WHERE clause constraints of the form:
**
** <blockquote>column OP expr</blockquote>
**
** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is
** stored in aConstraint[].op using one of the
** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^
** ^(The index of the column is stored in
** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the
** expr on the right-hand side can be evaluated (and thus the constraint
** is usable) and false if it cannot.)^
**
** ^The optimizer automatically inverts terms of the form "expr OP column"
** and makes other simplifications to the WHERE clause in an attempt to
** get as many WHERE clause terms into the form shown above as possible.
** ^The aConstraint[] array only reports WHERE clause terms that are
** relevant to the particular virtual table being queried.
**
** ^Information about the ORDER BY clause is stored in aOrderBy[].
** ^Each term of aOrderBy records a column of the ORDER BY clause.
**
** The colUsed field indicates which columns of the virtual table may be
** required by the current scan. Virtual table columns are numbered from
** zero in the order in which they appear within the CREATE TABLE statement
** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62),
** the corresponding bit is set within the colUsed mask if the column may be
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
**
** ^If the third parameter (the pointer to the sqlite3_module object) is
** NULL then no new module is created and any existing modules with the
** same name are dropped.
**
** See also: [sqlite3_drop_modules()]
*/
SQLITE_API int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
void *pClientData /* Client data for xCreate/xConnect */
);
SQLITE_API int sqlite3_create_module_v2(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
void *pClientData, /* Client data for xCreate/xConnect */
void(*xDestroy)(void*) /* Module destructor function */
);
/*
** CAPI3REF: Remove Unnecessary Virtual Table Implementations
** METHOD: sqlite3
**
** ^The sqlite3_drop_modules(D,L) interface removes all virtual
** table modules from database connection D except those named on list L.
** The L parameter must be either NULL or a pointer to an array of pointers
** to strings where the array is terminated by a single NULL pointer.
** ^If the L parameter is NULL, then all virtual table modules are removed.
**
** See also: [sqlite3_create_module()]
*/
SQLITE_API int sqlite3_drop_modules(
sqlite3 *db, /* Remove modules from this connection */
const char **azKeep /* Except, do not remove the ones named here */
);
/*
** CAPI3REF: Virtual Table Instance Object
** KEYWORDS: sqlite3_vtab
**
** Every [virtual table module] implementation uses a subclass
** of this object to describe a particular instance
** of the [virtual table]. Each subclass will
** be tailored to the specific needs of the module implementation.
** The purpose of this superclass is to define certain fields that are
** common to all module implementations.
**
** ^Virtual tables methods can set an error message by assigning a
** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should
** take care that any prior string is freed by a call to [sqlite3_free()]
** prior to assigning a new string to zErrMsg. ^After the error message
** is delivered up to the client application, the string will be automatically
** freed by sqlite3_free() and the zErrMsg field will be zeroed.
*/
struct sqlite3_vtab {
const sqlite3_module *pModule; /* The module for this virtual table */
int nRef; /* Number of open cursors */
char *zErrMsg; /* Error message from sqlite3_mprintf() */
/* Virtual table implementations will typically add additional fields */
};
/*
** CAPI3REF: Virtual Table Cursor Object
** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
**
** Every [virtual table module] implementation uses a subclass of the
** following structure to describe cursors that point into the
** [virtual table] and are used
** to loop through the virtual table. Cursors are created using the
** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed
** by the [sqlite3_module.xClose | xClose] method. Cursors are used
** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods
** of the module. Each module implementation will define
** the content of a cursor structure to suit its own needs.
**
** This superclass exists in order to define fields of the cursor that
** are common to all implementations.
*/
struct sqlite3_vtab_cursor {
sqlite3_vtab *pVtab; /* Virtual table of this cursor */
/* Virtual table implementations will typically add additional fields */
};
/*
** CAPI3REF: Declare The Schema Of A Virtual Table
**
** ^The [xCreate] and [xConnect] methods of a
** [virtual table module] call this interface
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
/*
** CAPI3REF: Overload A Function For A Virtual Table
** METHOD: sqlite3
**
** ^(Virtual tables can provide alternative implementations of functions
** using the [xFindFunction] method of the [virtual table module].
** But global versions of those functions
** must exist in order to be overloaded.)^
**
** ^(This API makes sure a global version of a function with a particular
** name and number of parameters exists. If no such function exists
** before this API is called, a new function is created.)^ ^The implementation
** of the new function always causes an exception to be thrown. So
** the new function is not good for anything by itself. Its only
** purpose is to be a placeholder function that can be overloaded
** by a [virtual table].
*/
SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
/*
** CAPI3REF: A Handle To An Open BLOB
** KEYWORDS: {BLOB handle} {BLOB handles}
**
** An instance of this object represents an open BLOB on which
** [sqlite3_blob_open | incremental BLOB I/O] can be performed.
** ^Objects of this type are created by [sqlite3_blob_open()]
** and destroyed by [sqlite3_blob_close()].
** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces
** can be used to read or write small subsections of the BLOB.
** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes.
*/
typedef struct sqlite3_blob sqlite3_blob;
/*
** CAPI3REF: Open A BLOB For Incremental I/O
** METHOD: sqlite3
** CONSTRUCTOR: sqlite3_blob
**
** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
** in row iRow, column zColumn, table zTable in database zDb;
** in other words, the same BLOB that would be selected by:
**
** <pre>
** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
** </pre>)^
**
** ^(Parameter zDb is not the filename that contains the database, but
** of this interface is undefined. ^The requested measurement is written into
** a variable pointed to by the "pOut" parameter.
**
** The "flags" parameter must be passed a mask of flags. At present only
** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX
** is specified, then status information is available for all elements
** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If
** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements
** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of
** the EXPLAIN QUERY PLAN output) are available. Invoking API
** sqlite3_stmt_scanstatus() is equivalent to calling
** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter.
**
** Parameter "idx" identifies the specific query element to retrieve statistics
** for. Query elements are numbered starting from zero. A value of -1 may
** retrieve statistics for the entire query. ^If idx is out of range
** - less than -1 or greater than or equal to the total number of query
** elements used to implement the statement - a non-zero value is returned and
** the variable that pOut points to is unchanged.
**
** See also: [sqlite3_stmt_scanstatus_reset()]
*/
SQLITE_API int sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
void *pOut /* Result written here */
);
SQLITE_API int sqlite3_stmt_scanstatus_v2(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
int flags, /* Mask of flags defined below */
void *pOut /* Result written here */
);
/*
** CAPI3REF: Prepared Statement Scan Status
** KEYWORDS: {scan status flags}
*/
#define SQLITE_SCANSTAT_COMPLEX 0x0001
/*
** CAPI3REF: Zero Scan-Status Counters
** METHOD: sqlite3_stmt
**
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** CAPI3REF: Flush caches to disk mid-transaction
** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface is invoked, any dirty
** pages in the pager-cache that are not currently in use are written out
** to disk. A dirty page may be in use if a database cursor created by an
** active SQL statement is reading from it, or if it is page 1 of a database
** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)]
** interface flushes caches for all schemas - "main", "temp", and
** any [attached] databases.
**
** ^If this function needs to obtain extra database locks before dirty pages
** can be flushed to disk, it does so. ^If those locks cannot be obtained
** immediately and there is a busy-handler callback configured, it is invoked
** in the usual manner. ^If the required lock still cannot be obtained, then
** the database is skipped and an attempt made to flush any dirty pages
** belonging to the next (if any) database. ^If any databases are skipped
** because locks cannot be obtained, but no other error occurs, this
** function returns SQLITE_BUSY.
**
** ^If any other error occurs while flushing dirty pages to disk (for
** example an IO error or out-of-memory condition), then processing is
** abandoned and an SQLite [error code] is returned to the caller immediately.
**
** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK.
**
** ^This function does not set the database handle error code or message
** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions.
*/
SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
** METHOD: sqlite3
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
**
** ^The [sqlite3_preupdate_hook()] interface registers a callback function
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
** on a database table.
** ^At most one preupdate hook may be registered at a time on a single
** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
** the previous setting.
** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()]
** with a NULL pointer as the second parameter.
** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
** the first parameter to callbacks.
**
** ^The preupdate hook only fires for changes to real database tables; the
** preupdate hook is not invoked for changes to [virtual tables] or to
** system tables like sqlite_sequence or sqlite_stat1.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
** ^The third parameter to the preupdate callback is one of the constants
** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the
** kind of update operation that is about to occur.
** ^(The fourth parameter to the preupdate callback is the name of the
** database within the database connection that is being modified. This
** will be "main" for the main database or "temp" for TEMP tables or
** the name given after the AS keyword in the [ATTACH] statement for attached
** databases.)^
** ^The fifth parameter to the preupdate callback is the name of the
** table that is being modified.
**
*/
struct sqlite3_rtree_query_info {
void *pContext; /* pContext from when function registered */
int nParam; /* Number of function parameters */
sqlite3_rtree_dbl *aParam; /* value of function parameters */
void *pUser; /* callback can use this, if desired */
void (*xDelUser)(void*); /* function to free pUser */
sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
unsigned int *anQueue; /* Number of pending entries in the queue */
int nCoord; /* Number of coordinates */
int iLevel; /* Level of current node or entry */
int mxLevel; /* The largest iLevel value in the tree */
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visibility */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
};
/*
** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
*/
#define NOT_WITHIN 0 /* Object completely outside of query region */
#define PARTLY_WITHIN 1 /* Object partially overlaps query region */
#define FULLY_WITHIN 2 /* Object fully contained within query region */
#if 0
} /* end of the 'extern "C"' block */
#endif
#endif /* ifndef _SQLITE3RTREE_H_ */
/******** End of sqlite3rtree.h *********/
/******** Begin file sqlite3session.h *********/
#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION)
#define __SQLITESESSION_H_ 1
/*
** Make sure we can call this stuff from C++.
*/
#if 0
extern "C" {
#endif
/*
** CAPI3REF: Session Object Handle
**
** An instance of this object is a [session] that can be used to
** record changes to a database.
*/
typedef struct sqlite3_session sqlite3_session;
/*
** CAPI3REF: Changeset Iterator Handle
**
** An instance of this object acts as a cursor for iterating
** over the elements of a [changeset] or [patchset].
*/
typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
/*
** CAPI3REF: Create A New Session Object
** CONSTRUCTOR: sqlite3_session
**
** Create a new session object attached to database handle db. If successful,
** a pointer to the new object is written to *ppSession and SQLITE_OK is
** returned. If an error occurs, *ppSession is set to NULL and an SQLite
** error code (e.g. SQLITE_NOMEM) is returned.
**
** It is possible to create multiple session objects attached to a single
** database handle.
**
** Session objects created using this function should be deleted using the
** [sqlite3session_delete()] function before the database handle that they
** are attached to is itself closed. If the database handle is closed before
** the session object is deleted, then the results of calling any session
** module function, including [sqlite3session_delete()] on the session object
** are undefined.
**
** Because the session module uses the [sqlite3_preupdate_hook()] API, it
** is not possible for an application to register a pre-update hook on a
** database handle that has one or more session objects attached. Nor is
** it possible to create a session object attached to a database handle for
** which a pre-update hook is already defined. The results of attempting
** either of these things are undefined.
**
** The session object will be used to create changesets for tables in
** database zDb, where zDb is either "main", or "temp", or the name of an
** attached database. It is not an error if database zDb is not attached
** to the database when the session object is created.
*/
SQLITE_API int sqlite3session_create(
sqlite3 *db, /* Database handle */
const char *zDb, /* Name of db (e.g. "main") */
sqlite3_session **ppSession /* OUT: New session object */
);
/*
** CAPI3REF: Delete A Session Object
** DESTRUCTOR: sqlite3_session
**
** Delete a session object previously allocated using
** [sqlite3session_create()]. Once a session object has been deleted, the
** results of attempting to use pSession with any other session module
** function are undefined.
**
** Session objects must be deleted before the database handle to which they
** are attached is closed. Refer to the documentation for
** [sqlite3session_create()] for details.
*/
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
/*
** CAPI3REF: Configure a Session Object
** METHOD: sqlite3_session
**
SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
** of the flags shown below.
**
** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set.
** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data
** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With
** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored
** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL
** indices.)
*/
#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
#define BTREE_BLOBKEY 2 /* Table has keys only - no data */
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, i64*);
SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int);
SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
/*
** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
** should be one of the following values. The integer values are assigned
** to constants so that the offset of the corresponding field in an
** SQLite database header may be found using the following formula:
**
** offset = 36 + (idx * 4)
**
** For example, the free-page-count field is located at byte offset 36 of
** the database file header. The incr-vacuum-flag field is located at
** byte offset 64 (== 36+4*7).
**
** The BTREE_DATA_VERSION value is not really a value stored in the header.
** It is a read-only number computed by the pager. But we merge it with
** the header value access routines since its access pattern is the same.
** Call it a "virtual meta value".
*/
#define BTREE_FREE_PAGE_COUNT 0
#define BTREE_SCHEMA_VERSION 1
#define BTREE_FILE_FORMAT 2
#define BTREE_DEFAULT_CACHE_SIZE 3
#define BTREE_LARGEST_ROOT_PAGE 4
#define BTREE_TEXT_ENCODING 5
#define BTREE_USER_VERSION 6
#define BTREE_INCR_VACUUM 7
#define BTREE_APPLICATION_ID 8
#define BTREE_DATA_VERSION 15 /* A virtual meta-value */
/*
** Kinds of hints that can be passed into the sqlite3BtreeCursorHint()
** interface.
**
** BTREE_HINT_RANGE (arguments: Expr*, Mem*)
**
** The first argument is an Expr* (which is guaranteed to be constant for
** the lifetime of the cursor) that defines constraints on which rows
** might be fetched with this cursor. The Expr* tree may contain
** TK_REGISTER nodes that refer to values stored in the array of registers
** passed as the second parameter. In other words, if Expr.op==TK_REGISTER
** then the value of the node is the value in Mem[pExpr.iTable]. Any
** TK_COLUMN node in the expression tree refers to the Expr.iColumn-th
** column of the b-tree of the cursor. The Expr tree will not contain
** any function calls nor subqueries nor references to b-trees other than
** the cursor being hinted.
**
** The design of the _RANGE hint is aid b-tree implementations that try
** to prefetch content from remote machines - to provide those
** implementations with limits on what needs to be prefetched and thereby
** reduce network bandwidth.
**
** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by
** standard SQLite. The other hints are provided for extensions that use
** the SQLite parser and code generator but substitute their own storage
** engine.
*/
#define BTREE_HINT_RANGE 0 /* Range constraints on queries */
/*
** Values that may be OR'd together to form the argument to the
** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint():
**
** The BTREE_BULKLOAD flag is set on index cursors when the index is going
** to be filled with content that is already in sorted order.
**
** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or
** OP_SeekLE opcodes for a range search, but where the range of entries
** selected will all have the same key. In other words, the cursor will
** be used only for equality key searches.
**
*/
#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
/*
** Flags passed as the third argument to sqlite3BtreeCursor().
**
** For read-only cursors the wrFlag argument is always zero. For read-write
** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or just
** (BTREE_WRCSR). If the BTREE_FORDELETE bit is set, then the cursor will
** only be used by SQLite for the following:
**
** * to seek to and then delete specific entries, and/or
**
** * to read values that will be used to create keys that other
** BTREE_FORDELETE cursors will seek to and delete.
**
** The BTREE_FORDELETE flag is an optimization hint. It is not used by
** by this, the native b-tree engine of SQLite, but it is available to
** alternative storage engines that might be substituted in place of this
** b-tree system. For alternative storage engines in which a delete of
** the main table row automatically deletes corresponding index rows,
** the FORDELETE flag hint allows those alternative storage engines to
** skip a lot of work. Namely: FORDELETE cursors may treat all SEEK
** and DELETE operations as no-ops, and any READ operation against a
** FORDELETE cursor may return a null row: 0x01 0x00.
*/
#define BTREE_WRCSR 0x00000004 /* read-write cursor */
#define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
Pgno iTable, /* Index of root page */
int wrFlag, /* 1 for writing. 0 for read-only */
struct KeyInfo*, /* First argument to compare function */
BtCursor *pCursor /* Space to write cursor structure */
);
SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(Btree*,BtCursor*);
#endif
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...);
#endif
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
BtCursor*,
i64 intKey,
int bias,
int *pRes
);
SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
BtCursor*,
UnpackedRecord *pUnKey,
int *pRes
);
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*);
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
#define BTREE_APPEND 0x08 /* Insert is likely an append */
#define BTREE_PREFORMAT 0x80 /* Inserted data is a preformated cell */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
**
** Index btrees (used for indexes and also WITHOUT ROWID tables) contain
** an arbitrary key and no data. These btrees have pKey,nKey set to the
** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem
** fields give an array of Mem objects that are a decomposition of the key.
** The nMem field might be zero, indicating that no decomposition is available.
**
** Table btrees (used for rowid tables) contain an integer rowid used as
** the key and passed in the nKey field. The pKey field is zero.
** pData,nData hold the content of the new entry. nZero extra zero bytes
** are appended to the end of the content when constructing the entry.
** The aMem,nMem fields are uninitialized for table btrees.
**
** Field usage summary:
**
** Table BTrees Index Btrees
**
** pKey always NULL encoded key
** nKey the ROWID length of pKey
** pData data not used
** aMem not used decomposed key value
** nMem not used entries in aMem
** nData length of pData not used
** nZero extra zeros after pData not used
**
** This object is used to pass information into sqlite3BtreeInsert(). The
** same information used to be passed as five separate parameters. But placing
** the information into this object helps to keep the interface more
** organized and understandable, and it also helps the resulting code to
** run a little faster by using fewer registers for parameter passing.
*/
struct BtreePayload {
const void *pKey; /* Key content for indexes. NULL for tables */
sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */
const void *pData; /* Data for tables. */
sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */
u16 nMem; /* Number of aMem[] value. Might be zero */
int nData; /* Size of pData. 0 if none. */
int nZero; /* Extra zero data appended after pData,nData */
};
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
int flags, int seekResult);
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags);
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags);
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*);
SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
char *zAff; /* Affinity of the overall IN expression */
int iTable; /* Ephemeral table generated by the subroutine */
int iAddr; /* Subroutine entry address */
int regReturn; /* Register used to hold return address */
};
/*
** A single instruction of the virtual machine has an opcode
** and as many as three operands. The instruction is recorded
** as an instance of the following structure:
*/
struct VdbeOp {
u8 opcode; /* What operation to perform */
signed char p4type; /* One of the P4_xxx constants for p4 */
u16 p5; /* Fifth parameter is an unsigned 16-bit integer */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
int p3; /* The third parameter */
union p4union { /* fourth parameter */
int i; /* Integer value if p4type==P4_INT32 */
void *p; /* Generic pointer */
char *z; /* Pointer to data for string (char array) types */
i64 *pI64; /* Used when p4type is P4_INT64 */
double *pReal; /* Used when p4type is P4_REAL */
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
Mem *pMem; /* Used when p4type is P4_MEM */
VTable *pVtab; /* Used when p4type is P4_VTAB */
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
u32 *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
Table *pTab; /* Used when p4type is P4_TABLE */
SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
} p4;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
char *zComment; /* Comment to improve readability */
#endif
#ifdef SQLITE_VDBE_COVERAGE
u32 iSrcLine; /* Source-code line that generated this opcode
** with flags in the upper 8 bits */
#endif
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
u64 nExec;
u64 nCycle;
#endif
};
typedef struct VdbeOp VdbeOp;
/*
** A sub-routine used to implement a trigger program.
*/
struct SubProgram {
VdbeOp *aOp; /* Array of opcodes for sub-program */
int nOp; /* Elements in aOp[] */
int nMem; /* Number of memory cells required */
int nCsr; /* Number of cursors required */
u8 *aOnce; /* Array of OP_Once flags */
void *token; /* id that may be used to recursive triggers */
SubProgram *pNext; /* Next sub-program already visited */
};
/*
** A smaller version of VdbeOp used for the VdbeAddOpList() function because
** it takes up less space.
*/
struct VdbeOpList {
u8 opcode; /* What operation to perform */
signed char p1; /* First operand */
signed char p2; /* Second parameter (often the jump destination) */
signed char p3; /* Third parameter */
};
typedef struct VdbeOpList VdbeOpList;
/*
** Allowed values of VdbeOp.p4type
*/
#define P4_NOTUSED 0 /* The P4 parameter is not used */
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
#define P4_STATIC (-1) /* Pointer to a static string */
#define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */
#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */
#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */
#define P4_TABLE (-5) /* P4 is a pointer to a Table structure */
/* Above do not own any resources. Must free those below */
#define P4_FREE_IF_LE (-6)
#define P4_DYNAMIC (-6) /* Pointer to memory from sqliteMalloc() */
#define P4_FUNCDEF (-7) /* P4 is a pointer to a FuncDef structure */
#define P4_KEYINFO (-8) /* P4 is a pointer to a KeyInfo structure */
#define P4_EXPR (-9) /* P4 is a pointer to an Expr tree */
#define P4_MEM (-10) /* P4 is a pointer to a Mem* structure */
#define P4_VTAB (-11) /* P4 is a pointer to an sqlite3_vtab structure */
#define P4_REAL (-12) /* P4 is a 64-bit floating point value */
#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
#define P4_SUBRTNSIG (-17) /* P4 is a SubrtnSig pointer */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
#define P5_ConstraintUnique 2
#define P5_ConstraintCheck 3
#define P5_ConstraintFK 4
/*
** The Vdbe.aColName array contains 5n Mem structures, where n is the
** number of columns of data returned by the statement.
*/
#define COLNAME_NAME 0
#define COLNAME_DECLTYPE 1
#define COLNAME_DATABASE 2
#define COLNAME_TABLE 3
#define COLNAME_COLUMN 4
#ifdef SQLITE_ENABLE_COLUMN_METADATA
# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */
#else
#define OP_Sort 35 /* jump */
#define OP_Rewind 36 /* jump0 */
#define OP_IfEmpty 37 /* jump, synopsis: if( empty(P1) ) goto P2 */
#define OP_SorterNext 38 /* jump */
#define OP_Prev 39 /* jump */
#define OP_Next 40 /* jump */
#define OP_IdxLE 41 /* jump, synopsis: key=r[P3@P4] */
#define OP_IdxGT 42 /* jump, synopsis: key=r[P3@P4] */
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
#define OP_IdxLT 45 /* jump, synopsis: key=r[P3@P4] */
#define OP_IdxGE 46 /* jump, synopsis: key=r[P3@P4] */
#define OP_RowSetRead 47 /* jump, synopsis: r[P3]=rowset(P1) */
#define OP_RowSetTest 48 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
#define OP_Program 49 /* jump0 */
#define OP_FkIfZero 50 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
#define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
#define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
#define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
#define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
#define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
#define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
#define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
#define OP_Ge 58 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
#define OP_ElseEq 59 /* jump, same as TK_ESCAPE */
#define OP_IfPos 60 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
#define OP_IfNotZero 61 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
#define OP_DecrJumpZero 62 /* jump, synopsis: if (--r[P1])==0 goto P2 */
#define OP_IncrVacuum 63 /* jump */
#define OP_VNext 64 /* jump */
#define OP_Filter 65 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
#define OP_PureFunc 66 /* synopsis: r[P3]=func(r[P2@NP]) */
#define OP_Function 67 /* synopsis: r[P3]=func(r[P2@NP]) */
#define OP_Return 68
#define OP_EndCoroutine 69
#define OP_HaltIfNull 70 /* synopsis: if r[P3]=null halt */
#define OP_Halt 71
#define OP_Integer 72 /* synopsis: r[P2]=P1 */
#define OP_Int64 73 /* synopsis: r[P2]=P4 */
#define OP_String 74 /* synopsis: r[P2]='P4' (len=P1) */
#define OP_BeginSubrtn 75 /* synopsis: r[P2]=NULL */
#define OP_Null 76 /* synopsis: r[P2..P3]=NULL */
#define OP_SoftNull 77 /* synopsis: r[P1]=NULL */
#define OP_Blob 78 /* synopsis: r[P2]=P4 (len=P1) */
#define OP_Variable 79 /* synopsis: r[P2]=parameter(P1) */
#define OP_Move 80 /* synopsis: r[P2@P3]=r[P1@P3] */
#define OP_Copy 81 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
#define OP_SCopy 82 /* synopsis: r[P2]=r[P1] */
#define OP_IntCopy 83 /* synopsis: r[P2]=r[P1] */
#define OP_FkCheck 84
#define OP_ResultRow 85 /* synopsis: output=r[P1@P2] */
#define OP_CollSeq 86
#define OP_AddImm 87 /* synopsis: r[P1]=r[P1]+P2 */
#define OP_RealAffinity 88
#define OP_Cast 89 /* synopsis: affinity(r[P1]) */
#define OP_Permutation 90
#define OP_Compare 91 /* synopsis: r[P1@P3] <-> r[P2@P3] */
#define OP_IsTrue 92 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
#define OP_ZeroOrNull 93 /* synopsis: r[P2] = 0 OR NULL */
#define OP_Offset 94 /* synopsis: r[P3] = sqlite_offset(P1) */
#define OP_Column 95 /* synopsis: r[P3]=PX cursor P1 column P2 */
#define OP_TypeCheck 96 /* synopsis: typecheck(r[P1@P2]) */
#define OP_Affinity 97 /* synopsis: affinity(r[P1@P2]) */
#define OP_MakeRecord 98 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
#define OP_Count 99 /* synopsis: r[P2]=count() */
#define OP_ReadCookie 100
#define OP_SetCookie 101
#define OP_ReopenIdx 102 /* synopsis: root=P2 iDb=P3 */
#define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
#define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
#define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
#define OP_ShiftRight 106 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
#define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
#define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
#define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
#define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
#define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
#define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
#define OP_OpenRead 113 /* synopsis: root=P2 iDb=P3 */
#define OP_OpenWrite 114 /* synopsis: root=P2 iDb=P3 */
#define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
#define OP_OpenDup 116
#define OP_OpenAutoindex 117 /* synopsis: nColumn=P2 */
#define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */
#define OP_OpenEphemeral 119 /* synopsis: nColumn=P2 */
#define OP_SorterOpen 120
#define OP_SequenceTest 121 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
#define OP_OpenPseudo 122 /* synopsis: P3 columns in r[P2] */
#define OP_Close 123
#define OP_ColumnsUsed 124
#define OP_SeekScan 125 /* synopsis: Scan-ahead up to P1 rows */
#define OP_SeekHit 126 /* synopsis: set P2<=seekHit<=P3 */
#define OP_Sequence 127 /* synopsis: r[P2]=cursor[P1].ctr++ */
#define OP_NewRowid 128 /* synopsis: r[P2]=rowid */
#define OP_Insert 129 /* synopsis: intkey=r[P3] data=r[P2] */
#define OP_RowCell 130
#define OP_Delete 131
#define OP_ResetCount 132
#define OP_SorterCompare 133 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
#define OP_SorterData 134 /* synopsis: r[P2]=data */
#define OP_RowData 135 /* synopsis: r[P2]=data */
#define OP_Rowid 136 /* synopsis: r[P2]=PX rowid of P1 */
#define OP_NullRow 137
#define OP_SeekEnd 138
#define OP_IdxInsert 139 /* synopsis: key=r[P2] */
#define OP_SorterInsert 140 /* synopsis: key=r[P2] */
#define OP_IdxDelete 141 /* synopsis: key=r[P2@P3] */
#define OP_DeferredSeek 142 /* synopsis: Move P3 to P1.rowid if needed */
#define OP_IdxRowid 143 /* synopsis: r[P2]=rowid */
#define OP_FinishSeek 144
#define OP_Destroy 145
#define OP_Clear 146
#define OP_ResetSorter 147
#define OP_CreateBtree 148 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
#define OP_SqlExec 149
#define OP_ParseSchema 150
#define OP_LoadAnalysis 151
#define OP_DropTable 152
#define OP_DropIndex 153
#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
#define OP_DropTrigger 155
#define OP_IntegrityCk 156
#define OP_RowSetAdd 157 /* synopsis: rowset(P1)=r[P2] */
#define OP_Param 158
#define OP_FkCounter 159 /* synopsis: fkctr[P1]+=P2 */
#define OP_MemMax 160 /* synopsis: r[P1]=max(r[P1],r[P2]) */
#define OP_OffsetLimit 161 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
#define OP_AggInverse 162 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
#define OP_AggStep 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */
#define OP_AggStep1 164 /* synopsis: accum=r[P3] step(r[P2@P5]) */
#define OP_AggValue 165 /* synopsis: r[P3]=value N=P2 */
#define OP_AggFinal 166 /* synopsis: accum=r[P1] N=P2 */
#define OP_Expire 167
#define OP_CursorLock 168
#define OP_CursorUnlock 169
#define OP_TableLock 170 /* synopsis: iDb=P1 root=P2 write=P3 */
#define OP_VBegin 171
#define OP_VCreate 172
#define OP_VDestroy 173
#define OP_VOpen 174
#define OP_VCheck 175
#define OP_VInitIn 176 /* synopsis: r[P2]=ValueList(P1,P3) */
#define OP_VColumn 177 /* synopsis: r[P3]=vcolumn(P2) */
#define OP_VRename 178
#define OP_Pagecount 179
#define OP_MaxPgcnt 180
#define OP_ClrSubtype 181 /* synopsis: r[P1].subtype = 0 */
#define OP_GetSubtype 182 /* synopsis: r[P2] = r[P1].subtype */
#define OP_SetSubtype 183 /* synopsis: r[P2].subtype = r[P1] */
#define OP_FilterAdd 184 /* synopsis: filter(P1) += key(P3@P4) */
#define OP_Trace 185
#define OP_CursorHint 186
#define OP_ReleaseReg 187 /* synopsis: release r[P1@P2] mask P3 */
** Macros to compute aCol[] and aFunc[] register numbers.
**
** These macros should not be used prior to the call to
** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg.
** The assert()s that are part of this macro verify that constraint.
*/
#ifndef NDEBUG
#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I))
#define AggInfoFuncReg(A,I) \
(assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I))
#else
#define AggInfoColumnReg(A,I) ((A)->iFirstReg+(I))
#define AggInfoFuncReg(A,I) \
((A)->iFirstReg+(A)->nColumn+(I))
#endif
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater
** than 32767 we have to make it 32-bit. 16-bit is preferred because
** it uses less memory in the Expr object, which is a big memory user
** in systems with lots of prepared statements. And few applications
** need more than about 10 or 20 variables. But some extreme users want
** to have prepared statements with over 32766 variables, and for them
** the option is available (at compile-time).
*/
#if SQLITE_MAX_VARIABLE_NUMBER<32767
typedef i16 ynVar;
#else
typedef int ynVar;
#endif
/*
** Each node of an expression in the parse tree is an instance
** of this structure.
**
** Expr.op is the opcode. The integer parser token codes are reused
** as opcodes here. For example, the parser defines TK_GE to be an integer
** code representing the ">=" operator. This same integer code is reused
** to represent the greater-than-or-equal-to operator in the expression
** tree.
**
** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
** or TK_STRING), then Expr.u.zToken contains the text of the SQL literal. If
** the expression is a variable (TK_VARIABLE), then Expr.u.zToken contains the
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
** then Expr.u.zToken contains the name of the function.
**
** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
** binary operator. Either or both may be NULL.
**
** Expr.x.pList is a list of arguments if the expression is an SQL function,
** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
** Expr.x.pSelect is used if the expression is a sub-select or an expression of
** the form "<lhs> IN (SELECT ...)". If the EP_xIsSelect bit is set in the
** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
** valid.
**
** An expression of the form ID or ID.ID refers to a column in a table.
** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is
** the integer cursor number of a VDBE cursor pointing to that table and
** Expr.iColumn is the column number for the specific column. If the
** expression is used as a result in an aggregate SELECT, then the
** value is also stored in the Expr.iAgg column in the aggregate so that
** it can be accessed after all aggregates are computed.
**
** If the expression is an unbound variable marker (a question mark
** character '?' in the original SQL) then the Expr.iTable holds the index
** number for that variable.
**
** If the expression is a subquery then Expr.iColumn holds an integer
** register number containing the result of the subquery. If the
** subquery gives a constant result, then iTable is -1. If the subquery
** gives a different answer at different times during statement processing
** then iTable is the address of a subroutine that computes the subquery.
**
** If the Expr is of type OP_Column, and the table it is selecting from
** is a disk table or the "old.*" pseudo-table, then pTab points to the
** corresponding table definition.
**
** ALLOCATION NOTES:
**
** Expr objects can use a lot of memory space in database schema. To
** help reduce memory requirements, sometimes an Expr object will be
** truncated. And to reduce the number of memory allocations, sometimes
** two or more Expr objects will be stored in a single memory allocation,
** together with Expr.u.zToken strings.
**
** If the EP_Reduced and EP_TokenOnly flags are set when
** an Expr object is truncated. When EP_Reduced is set, then all
** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
** are contained within the same memory allocation. Note, however, that
** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately
** allocated, regardless of whether or not EP_Reduced is set.
*/
struct Expr {
u8 op; /* Operation performed by this node */
char affExpr; /* affinity, or RAISE type */
u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth
** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
#ifdef SQLITE_DEBUG
u8 vvaFlags; /* Verification flags. */
#endif
u32 flags; /* Various flags. EP_* See below */
union {
char *zToken; /* Token value. Zero terminated and dequoted */
int iValue; /* Non-negative integer value if EP_IntValue */
} u;
/* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
** access them will result in a segfault or malfunction.
*********************************************************************/
Expr *pLeft; /* Left subnode */
Expr *pRight; /* Right subnode */
union {
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
} x;
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
** access them will result in a segfault or malfunction.
*********************************************************************/
#if SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Height of the tree headed by this node */
#endif
int iTable; /* TK_COLUMN: cursor number of table holding column
** TK_REGISTER: register number
** TK_TRIGGER: 1 -> new, 0 -> old
** EP_Unlikely: 134217728 times likelihood
** TK_IN: ephemeral table holding RHS
** TK_SELECT_COLUMN: Number of columns on the LHS
** TK_SELECT: 1st register of result vector */
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
** TK_VARIABLE: variable number (always >= 1).
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
union {
int iJoin; /* If EP_OuterON or EP_InnerON, the right table */
int iOfst; /* else: start of token from start of statement */
} w;
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
** for a column of an index on an expression */
Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
int nReg; /* TK_NULLS: Number of registers to NULL out */
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
int iAddr; /* Subroutine entry address */
int regReturn; /* Register used to hold return address */
} sub;
} y;
};
/* The following are the meanings of bits in the Expr.flags field.
** Value restrictions:
**
** EP_Agg == NC_HasAgg == SF_HasAgg
** EP_Win == NC_HasWin
*/
#define EP_OuterON 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_InnerON 0x000002 /* Originates in ON/USING of an inner join */
#define EP_Distinct 0x000004 /* Aggregate function with DISTINCT keyword */
#define EP_HasFunc 0x000008 /* Contains one or more functions of any kind */
#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
#define EP_FixedCol 0x000020 /* TK_Column with a known fixed value */
#define EP_VarSelect 0x000040 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000080 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000100 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000200 /* Tree contains a TK_COLLATE operator */
#define EP_Commuted 0x000400 /* Comparison operator has been commuted */
#define EP_IntValue 0x000800 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x001000 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x002000 /* Operator does not contribute to affinity */
#define EP_Reduced 0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */
#define EP_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_FullSize 0x020000 /* Expr structure must remain full sized */
#define EP_IfNullRow 0x040000 /* The TK_IF_NULL_ROW opcode */
#define EP_Unlikely 0x080000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x200000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery 0x400000 /* Tree contains a TK_SELECT operator */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
**
** The jointype starts out showing the join type between the current table
** and the next table on the list. The parser builds the list this way.
** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
** jointype expresses the join between the table and the previous table.
**
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
**
** Aggressive use of "union" helps keep the size of the object small. This
** has been shown to boost performance, in addition to saving memory.
** Access to union elements is gated by the following rules which should
** always be checked, either by an if-statement or by an assert().
**
** Field Only access if this is true
** --------------- -----------------------------------
** u1.zIndexedBy fg.isIndexedBy
** u1.pFuncArg fg.isTabFunc
** u1.nRow !fg.isTabFunc && !fg.isIndexedBy
**
** u2.pIBIndex fg.isIndexedBy
** u2.pCteUse fg.isCte
**
** u3.pOn !fg.isUsing
** u3.pUsing fg.isUsing
**
** u4.zDatabase !fg.fixedSchema && !fg.isSubquery
** u4.pSchema fg.fixedSchema
** u4.pSubq fg.isSubquery
**
** See also the sqlite3SrcListDelete() routine for assert() statements that
** check invariants on the fields of this object, especially the flags
** inside the fg struct.
*/
struct SrcItem {
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pSTab; /* Table object for zName. Mnemonic: Srcitem-TABle */
struct {
u8 jointype; /* Type of join between this table and the previous */
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
unsigned isSubquery :1; /* True if this term is a subquery */
unsigned isTabFunc :1; /* True if table-valued-function syntax */
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned isMaterialized:1; /* This is a materialized view */
unsigned viaCoroutine :1; /* Implemented as a co-routine */
unsigned isRecursive :1; /* True for recursive reference in WITH */
unsigned fromDDL :1; /* Comes from sqlite_schema */
unsigned isCte :1; /* This is a CTE */
unsigned notCte :1; /* This item may not match a CTE */
unsigned isUsing :1; /* u3.pUsing is valid */
unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
unsigned rowidUsed :1; /* The ROWID of this table is referenced */
unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */
unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */
unsigned fromExists :1; /* Comes from WHERE EXISTS(...) */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */
union {
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
ExprList *pFuncArg; /* Arguments to table-valued-function */
u32 nRow; /* Number of rows in a VALUES clause */
} u1;
union {
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */
} u2;
union {
Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
} u3;
union {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
Subquery *pSubq; /* Description of a subquery */
} u4;
};
/*
** The OnOrUsing object represents either an ON clause or a USING clause.
** It can never be both at the same time, but it can be neither.
*/
struct OnOrUsing {
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
};
/*
** This object represents one or more tables that are the source of
** content for an SQL statement. For example, a single SrcList object
** is used to hold the FROM clause of a SELECT statement. SrcList also
** represents the target tables for DELETE, INSERT, and UPDATE statements.
**
*/
struct SrcList {
int nSrc; /* Number of tables or subqueries in the FROM clause */
u32 nAlloc; /* Number of entries allocated in a[] below */
SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */
};
/* Size (in bytes) of a SrcList object that can hold as many as N
** SrcItem objects. */
#define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem))
/* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a
** special case of SZ_SRCITEM(1) that comes up often. */
#define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem))
/*
** Permitted values of the SrcList.a.jointype field
*/
#define JT_INNER 0x01 /* Any kind of inner or cross join */
#define JT_CROSS 0x02 /* Explicit use of the CROSS keyword */
#define JT_NATURAL 0x04 /* True for a "natural" join */
#define JT_LEFT 0x08 /* Left outer join */
#define JT_RIGHT 0x10 /* Right outer join */
#define JT_OUTER 0x20 /* The "OUTER" keyword is present */
** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER
** NC_HasWin == EP_Win
**
*/
#define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */
#define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */
#define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */
#define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */
#define NC_HasAgg 0x000010 /* One or more aggregate functions seen */
#define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */
#define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
#define NC_Subquery 0x000040 /* A subquery has been seen */
#define NC_UEList 0x000080 /* True if uNC.pEList is used */
#define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
/* 0x002000 // available for reuse */
#define NC_AllowWin 0x004000 /* Window functions are allowed here */
#define NC_HasWin 0x008000 /* One or more window functions seen */
#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
/*
** An instance of the following object describes a single ON CONFLICT
** clause in an upsert.
**
** The pUpsertTarget field is only set if the ON CONFLICT clause includes
** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the
** conflict-target clause.) The pUpsertTargetWhere is the optional
** WHERE clause used to identify partial unique indexes.
**
** pUpsertSet is the list of column=expr terms of the UPDATE statement.
** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The
** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the
** WHERE clause is omitted.
*/
struct Upsert {
ExprList *pUpsertTarget; /* Optional description of conflict target */
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
u8 isDup; /* True if 2nd or later with same pUpsertIdx */
/* Above this point is the parse tree for the ON CONFLICT clauses.
** The next group of fields stores intermediate data. */
void *pToFree; /* Free memory when deleting the Upsert object */
/* All fields above are owned by the Upsert object and must be freed
** when the Upsert is destroyed. The fields below are used to transfer
** information from the INSERT processing down into the UPDATE processing
** while generating code. The fields below are owned by the INSERT
** statement and will be freed by INSERT processing. */
Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */
SrcList *pUpsertSrc; /* Table to be updated */
int regData; /* First register holding array of VALUES */
int iDataCur; /* Index of the data cursor */
int iIdxCur; /* Index of the first index cursor */
};
/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**
** See the header comment on the computeLimitRegisters() routine for a
** detailed description of the meaning of the iLimit and iOffset fields.
**
** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
** These addresses must be stored so that we can go back and fill in
** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor
** the number of columns in P2 can be computed at the same time
** as the OP_OpenEphm instruction is coded because not
** enough information about the compound query is known at that point.
** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
** sequences for the ORDER BY clause.
*/
struct Select {
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
LogEst nSelectRow; /* Estimated number of result rows */
u32 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
u32 selId; /* Unique identifier number for this SELECT */
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
ExprList *pEList; /* The fields of the result */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
Expr *pHaving; /* The HAVING clause */
ExprList *pOrderBy; /* The ORDER BY clause */
Select *pPrior; /* Prior select in a compound select statement */
Select *pNext; /* Next select to the left in a compound */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
With *pWith; /* WITH clause attached to this select. Or NULL. */
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin; /* List of window functions */
Window *pWinDefn; /* List of named window definitions */
#endif
};
/*
** Allowed values for Select.selFlags. The "SF" prefix stands for
** "Select Flag".
**
** Value constraints (all checked via assert())
** SF_HasAgg == NC_HasAgg
** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER
** SF_FixedLimit == WHERE_USE_LIMIT
*/
#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
#define SF_All 0x0000002 /* Includes the ALL keyword */
#define SF_Resolved 0x0000004 /* Identifiers have been resolved */
#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
#define SF_HasAgg 0x0000010 /* Contains aggregate functions */
#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */
#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
#define SF_View 0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
#define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
#define SF_Correlated 0x20000000 /* True if references the outer context */
#define SF_OnToWhere 0x40000000 /* One or more ON clauses moved to WHERE */
/* True if SrcItem X is a subquery that has SF_NestedFrom */
#define IsNestedFrom(X) \
((X)->fg.isSubquery && \
((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0)
/*
** The results of a SELECT can be distributed in several ways, as defined
** by one of the following macros. The "SRT" prefix means "SELECT Result
** Type".
**
** SRT_Union Store results as a key in a temporary index
** identified by pDest->iSDParm.
**
** SRT_Except Remove results from the temporary index pDest->iSDParm.
**
** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
** set is not empty.
**
** SRT_Discard Throw the results away. This is used by SELECT
** statements within triggers whose only purpose is
** the side-effects of functions.
**
** SRT_Output Generate a row of output (using the OP_ResultRow
** opcode) for each row in the result set.
**
** SRT_Mem Only valid if the result is a single column.
** Store the first column of the first result row
** in register pDest->iSDParm then abandon the rest
** of the query. This destination implies "LIMIT 1".
**
** SRT_Set The result must be a single column. Store each
** row of result as the key in table pDest->iSDParm.
** Apply the affinity pDest->affSdst before storing
** results. if pDest->iSDParm2 is positive, then it is
** a register holding a Bloom filter for the IN operator
** that should be populated in addition to the
** pDest->iSDParm table. This SRT is used to
** implement "IN (SELECT ...)".
**
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
** the result there. The cursor is left open after
** returning. This is like SRT_Table except that
** this destination uses OP_OpenEphemeral to create
** the table first.
**
** SRT_Coroutine Generate a co-routine that returns a new row of
** results each time it is invoked. The entry point
** of the co-routine is stored in register pDest->iSDParm
** and the result row is stored in pDest->nDest registers
** starting with pDest->iSdst.
**
** SRT_Table Store results in temporary table pDest->iSDParm.
** SRT_Fifo This is like SRT_EphemTab except that the table
** is assumed to already be open. SRT_Fifo has
** the additional property of being able to ignore
** the ORDER BY clause.
**
** SRT_DistFifo Store results in a temporary table pDest->iSDParm.
** But also use temporary table pDest->iSDParm+1 as
** a record of all prior results and ignore any duplicate
** rows. Name means: "Distinct Fifo".
**
** SRT_Queue Store results in priority queue pDest->iSDParm (really
** an index). Append a sequence number so that all entries
** are distinct.
**
** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
** the same record has never been stored before. The
** index at pDest->iSDParm+1 hold all prior stores.
**
** SRT_Upfrom Store results in the temporary table already opened by
** pDest->iSDParm. If (pDest->iSDParm<0), then the temp
** table is an intkey table - in this case the first
** column returned by the SELECT is used as the integer
** key. If (pDest->iSDParm>0), then the table is an index
** table. (pDest->iSDParm) is the number of key columns in
** each index record in this case.
*/
#define SRT_Union 1 /* Store result as keys in an index */
#define SRT_Except 2 /* Remove result from a UNION index */
#define SRT_Exists 3 /* Store 1 if the result is not empty */
#define SRT_Discard 4 /* Do not save the results anywhere */
#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
/* The DISTINCT clause is ignored for all of the above. Not that
** IgnorableDistinct() implies IgnorableOrderby() */
#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
#define SRT_Queue 7 /* Store result in an queue */
#define SRT_Fifo 8 /* Store result as data with an automatic rowid */
/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
#define SRT_Output 9 /* Output each row of result */
#define SRT_Mem 10 /* Store result in a memory cell */
#define SRT_Set 11 /* Store results as keys in an index */
#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine 13 /* Generate a single row of result */
#define SRT_Table 14 /* Store result as data with an automatic rowid */
int regCtr; /* Memory register holding the rowid counter */
};
/*
** At least one instance of the following structure is created for each
** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
** statement. All such objects are stored in the linked list headed at
** Parse.pTriggerPrg and deleted once statement compilation has been
** completed.
**
** A Vdbe sub-program that implements the body and WHEN clause of trigger
** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of
** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable.
** The Parse.pTriggerPrg list never contains two entries with the same
** values for both pTrigger and orconf.
**
** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
** accessed (or set to 0 for triggers fired as a result of INSERT
** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
** a mask of new.* columns used by the program.
*/
struct TriggerPrg {
Trigger *pTrigger; /* Trigger this program was coded from */
TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */
SubProgram *pProgram; /* Program implementing pTrigger/orconf */
int orconf; /* Default ON CONFLICT policy */
u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */
};
/*
** The yDbMask datatype for the bitmask of all attached databases.
*/
#if SQLITE_MAX_ATTACHED>30
typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8];
# define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0)
# define DbMaskZero(M) memset((M),0,sizeof(M))
# define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7))
# define DbMaskAllZero(M) sqlite3DbMaskAllZero(M)
# define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0)
#else
typedef unsigned int yDbMask;
# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0)
# define DbMaskZero(M) ((M)=0)
# define DbMaskSet(M,I) ((M)|=(((yDbMask)1)<<(I)))
# define DbMaskAllZero(M) ((M)==0)
# define DbMaskNonZero(M) ((M)!=0)
#endif
/*
** For each index X that has as one of its arguments either an expression
** or the name of a virtual generated column, and if X is in scope such that
** the value of the expression can simply be read from the index, then
** there is an instance of this object on the Parse.pIdxExpr list.
**
** During code generation, while generating code to evaluate expressions,
** this list is consulted and if a matching expression is found, the value
** is read from the index rather than being recomputed.
*/
struct IndexedExpr {
Expr *pExpr; /* The expression contained in the index */
int iDataCur; /* The data cursor associated with the index */
int iIdxCur; /* The index cursor */
int iIdxCol; /* The index column that contains value of pExpr */
u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */
u8 aff; /* Affinity of the pExpr expression */
IndexedExpr *pIENext; /* Next in a list of all indexed expressions */
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
const char *zIdxName; /* Name of index, used only for bytecode comments */
#endif
};
/*
** An instance of the ParseCleanup object specifies an operation that
** should be performed after parsing to deallocation resources obtained
** during the parse and which are no longer needed.
*/
struct ParseCleanup {
ParseCleanup *pNext; /* Next cleanup task */
void *pPtr; /* Pointer to object to deallocate */
void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */
};
/*
** An SQL parser context. A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
**
** The structure is divided into two parts. When the parser and code
** generate call themselves recursively, the first part of the structure
** is constant but the second part is reset at the beginning and end of
** each recursion.
**
** The nTableLock and aTableLock variables are only used if the shared-cache
** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are
** used to store the set of table-locks required by the statement being
** compiled. Function sqlite3TableLock() is used to add entries to the
** list.
*/
struct Parse {
sqlite3 *db; /* The main database structure */
char *zErrMsg; /* An error message */
Vdbe *pVdbe; /* An engine for executing database bytecode */
int rc; /* Return code from execution */
LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u8 nested; /* Number of nested calls to the parser/code generator */
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */
u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
u8 bReturning; /* Coding a RETURNING trigger */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
#endif
#ifdef SQLITE_DEBUG
u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */
u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER)
** and ALTER TABLE ADD COLUMN. */
#endif
bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
bft bHasWith :1; /* True if statement contains WITH */
bft okConstFactor :1; /* OK to factor out constants */
bft checkSchema :1; /* Causes schema cookie check after an error */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */
int nLabel; /* The *negative* of the number of labels used */
int nLabelAlloc; /* Number of slots in aLabel */
int *aLabel; /* Space to hold the labels */
ExprList *pConstExpr;/* Constant expressions */
IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */
IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
int nMaxArg; /* Max args to xUpdate and xFilter vtab methods */
int nSelect; /* Number of SELECT stmts. Counter for Select.selId */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
/**************************************************************************
** Fields above must be initialized to zero. The fields that follow,
** down to the beginning of the recursive section, do not need to be
** initialized as they will be set before being used. The boundary is
** determined by offsetof(Parse,aTempReg).
**************************************************************************/
int aTempReg[8]; /* Holding area for temporary registers */
Parse *pOuterParse; /* Outer Parse object when nested */
Token sNameToken; /* Token with unqualified schema object name */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
union {
struct { /* These fields available when isCreate is true */
int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
int regRowid; /* Register holding rowid of CREATE TABLE entry */
int regRoot; /* Register holding root page for new objects */
Token constraintName; /* Name of the constraint currently being parsed */
} cr;
struct { /* These fields available to all other statements */
Returning *pReturning; /* The RETURNING clause */
} d;
} u1;
/************************************************************************
** Above is constant between recursions. Below is reset before and after
** each recursion. The boundary between these two regions is determined
** using offsetof(Parse,sLastToken) so the sLastToken field must be the
** first field in the recursive region.
************************************************************************/
Token sLastToken; /* The last token parsed */
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
#define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg))
#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
/*
** Return true if currently inside an sqlite3_declare_vtab() call.
*/
#ifdef SQLITE_OMIT_VIRTUALTABLE
#define IN_DECLARE_VTAB 0
#else
#define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB)
#endif
#if defined(SQLITE_OMIT_ALTERTABLE)
#define IN_RENAME_OBJECT 0
#else
#define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME)
#endif
#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)
#define IN_SPECIAL_PARSE 0
#else
#define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL)
#endif
/*
** An instance of the following structure can be declared on a stack and used
** to save the Parse.zAuthContext value so that it can be restored later.
*/
struct AuthContext {
const char *zAuthContext; /* Put saved Parse.zAuthContext here */
Parse *pParse; /* The Parse structure */
};
/*
** Bitfield flags for P5 value in various opcodes.
**
** Value constraints (enforced via assert()):
** OPFLAG_LENGTHARG == SQLITE_FUNC_LENGTH
** OPFLAG_TYPEOFARG == SQLITE_FUNC_TYPEOF
** OPFLAG_BULKCSR == BTREE_BULKLOAD
** OPFLAG_SEEKEQ == BTREE_SEEK_EQ
** OPFLAG_FORDELETE == BTREE_FORDELETE
** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION
** OPFLAG_AUXDELETE == BTREE_AUXDELETE
*/
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
/* Also used in P2 (not P5) of OP_Delete */
#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */
/*
** Each trigger present in the database schema is stored as an instance of
** struct Trigger.
**
** Pointers to instances of struct Trigger are stored in two ways.
** 1. In the "trigHash" hash table (part of the sqlite3* that represents the
** database). This allows Trigger structures to be retrieved by name.
** 2. All triggers associated with a single table form a linked list, using the
** pNext member of struct Trigger. A pointer to the first element of the
** linked list is stored as the "pTrigger" member of the associated
** struct Table.
**
** The "step_list" member points to the first element of a linked list
** containing the SQL statements specified as the trigger program.
*/
struct Trigger {
char *zName; /* The name of the trigger */
char *table; /* The table or view to which the trigger applies */
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
u8 bReturning; /* This trigger implements a RETURNING clause */
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
the <column-list> is stored here */
Schema *pSchema; /* Schema containing the trigger */
Schema *pTabSchema; /* Schema containing the table */
TriggerStep *step_list; /* Link list of trigger program steps */
Trigger *pNext; /* Next trigger associated with the table */
};
/*
** A trigger is either a BEFORE or an AFTER trigger. The following constants
** determine which.
**
** If there are multiple triggers, you might of some BEFORE and some AFTER.
** In that cases, the constants below can be ORed together.
*/
#define TRIGGER_BEFORE 1
#define TRIGGER_AFTER 2
/*
** An instance of struct TriggerStep is used to store a single SQL statement
** that is a part of a trigger-program.
**
** Instances of struct TriggerStep are stored in a singly linked list (linked
** using the "pNext" member) referenced by the "step_list" member of the
** associated struct Trigger instance. The first element of the linked list is
** the first step of the trigger-program.
**
** The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
** "SELECT" statement. The meanings of the other members is determined by the
** value of "op" as follows:
**
** (op == TK_INSERT)
** orconf -> stores the ON CONFLICT algorithm
** pSelect -> The content to be inserted - either a SELECT statement or
/* The following callback (if not NULL) is invoked on every VDBE branch
** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
*/
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
#ifndef SQLITE_OMIT_DESERIALIZE
sqlite3_int64 mxMemdbSize; /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW
** feature is disabled. 0 if rowids can
** occur in views. */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
/* vvvv--- must be last ---vvv */
#ifdef SQLITE_DEBUG
sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */
#endif
};
/*
** This macro is used inside of assert() statements to indicate that
** the assert is only valid on a well-formed database. Instead of:
**
** assert( X );
**
** One writes:
**
** assert( X || CORRUPT_DB );
**
** CORRUPT_DB is true during normal operation. CORRUPT_DB does not indicate
** that the database is definitely corrupt, only that it might be corrupt.
** For most test cases, CORRUPT_DB is set to false using a special
** sqlite3_test_control(). This enables assert() statements to prove
** things that are always true for well-formed databases.
*/
#define CORRUPT_DB (sqlite3Config.neverCorrupt==0)
/*
** Context pointer passed down through the tree-walk.
*/
struct Walker {
Parse *pParse; /* Parser context. */
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
int walkerDepth; /* Number of subqueries */
u16 eCode; /* A small processing code */
u16 mWFlags; /* Use-dependent flags */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int n; /* A counter */
int iCur; /* A cursor number */
SrcList *pSrcList; /* FROM clause */
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */
int *aiCol; /* array of column indexes */
struct IdxCover *pIdxCover; /* Check for index coverage */
ExprList *pGroupBy; /* GROUP BY clause */
Select *pSelect; /* HAVING to WHERE clause ctx */
struct WindowRewrite *pRewrite; /* Window rewrite context */
struct WhereConst *pConst; /* WHERE clause constants */
struct RenameCtx *pRename; /* RENAME COLUMN context */
struct Table *pTab; /* Table of generated column */
struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */
SrcItem *pSrcItem; /* A single FROM clause item */
DbFixer *pFix; /* See sqlite3FixSelect() */
Mem *aMem; /* See sqlite3BtreeCursorHint() */
struct CheckOnCtx *pCheckOnCtx; /* See selectCheckOnClauses() */
} u;
};
/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.
*/
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
Walker w; /* Walker object */
Schema *pSchema; /* Fix items to this schema */
u8 bTemp; /* True for TEMP schema entries */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
};
/* Forward declarations */
SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
SQLITE_PRIVATE int sqlite3WalkExprNN(Walker*, Expr*);
SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*);
SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*);
SQLITE_PRIVATE void sqlite3WalkWinDefnDummyCallback(Walker*,Select*);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
#ifndef SQLITE_OMIT_CTE
SQLITE_PRIVATE void sqlite3SelectPopWith(Walker*, Select*);
#else
# define sqlite3SelectPopWith 0
#endif
/*
** Return code from the parse-tree walking primitives and their
char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */
};
/* The size (in bytes) of a DbClientData object that can has a name
** that is N bytes long, including the zero-terminator. */
#define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N))
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
** data structures on sqlite3DebugPrintf() using a tree-like view.
*/
struct TreeView {
int iLevel; /* Which level of the tree we are on */
u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */
};
#endif /* SQLITE_DEBUG */
/*
** This object is used in various ways, most (but not all) related to window
** functions.
**
** (1) A single instance of this structure is attached to the
** the Expr.y.pWin field for each window function in an expression tree.
** This object holds the information contained in the OVER clause,
** plus additional fields used during code generation.
**
** (2) All window functions in a single SELECT form a linked-list
** attached to Select.pWin. The Window.pFunc and Window.pExpr
** fields point back to the expression that is the window function.
**
** (3) The terms of the WINDOW clause of a SELECT are instances of this
** object on a linked list attached to Select.pWinDefn.
**
** (4) For an aggregate function with a FILTER clause, an instance
** of this object is stored in Expr.y.pWin with eFrmType set to
** TK_FILTER. In this case the only field used is Window.pFilter.
**
** The uses (1) and (2) are really the same Window object that just happens
** to be accessible in two different ways. Use case (3) are separate objects.
*/
struct Window {
char *zName; /* Name of window (may be NULL) */
char *zBase; /* Name of base window for chaining (may be NULL) */
ExprList *pPartition; /* PARTITION BY clause */
ExprList *pOrderBy; /* ORDER BY clause */
u8 eFrmType; /* TK_RANGE, TK_GROUPS, TK_ROWS, or 0 */
u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
u8 bImplicitFrame; /* True if frame was implicitly specified */
u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */
Expr *pStart; /* Expression for "<expr> PRECEDING" */
Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
Window **ppThis; /* Pointer to this object in Select.pWin list */
Window *pNextWin; /* Next window function belonging to this SELECT */
Expr *pFilter; /* The FILTER expression */
FuncDef *pWFunc; /* The function */
int iEphCsr; /* Partition buffer or Peer buffer */
int regAccum; /* Accumulator */
int regResult; /* Interim result */
int csrApp; /* Function cursor (used by min/max) */
int regApp; /* Function register (also used by min/max) */
int regPart; /* Array of registers for PARTITION BY values */
Expr *pOwner; /* Expression object this window is attached to */
int nBufferCol; /* Number of columns in buffer table */
int iArgCol; /* Offset of first argument for this function */
int regOne; /* Register containing constant value 1 */
int regStartRowid;
int regEndRowid;
u8 bExprArgs; /* Defer evaluation of window function arguments
** due to the SQLITE_SUBTYPE flag */
};
SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow);
SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal);
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*);
SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window*);
SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p);
SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*);
SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin);
SQLITE_PRIVATE int sqlite3WindowCompare(const Parse*, const Window*, const Window*, int);
SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*);
SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*);
SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
SQLITE_PRIVATE void sqlite3WindowFunctions(void);
SQLITE_PRIVATE void sqlite3WindowChain(Parse*, Window*, Window*);
SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
#else
# define sqlite3WindowDelete(a,b)
# define sqlite3WindowFunctions()
# define sqlite3WindowAttach(a,b,c)
#endif
/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
#define SQLITE_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
} \
}
/*
** The SQLITE_*_BKPT macros are substitutes for the error codes with
** the same name but without the _BKPT suffix. These macros invoke
** routines that report the line-number on which the error originated
** using sqlite3_log(). The routines also provide a convenient place
** to set a debugger breakpoint.
*/
SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType);
SQLITE_PRIVATE int sqlite3CorruptError(int);
SQLITE_PRIVATE int sqlite3MisuseError(int);
SQLITE_PRIVATE int sqlite3CantopenError(int);
#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
** 2003 September 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.
**
*************************************************************************
** This is the header file for information that is private to the
** VDBE. This information used to all be at the top of the single
** source code file "vdbe.c". When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
*/
#ifndef SQLITE_VDBEINT_H
#define SQLITE_VDBEINT_H
/*
** The maximum number of times that a statement will try to reparse
** itself before giving up and returning SQLITE_SCHEMA.
*/
#ifndef SQLITE_MAX_SCHEMA_RETRY
# define SQLITE_MAX_SCHEMA_RETRY 50
#endif
/*
** VDBE_DISPLAY_P4 is true or false depending on whether or not the
** "explain" P4 display logic is enabled.
*/
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \
|| defined(SQLITE_ENABLE_BYTECODE_VTAB)
# define VDBE_DISPLAY_P4 1
#else
# define VDBE_DISPLAY_P4 0
#endif
/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine. Each instruction is an instance
** of the following structure.
*/
typedef struct VdbeOp Op;
/*
** Boolean values
*/
typedef unsigned Bool;
/* Opaque type used by code in vdbesort.c */
typedef struct VdbeSorter VdbeSorter;
/* Elements of the linked list at Vdbe.pAuxData */
typedef struct AuxData AuxData;
/* A cache of large TEXT or BLOB values in a VdbeCursor */
typedef struct VdbeTxtBlbCache VdbeTxtBlbCache;
/* Types of VDBE cursors */
#define CURTYPE_BTREE 0
#define CURTYPE_SORTER 1
#define CURTYPE_VTAB 2
#define CURTYPE_PSEUDO 3
/*
** A VdbeCursor is an superclass (a wrapper) for various cursor objects:
**
** * A b-tree cursor
** - In the main database or in an ephemeral database
** - On either an index or a table
** * A sorter
** * A virtual table
** * A one-row "pseudotable" stored in a single register
*/
typedef struct VdbeCursor VdbeCursor;
struct VdbeCursor {
u8 eCurType; /* One of the CURTYPE_* values above */
i8 iDb; /* Index of cursor database in db->aDb[] */
u8 nullRow; /* True if pointing to a row with no data */
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
u8 isTable; /* True for rowid tables. False for indexes */
#ifdef SQLITE_DEBUG
u8 seekOp; /* Most recent seek operation on this cursor */
u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
#endif
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */
Bool colCache:1; /* pCache pointer is initialized and non-NULL */
u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
union { /* pBtx for isEphermeral. pAltMap otherwise */
Btree *pBtx; /* Separate file holding temporary table */
u32 *aAltMap; /* Mapping from table to index column numbers */
} ub;
i64 seqCount; /* Sequence counter */
/* Cached OP_Column parse information is only valid if cacheStatus matches
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that
** the cache is out of date. */
u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0
** if there have been no prior seeks on the cursor. */
/* seekResult does not distinguish between "no seeks have ever occurred
** on this cursor" and "the most recent seek was an exact match".
** For CURTYPE_PSEUDO, seekResult is the register holding the record */
/* When a new VdbeCursor is allocated, only the fields above are zeroed.
** The fields that follow are uninitialized, and must be individually
** initialized prior to first use. */
VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
union {
BtCursor *pCursor; /* CURTYPE_BTREE or _PSEUDO. Btree cursor */
sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */
VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */
} uc;
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
u32 iHdrOffset; /* Offset to next unparsed byte of the header */
Pgno pgnoRoot; /* Root page of the open btree cursor */
i16 nField; /* Number of fields in the header */
u16 nHdrParsed; /* Number of header fields parsed so far */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
u32 *aOffset; /* Pointer to aType[nField] */
const u8 *aRow; /* Data for the current row, if all on one page */
u32 payloadSize; /* Total number of bytes in the record */
u32 szRow; /* Byte available in aRow */
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
u64 maskUsed; /* Mask of columns used by this cursor */
#endif
VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
/* Space is allocated for aType to hold at least 2*nField+1 entries:
** nField slots for aType[] and nField+1 array slots for aOffset[] */
u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */
};
/*
** The size (in bytes) of a VdbeCursor object that has an nField value of N
** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple
** of 8.
*/
#define SZ_VDBECURSOR(N) \
(ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64))
/* Return true if P is a null-only cursor
*/
#define IsNullCursor(P) \
((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)
/*
** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
*/
#define CACHE_STALE 0
/*
** Large TEXT or BLOB values can be slow to load, so we want to avoid
** loading them more than once. For that reason, large TEXT and BLOB values
** can be stored in a cache defined by this object, and attached to the
** VdbeCursor using the pCache field.
*/
struct VdbeTxtBlbCache {
char *pCValue; /* A RCStr buffer to hold the value */
i64 iOffset; /* File offset of the row being cached */
int iCol; /* Column for which the cache is valid */
u32 cacheStatus; /* Vdbe.cacheCtr value */
u32 colCacheCtr; /* Column cache counter */
};
/*
** When a sub-program is executed (OP_Program), a structure of this type
** is allocated to store the current value of the program counter, as
** well as the current memory cell array and various other frame specific
** values stored in the Vdbe struct. When the sub-program is finished,
** these values are copied back to the Vdbe from the VdbeFrame structure,
** restoring the state of the VM to as it was before the sub-program
** began executing.
**
** The memory for a VdbeFrame object is allocated and managed by a memory
** cell in the parent (calling) frame. When the memory cell is deleted or
** overwritten, the VdbeFrame object is not freed immediately. Instead, it
** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
** this instead of deleting the VdbeFrame immediately is to avoid recursive
** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
** child frame are released.
**
** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
** set to NULL if the currently executing frame is the main program.
*/
typedef struct VdbeFrame VdbeFrame;
struct VdbeFrame {
Vdbe *v; /* VM this frame belongs to */
VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
Op *aOp; /* Program instructions for parent frame */
Mem *aMem; /* Array of memory cells for parent frame */
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
u8 *aOnce; /* Bitmask used by OP_Once */
void *token; /* Copy of SubProgram.token */
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
AuxData *pAuxData; /* Linked list of auxdata allocations */
#if SQLITE_DEBUG
u32 iFrameMagic; /* magic number for sanity checking */
#endif
int nCursor; /* Number of entries in apCsr */
int pc; /* Program Counter in parent (calling) frame */
int nOp; /* Size of aOp array */
int nMem; /* Number of entries in aMem */
int nChildMem; /* Number of memory cells for child frame */
int nChildCsr; /* Number of cursors for child frame */
i64 nChange; /* Statement changes (Vdbe.nChange) */
i64 nDbChange; /* Value of db->nChange */
};
/* Magic number for sanity checking on VdbeFrame objects */
#define SQLITE_FRAME_MAGIC 0x879fb71e
/*
** Return a pointer to the array of registers allocated for use
** by a VdbeFrame.
*/
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
/*
** Internally, the vdbe manipulates nearly all SQL values as Mem
** structures. Each Mem struct may cache multiple representations (string,
** integer etc.) of the same value.
*/
struct sqlite3_value {
union MemValue {
double r; /* Real value used when MEM_Real is set in flags */
i64 i; /* Integer value used when MEM_Int is set in flags */
int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */
const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
} u;
char *z; /* String or BLOB value */
int n; /* Number of characters in string value, excluding '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
u8 eSubtype; /* Subtype for this value */
/* ShallowCopy only needs to copy the information above */
sqlite3 *db; /* The associated database connection */
int szMalloc; /* Size of the zMalloc allocation */
u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */
char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
u16 mScopyFlags; /* flags value immediately after the shallow copy */
u8 bScopy; /* The pScopyFrom of some other Mem *might* point here */
#endif
};
/*
** Size of struct Mem not including the Mem.zMalloc member or anything that
** follows.
*/
#define MEMCELLSIZE offsetof(Mem,db)
/* One or more of the following flags are set to indicate the
** representations of the value stored in the Mem struct.
**
** * MEM_Null An SQL NULL value
**
** * MEM_Null|MEM_Zero An SQL NULL with the virtual table
** UPDATE no-change flag set
**
** * MEM_Null|MEM_Term| An SQL NULL, but also contains a
** MEM_Subtype pointer accessible using
/* The ScanStatus object holds a single value for the
** sqlite3_stmt_scanstatus() interface.
**
** aAddrRange[]:
** This array is used by ScanStatus elements associated with EQP
** notes that make an SQLITE_SCANSTAT_NCYCLE value available. It is
** an array of up to 3 ranges of VM addresses for which the Vdbe.anCycle[]
** values should be summed to calculate the NCYCLE value. Each pair of
** integer addresses is a start and end address (both inclusive) for a range
** instructions. A start value of 0 indicates an empty range.
*/
typedef struct ScanStatus ScanStatus;
struct ScanStatus {
int addrExplain; /* OP_Explain for loop */
int aAddrRange[6];
int addrLoop; /* Address of "loops" counter */
int addrVisit; /* Address of "rows visited" counter */
int iSelectID; /* The "Select-ID" for this loop */
LogEst nEst; /* Estimated output rows per loop */
char *zName; /* Name of table or index */
};
/* The DblquoteStr object holds the text of a double-quoted
** string for a prepared statement. A linked list of these objects
** is constructed during statement parsing and is held on Vdbe.pDblStr.
** When computing a normalized SQL statement for an SQL statement, that
** list is consulted for each double-quoted identifier to see if the
** identifier should really be a string literal.
*/
typedef struct DblquoteStr DblquoteStr;
struct DblquoteStr {
DblquoteStr *pNextStr; /* Next string literal in the list */
char z[8]; /* Dequoted value for the string */
};
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
**
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
** is really a pointer to an instance of this structure.
*/
struct Vdbe {
sqlite3 *db; /* The database connection that owns this statement */
Vdbe **ppVPrev,*pVNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
u32 cacheCtr; /* VdbeCursor row cache generation counter */
int pc; /* The program counter */
int rc; /* Value to return */
i64 nChange; /* Number of db changes made since last reset */
int iStatement; /* Statement number (or 0 if has no opened stmt) */
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
Mem *aMem; /* The memory locations */
Mem **apArg; /* Arguments xUpdate and xFilter vtab methods */
VdbeCursor **apCsr; /* One element of this array for each open cursor */
Mem *aVar; /* Values for the OP_Variable opcode. */
/* When allocating a new Vdbe object, all of the fields below should be
** initialized to zero or NULL */
Op *aOp; /* Space to hold the virtual machine's program */
int nOp; /* Number of instructions in the program */
int nOpAlloc; /* Slots allocated for aOp[] */
Mem *aColName; /* Column names to return */
Mem *pResultRow; /* Current output row */
char *zErrMsg; /* Error message written here */
VList *pVList; /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
#ifdef SQLITE_DEBUG
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
int napArg; /* Size of the apArg[] array */
#endif
u16 nResColumn; /* Number of columns in one row of the result set */
u16 nResAlloc; /* Column slots allocated to aColName[] */
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
u8 eVdbeState; /* On of the VDBE_*_STATE values */
bft expired:2; /* 1: recompile VM immediately 2: when convenient */
bft explain:2; /* 0: normal, 1: EXPLAIN, 2: EXPLAIN QUERY PLAN */
bft changeCntOn:1; /* True to update the change-counter */
bft usesStmtJournal:1; /* True if uses a statement journal */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
bft haveEqpOps:1; /* Bytecode supports EXPLAIN QUERY PLAN */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_ENABLE_NORMALIZE
char *zNormSql; /* Normalization of the associated SQL statement */
DblquoteStr *pDblStr; /* List of double-quoted string literals */
#endif
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
int nFrame; /* Number of frames in pFrame list */
u32 expmask; /* Binding to these vars invalidates VM */
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
AuxData *pAuxData; /* Linked list of auxdata allocations */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int nScan; /* Entries in aScan[] */
ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */
#endif
};
/*
** The following are allowed values for Vdbe.eVdbeState
*/
#define VDBE_INIT_STATE 0 /* Prepared statement under construction */
#define VDBE_READY_STATE 1 /* Ready to run but not yet started */
#define VDBE_RUN_STATE 2 /* Run in progress */
/* 35 */ "Sort" OpHelp(""),
/* 36 */ "Rewind" OpHelp(""),
/* 37 */ "IfEmpty" OpHelp("if( empty(P1) ) goto P2"),
/* 38 */ "SorterNext" OpHelp(""),
/* 39 */ "Prev" OpHelp(""),
/* 40 */ "Next" OpHelp(""),
/* 41 */ "IdxLE" OpHelp("key=r[P3@P4]"),
/* 42 */ "IdxGT" OpHelp("key=r[P3@P4]"),
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
/* 45 */ "IdxLT" OpHelp("key=r[P3@P4]"),
/* 46 */ "IdxGE" OpHelp("key=r[P3@P4]"),
/* 47 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
/* 48 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
/* 49 */ "Program" OpHelp(""),
/* 50 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
/* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
/* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
/* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
/* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
/* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
/* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
/* 57 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
/* 58 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
/* 59 */ "ElseEq" OpHelp(""),
/* 60 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
/* 61 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
/* 62 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
/* 63 */ "IncrVacuum" OpHelp(""),
/* 64 */ "VNext" OpHelp(""),
/* 65 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
/* 66 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
/* 67 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
/* 68 */ "Return" OpHelp(""),
/* 69 */ "EndCoroutine" OpHelp(""),
/* 70 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
/* 71 */ "Halt" OpHelp(""),
/* 72 */ "Integer" OpHelp("r[P2]=P1"),
/* 73 */ "Int64" OpHelp("r[P2]=P4"),
/* 74 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
/* 75 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
/* 76 */ "Null" OpHelp("r[P2..P3]=NULL"),
/* 77 */ "SoftNull" OpHelp("r[P1]=NULL"),
/* 78 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
/* 79 */ "Variable" OpHelp("r[P2]=parameter(P1)"),
/* 80 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
/* 81 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
/* 82 */ "SCopy" OpHelp("r[P2]=r[P1]"),
/* 83 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
/* 84 */ "FkCheck" OpHelp(""),
/* 85 */ "ResultRow" OpHelp("output=r[P1@P2]"),
/* 86 */ "CollSeq" OpHelp(""),
/* 87 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
/* 88 */ "RealAffinity" OpHelp(""),
/* 89 */ "Cast" OpHelp("affinity(r[P1])"),
/* 90 */ "Permutation" OpHelp(""),
/* 91 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
/* 92 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
/* 93 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
/* 94 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
/* 95 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"),
/* 96 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
/* 97 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
/* 98 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
/* 99 */ "Count" OpHelp("r[P2]=count()"),
/* 100 */ "ReadCookie" OpHelp(""),
/* 101 */ "SetCookie" OpHelp(""),
/* 102 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
/* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
/* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
/* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
/* 106 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
/* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
/* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
/* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
/* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
/* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
/* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
/* 113 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
/* 114 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
/* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
/* 116 */ "OpenDup" OpHelp(""),
/* 117 */ "OpenAutoindex" OpHelp("nColumn=P2"),
/* 118 */ "String8" OpHelp("r[P2]='P4'"),
/* 119 */ "OpenEphemeral" OpHelp("nColumn=P2"),
/* 120 */ "SorterOpen" OpHelp(""),
/* 121 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
/* 122 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
/* 123 */ "Close" OpHelp(""),
/* 124 */ "ColumnsUsed" OpHelp(""),
/* 125 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
/* 126 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
/* 127 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
/* 128 */ "NewRowid" OpHelp("r[P2]=rowid"),
/* 129 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
/* 130 */ "RowCell" OpHelp(""),
/* 131 */ "Delete" OpHelp(""),
/* 132 */ "ResetCount" OpHelp(""),
/* 133 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
/* 134 */ "SorterData" OpHelp("r[P2]=data"),
/* 135 */ "RowData" OpHelp("r[P2]=data"),
/* 136 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
/* 137 */ "NullRow" OpHelp(""),
/* 138 */ "SeekEnd" OpHelp(""),
/* 139 */ "IdxInsert" OpHelp("key=r[P2]"),
/* 140 */ "SorterInsert" OpHelp("key=r[P2]"),
/* 141 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
/* 142 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
/* 143 */ "IdxRowid" OpHelp("r[P2]=rowid"),
/* 144 */ "FinishSeek" OpHelp(""),
/* 145 */ "Destroy" OpHelp(""),
/* 146 */ "Clear" OpHelp(""),
/* 147 */ "ResetSorter" OpHelp(""),
/* 148 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
/* 149 */ "SqlExec" OpHelp(""),
/* 150 */ "ParseSchema" OpHelp(""),
/* 151 */ "LoadAnalysis" OpHelp(""),
/* 152 */ "DropTable" OpHelp(""),
/* 153 */ "DropIndex" OpHelp(""),
/* 154 */ "Real" OpHelp("r[P2]=P4"),
/* 155 */ "DropTrigger" OpHelp(""),
/* 156 */ "IntegrityCk" OpHelp(""),
/* 157 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
/* 158 */ "Param" OpHelp(""),
/* 159 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
/* 160 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
/* 161 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
/* 162 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
/* 163 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
/* 164 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
/* 165 */ "AggValue" OpHelp("r[P3]=value N=P2"),
/* 166 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
/* 167 */ "Expire" OpHelp(""),
/* 168 */ "CursorLock" OpHelp(""),
/* 169 */ "CursorUnlock" OpHelp(""),
/* 170 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
/* 171 */ "VBegin" OpHelp(""),
/* 172 */ "VCreate" OpHelp(""),
/* 173 */ "VDestroy" OpHelp(""),
/* 174 */ "VOpen" OpHelp(""),
/* 175 */ "VCheck" OpHelp(""),
/* 176 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
/* 177 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
/* 178 */ "VRename" OpHelp(""),
/* 179 */ "Pagecount" OpHelp(""),
/* 180 */ "MaxPgcnt" OpHelp(""),
/* 181 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
/* 182 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"),
/* 183 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"),
/* 184 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
/* 185 */ "Trace" OpHelp(""),
/* 186 */ "CursorHint" OpHelp(""),
/* 187 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
if( 0==osSetEndOfFile(h) ){
rc = SQLITE_IOERR_TRUNCATE;
}
}
return rc;
}
/*
** Determine the size in bytes of the file opened by the handle passed as
** the first argument.
*/
static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){
int rc = SQLITE_OK;
#if SQLITE_OS_WINRT
FILE_STANDARD_INFO info;
BOOL b;
b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info));
if( b ){
*pnByte = info.EndOfFile.QuadPart;
}else{
rc = SQLITE_IOERR_FSTAT;
}
#else
DWORD upperBits = 0;
DWORD lowerBits = 0;
assert( pnByte );
lowerBits = osGetFileSize(h, &upperBits);
*pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits;
if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){
rc = SQLITE_IOERR_FSTAT;
}
#endif
return rc;
}
/*
** Close the handle passed as the only argument.
*/
static void winHandleClose(HANDLE h){
if( h!=INVALID_HANDLE_VALUE ){
osCloseHandle(h);
}
}
#endif /* #ifndef SQLITE_OMIT_WAL */
/*
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
winFile *pFile = (winFile*)id; /* File handle object */
int rc = SQLITE_OK; /* Return code for this function */
DWORD lastErrno;
#if SQLITE_MAX_MMAP_SIZE>0
sqlite3_int64 oldMmapSize;
if( pFile->nFetchOut>0 ){
/* File truncation is a no-op if there are outstanding memory mapped
** pages. This is because truncating the file means temporarily unmapping
** the file, and that might delete memory out from under existing cursors.
**
** This can result in incremental vacuum not truncating the file,
** if there is an active read cursor when the incremental vacuum occurs.
** No real harm comes of this - the database file is not corrupted,
** though some folks might complain that the file is bigger than it
** needs to be.
**
** The only feasible work-around is to defer the truncation until after
** all references to memory-mapped content are closed. That is doable,
** but involves adding a few branches in the common write code path which
** could slow down normal operations slightly. Hence, we have decided for
** now to simply make transactions a no-op if there are pending reads. We
** can maybe revisit this decision in the future.
*/
return SQLITE_OK;
}
#endif
assert( pFile );
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));
/* If the user has configured a chunk-size for this file, truncate the
** file so that it consists of an integer number of chunks (i.e. the
** actual file size after the operation may be larger than the requested
** size).
*/
if( pFile->szChunk>0 ){
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
}
#if SQLITE_MAX_MMAP_SIZE>0
if( pFile->pMapRegion ){
oldMmapSize = pFile->mmapSize;
}else{
oldMmapSize = 0;
}
winUnmapfile(pFile);
#endif
/* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
if( winSeekFile(pFile, nByte) ){
rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
"winTruncate1", pFile->zPath);
}else if( 0==osSetEndOfFile(pFile->h) &&
((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
pFile->lastErrno = lastErrno;
rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
"winTruncate2", pFile->zPath);
}
#if SQLITE_MAX_MMAP_SIZE>0
if( rc==SQLITE_OK && oldMmapSize>0 ){
if( oldMmapSize>nByte ){
winMapfile(pFile, -1);
}else{
winMapfile(pFile, oldMmapSize);
}
}
#endif
OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
# define SQLITE_FILE_HEADER "SQLite format 3"
#endif
/*
** Page type flags. An ORed combination of these flags appear as the
** first byte of on-disk image of every BTree page.
*/
#define PTF_INTKEY 0x01
#define PTF_ZERODATA 0x02
#define PTF_LEAFDATA 0x04
#define PTF_LEAF 0x08
/*
** An instance of this object stores information about each a single database
** page that has been loaded into memory. The information in this object
** is derived from the raw on-disk page content.
**
** As each database page is loaded into memory, the pager allocates an
** instance of this object and zeros the first 8 bytes. (This is the
** "extra" information associated with each page of the pager.)
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
u8 intKey; /* True if table b-trees. False for index b-trees */
u8 intKeyLeaf; /* True if the leaf of an intKey table */
Pgno pgno; /* Page number for this page */
/* Only the first 8 bytes (above) are zeroed by pager.c when a new page
** is allocated. All fields that follow must be initialized before use */
u8 leaf; /* True if a leaf page */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
u8 max1bytePayload; /* min(maxLocal,127) */
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
int nFree; /* Number of free bytes on the page. -1 for unknown */
u16 nCell; /* Number of cells on this page, local and ovfl */
u16 maskPage; /* Mask for page offset */
u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th
** non-overflow cell */
u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
BtShared *pBt; /* Pointer to BtShared that this page is part of */
u8 *aData; /* Pointer to disk image of the page data */
u8 *aDataEnd; /* One byte past the end of the entire page - not just
** the usable space, the entire page. Used to prevent
** corruption-induced buffer overflow. */
u8 *aCellIdx; /* The cell index area */
u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */
DbPage *pDbPage; /* Pager page handle */
u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */
void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */
};
/*
** A linked list of the following structures is stored at BtShared.pLock.
** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
** is opened on the table with root page BtShared.iTable. Locks are removed
** from this list when a transaction is committed or rolled back, or when
** a btree handle is closed.
*/
struct BtLock {
Btree *pBtree; /* Btree handle holding this lock */
Pgno iTable; /* Root page of table */
u8 eLock; /* READ_LOCK or WRITE_LOCK */
BtLock *pNext; /* Next in BtShared.pLock list */
};
/* Candidate values for BtLock.eLock */
#define READ_LOCK 1
#define WRITE_LOCK 2
/* A Btree handle
**
** A database connection contains a pointer to an instance of
** this object for every database file that it has open. This structure
** is opaque to the database connection. The database connection cannot
** see the internals of this structure and only deals with pointers to
** this structure.
**
** For some database files, the same underlying database cache might be
** shared between multiple connections. In that case, each connection
** has it own instance of this object. But each instance of this object
** points to the same BtShared object. The database cache and the
** schema associated with the database file are all contained within
** the BtShared object.
**
** All fields in this structure are accessed under sqlite3.mutex.
** The pBt pointer itself may not be changed while there exists cursors
** in the referenced BtShared that point back to this Btree since those
** cursors have to go through this Btree to find their BtShared and
** they often do so without holding sqlite3.mutex.
*/
struct Btree {
sqlite3 *db; /* The database connection holding this btree */
BtShared *pBt; /* Sharable content of this btree */
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
u8 sharable; /* True if we can share pBt with another db */
u8 locked; /* True if db currently has pBt locked */
u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
int nBackup; /* Number of backup operations reading this btree */
u32 iBDataVersion; /* Combines with pBt->pPager->iDataVersion */
Btree *pNext; /* List of other sharable Btrees from the same db */
Btree *pPrev; /* Back pointer of the same list */
#ifdef SQLITE_DEBUG
u64 nSeek; /* Calls to sqlite3BtreeMovetoUnpacked() */
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
BtLock lock; /* Object used to lock page 1 */
#endif
};
/*
** Btree.inTrans may take one of the following values.
**
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
** but any number may have active read transactions.
**
** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and
** SQLITE_TXN_WRITE
*/
#define TRANS_NONE 0
#define TRANS_READ 1
#define TRANS_WRITE 2
#if TRANS_NONE!=SQLITE_TXN_NONE
# error wrong numeric code for no-transaction
#endif
#if TRANS_READ!=SQLITE_TXN_READ
# error wrong numeric code for read-transaction
#endif
#if TRANS_WRITE!=SQLITE_TXN_WRITE
# error wrong numeric code for write-transaction
#endif
/*
** An instance of this object represents a single database file.
**
** A single database file can be in use at the same time by two
** or more database connections. When two or more connections are
** sharing the same database file, each connection has it own
** private Btree object for the file and each of those Btrees points
** to this one BtShared object. BtShared.nRef is the number of
** connections currently sharing this database file.
**
** Fields in this structure are accessed under the BtShared.mutex
** mutex, except for nRef and pNext which are accessed under the
** global SQLITE_MUTEX_STATIC_MAIN mutex. The pPager field
** may not be modified once it is initially set as long as nRef>0.
** The pSchema field may be set once under BtShared.mutex and
** thereafter is unchanged as long as nRef>0.
**
** isPending:
**
** If a BtShared client fails to obtain a write-lock on a database
** table (because there exists one or more read-locks on the table),
** the shared-cache enters 'pending-lock' state and isPending is
** set to true.
**
** The shared-cache leaves the 'pending lock' state when either of
** the following occur:
**
** 1) The current writer (BtShared.pWriter) concludes its transaction, OR
** 2) The number of locks held by other connections drops to zero.
**
** while in the 'pending-lock' state, no connection may start a new
** transaction.
**
** This feature is included to help prevent writer-starvation.
*/
struct BtShared {
Pager *pPager; /* The page cache */
sqlite3 *db; /* Database connection currently using this Btree */
BtCursor *pCursor; /* A list of all open cursors */
MemPage *pPage1; /* First page of the database */
u8 openFlags; /* Flags to sqlite3BtreeOpen() */
#ifndef SQLITE_OMIT_AUTOVACUUM
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */
u8 bDoTruncate; /* True to truncate db on commit */
#endif
u8 inTransaction; /* Transaction state */
u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
u8 nReserveWanted; /* Desired number of extra bytes per page */
u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
u32 pageSize; /* Total number of bytes on a page */
u32 usableSize; /* Number of usable bytes on each page */
int nTransaction; /* Number of open transactions (read + write) */
u32 nPage; /* Number of pages in the database */
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */
Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */
#ifndef SQLITE_OMIT_SHARED_CACHE
int nRef; /* Number of references to this structure */
BtShared *pNext; /* Next on a list of sharable BtShared structs */
BtLock *pLock; /* List of locks held on this shared-btree struct */
Btree *pWriter; /* Btree with currently open write transaction */
#endif
u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
int nPreformatSize; /* Size of last cell written by TransferRow() */
};
/*
** Allowed values for BtShared.btsFlags
*/
#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
#define BTS_OVERWRITE 0x0008 /* Overwrite deleted content with zeros */
#define BTS_FAST_SECURE 0x000c /* Combination of the previous two */
#define BTS_INITIALLY_EMPTY 0x0010 /* Database was empty at trans start */
#define BTS_NO_WAL 0x0020 /* Do not open write-ahead-log files */
#define BTS_EXCLUSIVE 0x0040 /* pWriter has an exclusive lock */
#define BTS_PENDING 0x0080 /* Waiting for read-locks to clear */
/*
** An instance of the following structure is used to hold information
** about a cell. The parseCellPtr() function fills in this structure
** based on information extract from the raw disk page.
*/
struct CellInfo {
i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
u8 *pPayload; /* Pointer to the start of payload */
u32 nPayload; /* Bytes of payload */
u16 nLocal; /* Amount of payload held locally, not on overflow */
u16 nSize; /* Size of the cell content on the main b-tree page */
};
/*
** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
** this will be declared corrupt. This value is calculated based on a
** maximum database size of 2^31 pages a minimum fanout of 2 for a
** root-node and 3 for all other internal nodes.
**
** If a tree that appears to be taller than this is encountered, it is
** assumed that the database is corrupt.
*/
#define BTCURSOR_MAX_DEPTH 20
/*
** Maximum amount of storage local to a database page, regardless of
** page size.
*/
#define BT_MAX_LOCAL 65501 /* 65536 - 35 */
/*
** A cursor is a pointer to a particular entry within a particular
** b-tree within a database file.
**
** The entry is identified by its MemPage and the index in
** MemPage.aCell[] of the entry.
**
** A single database file can be shared by two more database connections,
** but cursors cannot be shared. Each cursor is associated with a
** particular database connection identified BtCursor.pBtree.db.
**
** Fields in this structure are accessed under the BtShared.mutex
** found at self->pBt->mutex.
**
** skipNext meaning:
** The meaning of skipNext depends on the value of eState:
**
** eState Meaning of skipNext
** VALID skipNext is meaningless and is ignored
** INVALID skipNext is meaningless and is ignored
** SKIPNEXT sqlite3BtreeNext() is a no-op if skipNext>0 and
** sqlite3BtreePrevious() is no-op if skipNext<0.
** REQUIRESEEK restoreCursorPosition() restores the cursor to
** eState=SKIPNEXT if skipNext!=0
** FAULT skipNext holds the cursor fault error code.
*/
struct BtCursor {
u8 eState; /* One of the CURSOR_XXX constants (see below) */
u8 curFlags; /* zero or more BTCF_* flags defined below */
u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
u8 hints; /* As configured by CursorSetHints() */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
** Error code if eState==CURSOR_FAULT */
Btree *pBtree; /* The Btree to which this cursor belongs */
Pgno *aOverflow; /* Cache of overflow page locations */
void *pKey; /* Saved key that was cursor last known position */
/* All fields above are zeroed when the cursor is allocated. See
** sqlite3BtreeCursorZero(). Fields that follow must be manually
** initialized. */
#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */
BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext; /* Forms a linked list of all cursors */
CellInfo info; /* A parse of the cell we are pointing at */
i64 nKey; /* Size of pKey, or last integer key */
Pgno pgnoRoot; /* The root page of this tree */
i8 iPage; /* Index of current page in apPage */
u8 curIntKey; /* Value of apPage[0]->intKey */
u16 ix; /* Current index for apPage[iPage] */
u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */
struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */
MemPage *pPage; /* Current page */
MemPage *apPage[BTCURSOR_MAX_DEPTH-1]; /* Stack of parents of current page */
};
/*
** Legal values for BtCursor.curFlags
*/
#define BTCF_WriteFlag 0x01 /* True if a write cursor */
#define BTCF_ValidNKey 0x02 /* True if info.nKey is valid */
#define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */
#define BTCF_AtLast 0x08 /* Cursor is pointing to the last entry */
#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */
#define BTCF_Pinned 0x40 /* Cursor is busy and cannot be moved */
/*
** Potential values for BtCursor.eState.
**
** CURSOR_INVALID:
** Cursor does not point to a valid entry. This can happen (for example)
** because the table is empty or because BtreeCursorFirst() has not been
** called.
**
** CURSOR_VALID:
** Cursor points to a valid entry. getPayload() etc. may be called.
**
** CURSOR_SKIPNEXT:
** Cursor is valid except that the Cursor.skipNext field is non-zero
** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
** operation should be a no-op.
**
** CURSOR_REQUIRESEEK:
** The table that this cursor was opened on still exists, but has been
** modified since the cursor was last used. The cursor position is saved
** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
** this state, restoreCursorPosition() can be called to attempt to
** seek the cursor to the saved position.
**
** CURSOR_FAULT:
** An unrecoverable error (an I/O error or a malloc failure) has occurred
** on a different connection that shares the BtShared cache with this
** cursor. The error has left the cache in an inconsistent state.
** Do nothing else with this cursor. Any attempt to use the cursor
** should return the error code stored in BtCursor.skipNext
*/
#define CURSOR_VALID 0
#define CURSOR_INVALID 1
#define CURSOR_SKIPNEXT 2
#define CURSOR_REQUIRESEEK 3
#define CURSOR_FAULT 4
/*
** The database page the PENDING_BYTE occupies. This page is never used.
*/
#define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/((pBt)->pageSize))+1))
/*
** These macros define the location of the pointer-map entry for a
** database page. The first argument to each is the number of usable
** bytes on each page of the database (often 1024). The second is the
** page number to look up in the pointer map.
**
** PTRMAP_PAGENO returns the database page number of the pointer-map
** page that stores the required pointer. PTRMAP_PTROFFSET returns
** the offset of the requested map entry.
**
** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
** this test.
*/
#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno)
#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1))
#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno))
/*
** The pointer map is a lookup table that identifies the parent page for
** each child page in the database file. The parent page is the page that
** contains a pointer to the child. Every page in the database contains
** 0 or 1 parent pages. (In this context 'database page' refers
** to any page that is not part of the pointer map itself.) Each pointer map
** entry consists of a single byte 'type' and a 4 byte parent page number.
** The PTRMAP_XXX identifiers below are the valid types.
**
** The purpose of the pointer map is to facility moving pages from one
** position in the file to another as part of autovacuum. When a page
** is moved, the pointer in its parent must be updated to point to the
** new location. The pointer map is used to locate the parent page quickly.
**
** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
** used in this case.
**
** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
** is not used in this case.
**
** PTRMAP_OVERFLOW1: The database page is the first page in a list of
** overflow pages. The page number identifies the page that
** contains the cell with a pointer to this overflow page.
**
** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
** overflow pages. The page-number identifies the previous
** page in the overflow page list.
**
return 0;
}
}
return 1;
}
#endif /* NDEBUG */
#ifndef NDEBUG
/*
** Return true if the correct mutexes are held for accessing the
** db->aDb[iDb].pSchema structure. The mutexes required for schema
** access are:
**
** (1) The mutex on db
** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt.
**
** If pSchema is not NULL, then iDb is computed from pSchema and
** db using sqlite3SchemaToIndex().
*/
SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
Btree *p;
assert( db!=0 );
if( db->pVfs==0 && db->nDb==0 ) return 1;
if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
assert( iDb>=0 && iDb<db->nDb );
if( !sqlite3_mutex_held(db->mutex) ) return 0;
if( iDb==1 ) return 1;
p = db->aDb[iDb].pBt;
assert( p!=0 );
return p->sharable==0 || p->locked==1;
}
#endif /* NDEBUG */
#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */
/*
** The following are special cases for mutex enter routines for use
** in single threaded applications that use shared cache. Except for
** these two routines, all mutex operations are no-ops in that case and
** are null #defines in btree.h.
**
** If shared cache is disabled, then all btree mutex routines, including
** the ones below, are no-ops and are null #defines in btree.h.
*/
SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){
p->pBt->db = p->db;
}
SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
int i;
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
if( p ){
p->pBt->db = p->db;
}
}
}
#endif /* if SQLITE_THREADSAFE */
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Enter a mutex on a Btree given a cursor owned by that Btree.
**
** These entry points are used by incremental I/O only. Enter() is required
** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not
** the build is threadsafe. Leave() is only required by threadsafe builds.
*/
SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){
sqlite3BtreeEnter(pCur->pBtree);
}
# if SQLITE_THREADSAFE
SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
sqlite3BtreeLeave(pCur->pBtree);
}
# endif
#endif /* ifndef SQLITE_OMIT_INCRBLOB */
#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */
/************** End of btmutex.c *********************************************/
/************** Begin file btree.c *******************************************/
/*
** 2004 April 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.
**
*************************************************************************
** This file implements an external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
/* #include "btreeInt.h" */
/*
** The header string that appears at the beginning of every
** SQLite database.
*/
static const char zMagicHeader[] = SQLITE_FILE_HEADER;
/*
** Set this global variable to 1 to enable tracing using the TRACE
** macro.
*/
#if 0
int sqlite3BtreeTrace=1; /* True to enable tracing */
# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);}
#else
# define TRACE(X)
#endif
/*
** Extract a 2-byte big-endian integer from an array of unsigned bytes.
** But if the value is zero, make it 65536.
**
** This routine is used to extract the "offset to cell content area" value
** from the header of a btree page. If the page size is 65536 and the page
** is empty, the offset should be 65536, but the 2-byte value stores zero.
*/
if( isIndex && (!pSchema || (pSchema->schemaFlags&DB_SchemaLoaded)==0) ){
return 1;
}
/* Figure out the root-page that the lock should be held on. For table
** b-trees, this is just the root page of the b-tree being read or
** written. For index b-trees, it is the root page of the associated
** table. */
if( isIndex ){
HashElem *p;
int bSeen = 0;
for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
Index *pIdx = (Index *)sqliteHashData(p);
if( pIdx->tnum==iRoot ){
if( bSeen ){
/* Two or more indexes share the same root page. There must
** be imposter tables. So just return true. The assert is not
** useful in that case. */
return 1;
}
iTab = pIdx->pTable->tnum;
bSeen = 1;
}
}
}else{
iTab = iRoot;
}
SHARED_LOCK_TRACE(pBtree->pBt,"hasLock",iRoot,eLockType);
/* Search for the required lock. Either a write-lock on root-page iTab, a
** write-lock on the schema table, or (if the client is reading) a
** read-lock on iTab will suffice. Return 1 if any of these are found. */
for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){
if( pLock->pBtree==pBtree
&& (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1))
&& pLock->eLock>=eLockType
){
return 1;
}
}
/* Failed to find the required lock. */
return 0;
}
#endif /* SQLITE_DEBUG */
#ifdef SQLITE_DEBUG
/*
**** This function may be used as part of assert() statements only. ****
**
** Return true if it would be illegal for pBtree to write into the
** table or index rooted at iRoot because other shared connections are
** simultaneously reading that same table or index.
**
** It is illegal for pBtree to write if some other Btree object that
** shares the same BtShared object is currently reading or writing
** the iRoot table. Except, if the other Btree object has the
** read-uncommitted flag set, then it is OK for the other object to
** have a read cursor.
**
** For example, before writing to any part of the table or index
** rooted at page iRoot, one should call:
**
** assert( !hasReadConflicts(pBtree, iRoot) );
*/
static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
BtCursor *p;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( p->pgnoRoot==iRoot
&& p->pBtree!=pBtree
&& 0==(p->pBtree->db->flags & SQLITE_ReadUncommit)
){
return 1;
}
}
return 0;
}
#endif /* #ifdef SQLITE_DEBUG */
/*
** Query to see if Btree handle p may obtain a lock of type eLock
** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
** SQLITE_OK if the lock may be obtained (by calling
** setSharedCacheTableLock()), or SQLITE_LOCKED if not.
*/
static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
BtShared *pBt = p->pBt;
BtLock *pIter;
assert( sqlite3BtreeHoldsMutex(p) );
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 );
/* If requesting a write-lock, then the Btree must have an open write
** transaction on this file. And, obviously, for this to be so there
** must be an open write transaction on the file itself.
*/
assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) );
assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE );
/* This routine is a no-op if the shared-cache is not enabled */
if( !p->sharable ){
return SQLITE_OK;
}
/* If some other connection is holding an exclusive lock, the
** requested lock may not be obtained.
*/
if( pBt->pWriter!=p && (pBt->btsFlags & BTS_EXCLUSIVE)!=0 ){
sqlite3ConnectionBlocked(p->db, pBt->pWriter->db);
return SQLITE_LOCKED_SHAREDCACHE;
}
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
/* The condition (pIter->eLock!=eLock) in the following if(...)
** statement is a simplification of:
**
** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
BtLock *pLock = *ppIter;
assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree );
assert( pLock->pBtree->inTrans>=pLock->eLock );
if( pLock->pBtree==p ){
*ppIter = pLock->pNext;
assert( pLock->iTable!=1 || pLock==&p->lock );
if( pLock->iTable!=1 ){
sqlite3_free(pLock);
}
}else{
ppIter = &pLock->pNext;
}
}
assert( (pBt->btsFlags & BTS_PENDING)==0 || pBt->pWriter );
if( pBt->pWriter==p ){
pBt->pWriter = 0;
pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
}else if( pBt->nTransaction==2 ){
/* This function is called when Btree p is concluding its
** transaction. If there currently exists a writer, and p is not
** that writer, then the number of locks held by connections other
** than the writer must be about to drop to zero. In this case
** set the BTS_PENDING flag to 0.
**
** If there is not currently a writer, then BTS_PENDING must
** be zero already. So this next line is harmless in that case.
*/
pBt->btsFlags &= ~BTS_PENDING;
}
}
/*
** This function changes all write-locks held by Btree p into read-locks.
*/
static void downgradeAllSharedCacheTableLocks(Btree *p){
BtShared *pBt = p->pBt;
SHARED_LOCK_TRACE(pBt, "downgradeLocks", 0, 0);
if( pBt->pWriter==p ){
BtLock *pLock;
pBt->pWriter = 0;
pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){
assert( pLock->eLock==READ_LOCK || pLock->pBtree==p );
pLock->eLock = READ_LOCK;
}
}
}
#endif /* SQLITE_OMIT_SHARED_CACHE */
static void releasePage(MemPage *pPage); /* Forward reference */
static void releasePageOne(MemPage *pPage); /* Forward reference */
static void releasePageNotNull(MemPage *pPage); /* Forward reference */
/*
***** This routine is used inside of assert() only ****
**
** Verify that the cursor holds the mutex on its BtShared
*/
#ifdef SQLITE_DEBUG
static int cursorHoldsMutex(BtCursor *p){
return sqlite3_mutex_held(p->pBt->mutex);
}
/* Verify that the cursor and the BtShared agree about what is the current
** database connetion. This is important in shared-cache mode. If the database
** connection pointers get out-of-sync, it is possible for routines like
** btreeInitPage() to reference an stale connection pointer that references a
** a connection that has already closed. This routine is used inside assert()
** statements only and for the purpose of double-checking that the btree code
** does keep the database connection pointers up-to-date.
*/
static int cursorOwnsBtShared(BtCursor *p){
assert( cursorHoldsMutex(p) );
return (p->pBtree->db==p->pBt->db);
}
#endif
/*
** Invalidate the overflow cache of the cursor passed as the first argument.
** on the shared btree structure pBt.
*/
#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl)
/*
** Invalidate the overflow page-list cache for all cursors opened
** on the shared btree structure pBt.
*/
static void invalidateAllOverflowCache(BtShared *pBt){
BtCursor *p;
assert( sqlite3_mutex_held(pBt->mutex) );
for(p=pBt->pCursor; p; p=p->pNext){
invalidateOverflowCache(p);
}
}
#ifndef SQLITE_OMIT_INCRBLOB
/*
** This function is called before modifying the contents of a table
** to invalidate any incrblob cursors that are open on the
** row or one of the rows being modified.
**
** If argument isClearTable is true, then the entire contents of the
** table is about to be deleted. In this case invalidate all incrblob
** cursors open on any row within the table with root-page pgnoRoot.
**
** Otherwise, if argument isClearTable is false, then the row with
** rowid iRow is being replaced or deleted. In this case invalidate
** only those incrblob cursors open on that specific row.
*/
static void invalidateIncrblobCursors(
Btree *pBtree, /* The database file to check */
Pgno pgnoRoot, /* The table that might be changing */
i64 iRow, /* The rowid that might be changing */
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
assert( pBtree->hasIncrblobCur );
assert( sqlite3BtreeHoldsMutex(pBtree) );
pBtree->hasIncrblobCur = 0;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( (p->curFlags & BTCF_Incrblob)!=0 ){
pBtree->hasIncrblobCur = 1;
if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
p->eState = CURSOR_INVALID;
}
}
}
}
#else
/* Stub function when INCRBLOB is omitted */
#define invalidateIncrblobCursors(w,x,y,z)
#endif /* SQLITE_OMIT_INCRBLOB */
/*
** Set bit pgno of the BtShared.pHasContent bitvec. This is called
** when a page that previously contained data becomes a free-list leaf
** page.
**
** The BtShared.pHasContent bitvec exists to work around an obscure
** bug caused by the interaction of two useful IO optimizations surrounding
** free-list leaf pages:
**
** 1) When all data is deleted from a page and the page becomes
** a free-list leaf page, the page is not written to the database
** (as free-list leaf pages contain no meaningful data). Sometimes
** such a page is not even journalled (as it will not be modified,
** why bother journalling it?).
**
** 2) When a free-list leaf page is reused, its content is not read
** from the database or written to the journal file (why should it
** be, if it is not at all meaningful?).
**
** By themselves, these optimizations work fine and provide a handy
** performance boost to bulk delete or insert operations. However, if
** a page is moved to the free-list and then reused within the same
** transaction, a problem comes up. If the page is not journalled when
** it is moved to the free-list and it is also not journalled when it
** is extracted from the free-list and reused, then the original data
** may be lost. In the event of a rollback, it may not be possible
** to restore the database to its original configuration.
**
** The solution is the BtShared.pHasContent bitvec. Whenever a page is
** moved to become a free-list leaf page, the corresponding bit is
** set in the bitvec. Whenever a leaf page is extracted from the free-list,
** optimization 2 above is omitted if the corresponding bit is already
** set in BtShared.pHasContent. The contents of the bitvec are cleared
** at the end of every transaction.
*/
static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
int rc = SQLITE_OK;
if( !pBt->pHasContent ){
assert( pgno<=pBt->nPage );
pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
if( !pBt->pHasContent ){
rc = SQLITE_NOMEM_BKPT;
}
}
if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
rc = sqlite3BitvecSet(pBt->pHasContent, pgno);
}
return rc;
}
/*
** Query the BtShared.pHasContent vector.
**
** This function is called when a free-list leaf page is removed from the
** free-list for reuse. It returns false if it is safe to retrieve the
** page from the pager layer with the 'no-content' flag set. True otherwise.
*/
static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
Bitvec *p = pBt->pHasContent;
return p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTestNotNull(p, pgno));
}
/*
** Clear (destroy) the BtShared.pHasContent bitvec. This should be
** invoked at the conclusion of each write-transaction.
*/
static void btreeClearHasContent(BtShared *pBt){
sqlite3BitvecDestroy(pBt->pHasContent);
pBt->pHasContent = 0;
}
/*
** Release all of the apPage[] pages for a cursor.
*/
static void btreeReleaseAllCursorPages(BtCursor *pCur){
int i;
if( pCur->iPage>=0 ){
for(i=0; i<pCur->iPage; i++){
releasePageNotNull(pCur->apPage[i]);
}
releasePageNotNull(pCur->pPage);
pCur->iPage = -1;
}
}
/*
** The cursor passed as the only argument must point to a valid entry
** when this function is called (i.e. have eState==CURSOR_VALID). This
** function saves the current cursor key in variables pCur->nKey and
** pCur->pKey. SQLITE_OK is returned if successful or an SQLite error
** code otherwise.
**
** If the cursor is open on an intkey table, then the integer key
** (the rowid) is stored in pCur->nKey and pCur->pKey is left set to
** NULL. If the cursor is open on a non-intkey table, then pCur->pKey is
** set to point to a malloced buffer pCur->nKey bytes in size containing
** the key.
*/
static int saveCursorKey(BtCursor *pCur){
int rc = SQLITE_OK;
assert( CURSOR_VALID==pCur->eState );
assert( 0==pCur->pKey );
assert( cursorHoldsMutex(pCur) );
if( pCur->curIntKey ){
/* Only the rowid is required for a table btree */
pCur->nKey = sqlite3BtreeIntegerKey(pCur);
}else{
/* For an index btree, save the complete key content. It is possible
** that the current key is corrupt. In that case, it is possible that
** the sqlite3VdbeRecordUnpack() function may overread the buffer by
** up to the size of 1 varint plus 1 8-byte value when the cursor
** position is restored. Hence the 17 bytes of padding allocated
** below. */
void *pKey;
pCur->nKey = sqlite3BtreePayloadSize(pCur);
pKey = sqlite3Malloc( ((i64)pCur->nKey) + 9 + 8 );
if( pKey ){
rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
memset(((u8*)pKey)+pCur->nKey, 0, 9+8);
pCur->pKey = pKey;
}else{
sqlite3_free(pKey);
}
}else{
rc = SQLITE_NOMEM_BKPT;
}
}
assert( !pCur->curIntKey || !pCur->pKey );
return rc;
}
/*
** Save the current cursor position in the variables BtCursor.nKey
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
**
** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
** prior to calling this routine.
*/
static int saveCursorPosition(BtCursor *pCur){
int rc;
assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState );
assert( 0==pCur->pKey );
assert( cursorHoldsMutex(pCur) );
if( pCur->curFlags & BTCF_Pinned ){
return SQLITE_CONSTRAINT_PINNED;
}
if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
}else{
pCur->skipNext = 0;
}
rc = saveCursorKey(pCur);
if( rc==SQLITE_OK ){
btreeReleaseAllCursorPages(pCur);
pCur->eState = CURSOR_REQUIRESEEK;
}
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast);
return rc;
}
/* Forward reference */
static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*);
/*
** Save the positions of all cursors (except pExcept) that are open on
** the table with root-page iRoot. "Saving the cursor position" means that
** the location in the btree is remembered in such a way that it can be
** moved back to the same spot after the btree has been modified. This
** routine is called just before cursor pExcept is used to modify the
** table, for example in BtreeDelete() or BtreeInsert().
**
** If there are two or more cursors on the same btree, then all such
** cursors should have their BTCF_Multiple flag set. The btreeCursor()
** routine enforces that rule. This routine only needs to be called in
** the uncommon case when pExpect has the BTCF_Multiple flag set.
**
** If pExpect!=NULL and if no other cursors are found on the same root-page,
** then the BTCF_Multiple flag on pExpect is cleared, to avoid another
** pointless call to this routine.
**
** Implementation note: This routine merely checks to see if any cursors
** need to be saved. It calls out to saveCursorsOnList() in the (unusual)
** event that cursors are in need to being saved.
*/
static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
BtCursor *p;
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pExcept==0 || pExcept->pBt==pBt );
for(p=pBt->pCursor; p; p=p->pNext){
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break;
}
if( p ) return saveCursorsOnList(p, iRoot, pExcept);
if( pExcept ) pExcept->curFlags &= ~BTCF_Multiple;
return SQLITE_OK;
}
/* This helper routine to saveAllCursors does the actual work of saving
** the cursors if and when a cursor is found that actually requires saving.
** The common case is that no cursors need to be saved, so this routine is
** broken out from its caller to avoid unnecessary stack pointer movement.
*/
static int SQLITE_NOINLINE saveCursorsOnList(
BtCursor *p, /* The first cursor that needs saving */
Pgno iRoot, /* Only save cursor with this iRoot. Save all if zero */
BtCursor *pExcept /* Do not save this cursor */
){
do{
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
int rc = saveCursorPosition(p);
if( SQLITE_OK!=rc ){
return rc;
}
}else{
testcase( p->iPage>=0 );
btreeReleaseAllCursorPages(p);
}
}
p = p->pNext;
}while( p );
return SQLITE_OK;
}
/*
** Clear the current cursor position.
*/
SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
pCur->eState = CURSOR_INVALID;
}
/*
** In this version of BtreeMoveto, pKey is a packed index record
** such as is generated by the OP_MakeRecord opcode. Unpack the
** record and then call sqlite3BtreeIndexMoveto() to do the work.
*/
static int btreeMoveto(
BtCursor *pCur, /* Cursor open on the btree to be searched */
const void *pKey, /* Packed key if the btree is an index */
i64 nKey, /* Integer key for tables. Size of pKey for indices */
int bias, /* Bias search to the high end */
int *pRes /* Write search results here */
){
int rc; /* Status code */
UnpackedRecord *pIdxKey; /* Unpacked index key */
if( pKey ){
KeyInfo *pKeyInfo = pCur->pKeyInfo;
assert( nKey==(i64)(int)nKey );
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack((int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes);
}
sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
}else{
pIdxKey = 0;
rc = sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes);
}
return rc;
}
/*
** Restore the cursor to the position it was in (or as close to as possible)
** when saveCursorPosition() was called. Note that this call deletes the
** saved position info stored by saveCursorPosition(), so there can be
** at most one effective restoreCursorPosition() call after each
** saveCursorPosition().
*/
static int btreeRestoreCursorPosition(BtCursor *pCur){
int rc;
int skipNext = 0;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState>=CURSOR_REQUIRESEEK );
if( pCur->eState==CURSOR_FAULT ){
return pCur->skipNext;
}
pCur->eState = CURSOR_INVALID;
if( sqlite3FaultSim(410) ){
rc = SQLITE_IOERR;
}else{
rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
}
if( rc==SQLITE_OK ){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
if( skipNext ) pCur->skipNext = skipNext;
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
pCur->eState = CURSOR_SKIPNEXT;
}
}
return rc;
}
#define restoreCursorPosition(p) \
(p->eState>=CURSOR_REQUIRESEEK ? \
btreeRestoreCursorPosition(p) : \
SQLITE_OK)
/*
** Determine whether or not a cursor has moved from the position where
** it was last placed, or has been invalidated for any other reason.
** Cursors can move when the row they are pointing at is deleted out
** from under them, for example. Cursor might also move if a btree
** is rebalanced.
**
** Calling this routine with a NULL cursor pointer returns false.
**
** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor
** back to where it ought to be if this routine returns true.
*/
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
assert( EIGHT_BYTE_ALIGNMENT(pCur)
|| pCur==sqlite3BtreeFakeValidCursor() );
assert( offsetof(BtCursor, eState)==0 );
assert( sizeof(pCur->eState)==1 );
return CURSOR_VALID != *(u8*)pCur;
}
/*
** Return a pointer to a fake BtCursor object that will always answer
** false to the sqlite3BtreeCursorHasMoved() routine above. The fake
** cursor returned must not be used with any other Btree interface.
*/
SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void){
static u8 fakeCursor = CURSOR_VALID;
assert( offsetof(BtCursor, eState)==0 );
return (BtCursor*)&fakeCursor;
}
/*
** This routine restores a cursor back to its original position after it
** has been moved by some outside activity (such as a btree rebalance or
** a row having been deleted out from under the cursor).
**
** On success, the *pDifferentRow parameter is false if the cursor is left
** pointing at exactly the same row. *pDifferntRow is the row the cursor
** was pointing to has been deleted, forcing the cursor to point to some
** nearby row.
**
** This routine should only be called for a cursor that just returned
** TRUE from sqlite3BtreeCursorHasMoved().
*/
SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
int rc;
assert( pCur!=0 );
assert( pCur->eState!=CURSOR_VALID );
rc = restoreCursorPosition(pCur);
if( rc ){
*pDifferentRow = 1;
return rc;
}
if( pCur->eState!=CURSOR_VALID ){
*pDifferentRow = 1;
}else{
*pDifferentRow = 0;
}
return SQLITE_OK;
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
/*
** Provide hints to the cursor. The particular hint given (and the type
** and number of the varargs parameters) is determined by the eHintType
** parameter. See the definitions of the BTREE_HINT_* macros for details.
*/
SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
/* Used only by system that substitute their own storage engine */
#ifdef SQLITE_DEBUG
if( ALWAYS(eHintType==BTREE_HINT_RANGE) ){
va_list ap;
Expr *pExpr;
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3CursorRangeHintExprCheck;
va_start(ap, eHintType);
pExpr = va_arg(ap, Expr*);
w.u.aMem = va_arg(ap, Mem*);
va_end(ap);
assert( pExpr!=0 );
assert( w.u.aMem!=0 );
sqlite3WalkExpr(&w, pExpr);
}
#endif /* SQLITE_DEBUG */
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
/*
** Provide flag hints to the cursor.
*/
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
pCur->hints = (u8)x;
}
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Given a page number of a regular database page, return the page
** number for the pointer-map page that contains the entry for the
** input page number.
**
** Return 0 (not a valid page) for pgno==1 since there is
** no pointer map associated with page 1. The integrity_check logic
** requires that ptrmapPageno(*,1)!=1.
*/
static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
int nPagesPerMapPage;
Pgno iPtrMap, ret;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno<2 ) return 0;
nPagesPerMapPage = (pBt->usableSize/5)+1;
iPtrMap = (pgno-2)/nPagesPerMapPage;
ret = (iPtrMap*nPagesPerMapPage) + 2;
if( ret==PENDING_BYTE_PAGE(pBt) ){
ret++;
}
return ret;
}
/*
** Write an entry into the pointer map.
**
** This routine updates the pointer map entry for page number 'key'
** so that it maps to type 'eType' and parent page number 'pgno'.
**
** If *pRC is initially non-zero (non-SQLITE_OK) then this routine is
** a no-op. If an error occurs, the appropriate error code is written
** into *pRC.
*/
static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
DbPage *pDbPage; /* The pointer map page */
u8 *pPtrmap; /* The pointer map data */
Pgno iPtrmap; /* The pointer map page number */
int offset; /* Offset in pointer map page */
int rc; /* Return code from subfunctions */
if( *pRC ) return;
assert( sqlite3_mutex_held(pBt->mutex) );
/* The super-journal page number must never be used as a pointer map page */
assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );
assert( pBt->autoVacuum );
if( key==0 ){
*pRC = SQLITE_CORRUPT_BKPT;
return;
}
iPtrmap = PTRMAP_PAGENO(pBt, key);
}
}
if( mutexOpen ){
assert( sqlite3_mutex_held(mutexOpen) );
sqlite3_mutex_leave(mutexOpen);
}
assert( rc!=SQLITE_OK || sqlite3BtreeConnectionCount(*ppBtree)>0 );
return rc;
}
/*
** Decrement the BtShared.nRef counter. When it reaches zero,
** remove the BtShared structure from the sharing list. Return
** true if the BtShared.nRef counter reaches zero and return
** false if it is still positive.
*/
static int removeFromSharingList(BtShared *pBt){
#ifndef SQLITE_OMIT_SHARED_CACHE
MUTEX_LOGIC( sqlite3_mutex *pMainMtx; )
BtShared *pList;
int removed = 0;
assert( sqlite3_mutex_notheld(pBt->mutex) );
MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
sqlite3_mutex_enter(pMainMtx);
pBt->nRef--;
if( pBt->nRef<=0 ){
if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;
}else{
pList = GLOBAL(BtShared*,sqlite3SharedCacheList);
while( ALWAYS(pList) && pList->pNext!=pBt ){
pList=pList->pNext;
}
if( ALWAYS(pList) ){
pList->pNext = pBt->pNext;
}
}
if( SQLITE_THREADSAFE ){
sqlite3_mutex_free(pBt->mutex);
}
removed = 1;
}
sqlite3_mutex_leave(pMainMtx);
return removed;
#else
UNUSED_PARAMETER( pBt );
return 1;
#endif
}
/*
** Make sure pBt->pTmpSpace points to an allocation of
** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
** pointer.
*/
static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){
assert( pBt!=0 );
assert( pBt->pTmpSpace==0 );
/* This routine is called only by btreeCursor() when allocating the
** first write cursor for the BtShared object */
assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 );
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
if( pBt->pTmpSpace==0 ){
BtCursor *pCur = pBt->pCursor;
pBt->pCursor = pCur->pNext; /* Unlink the cursor */
memset(pCur, 0, sizeof(*pCur));
return SQLITE_NOMEM_BKPT;
}
/* One of the uses of pBt->pTmpSpace is to format cells before
** inserting them into a leaf page (function fillInCell()). If
** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
** by the various routines that manipulate binary cells. Which
** can mean that fillInCell() only initializes the first 2 or 3
** bytes of pTmpSpace, but that the first 4 bytes are copied from
** it into a database page. This is not actually a problem, but it
** does cause a valgrind error when the 1 or 2 bytes of uninitialized
** data is passed to system call write(). So to avoid this error,
** zero the first 4 bytes of temp space here.
**
** Also: Provide four bytes of initialized space before the
** beginning of pTmpSpace as an area available to prepend the
** left-child pointer to the beginning of a cell.
*/
memset(pBt->pTmpSpace, 0, 8);
pBt->pTmpSpace += 4;
return SQLITE_OK;
}
/*
** Free the pBt->pTmpSpace allocation
*/
static void freeTempSpace(BtShared *pBt){
if( pBt->pTmpSpace ){
pBt->pTmpSpace -= 4;
sqlite3PageFree(pBt->pTmpSpace);
pBt->pTmpSpace = 0;
}
}
/*
** Close an open database and invalidate all cursors.
*/
SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
BtShared *pBt = p->pBt;
/* Close all cursors opened via this handle. */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
/* Verify that no other cursors have this Btree open */
#ifdef SQLITE_DEBUG
{
BtCursor *pCur = pBt->pCursor;
while( pCur ){
BtCursor *pTmp = pCur;
pCur = pCur->pNext;
assert( pTmp->pBtree!=p );
}
}
#endif
/* Rollback any active transaction and free the handle structure.
** The call to sqlite3BtreeRollback() drops any table-locks held by
** this handle.
*/
sqlite3BtreeRollback(p, SQLITE_OK, 0);
sqlite3BtreeLeave(p);
/* If there are still other outstanding references to the shared-btree
** structure, return now. The remainder of this procedure cleans
** up the shared-btree.
*/
assert( p->wantToLock==0 && p->locked==0 );
if( !p->sharable || removeFromSharingList(pBt) ){
/* The pBt is no longer on the sharing list, so we can access
** it without having to hold the mutex.
**
** Clean out and delete the BtShared object.
*/
assert( !pBt->pCursor );
sqlite3PagerClose(pBt->pPager, p->db);
if( pBt->xFreeSchema && pBt->pSchema ){
pBt->xFreeSchema(pBt->pSchema);
}
sqlite3DbFree(0, pBt->pSchema);
freeTempSpace(pBt);
sqlite3_free(pBt);
}
#ifndef SQLITE_OMIT_SHARED_CACHE
assert( p->wantToLock==0 );
assert( p->locked==0 );
if( p->pPrev ) p->pPrev->pNext = p->pNext;
if( p->pNext ) p->pNext->pPrev = p->pPrev;
#endif
sqlite3_free(p);
return SQLITE_OK;
}
/*
** Change the "soft" limit on the number of pages in the cache.
** Unused and unmodified pages will be recycled when the number of
** pages in the cache exceeds this soft limit. But the size of the
** cache is allowed to grow larger than this limit if it contains
** dirty pages or pages still in active use.
*/
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
BtShared *pBt = p->pBt;
return rc;
}
if( nPage>nPageFile ){
if( sqlite3WritableSchema(pBt->db)==0 ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}else{
nPage = nPageFile;
}
}
/* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to
** be less than 480. In other words, if the page size is 512, then the
** reserved space size cannot exceed 32. */
if( usableSize<480 ){
goto page1_init_failed;
}
pBt->btsFlags |= BTS_PAGESIZE_FIXED;
pBt->pageSize = pageSize;
pBt->usableSize = usableSize;
#ifndef SQLITE_OMIT_AUTOVACUUM
pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0);
pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0);
#endif
}
/* maxLocal is the maximum amount of payload to store locally for
** a cell. Make sure it is small enough so that at least minFanout
** cells can will fit on one page. We assume a 10-byte page header.
** Besides the payload, the cell must store:
** 2-byte pointer to the cell
** 4-byte child pointer
** 9-byte nKey value
** 4-byte nData value
** 4-byte overflow page pointer
** So a cell consists of a 2-byte pointer, a header which is as much as
** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow
** page pointer.
*/
pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23);
pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23);
pBt->maxLeaf = (u16)(pBt->usableSize - 35);
pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23);
if( pBt->maxLocal>127 ){
pBt->max1bytePayload = 127;
}else{
pBt->max1bytePayload = (u8)pBt->maxLocal;
}
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
pBt->pPage1 = pPage1;
pBt->nPage = nPage;
return SQLITE_OK;
page1_init_failed:
releasePageOne(pPage1);
pBt->pPage1 = 0;
return rc;
}
#ifndef NDEBUG
/*
** Return the number of cursors open on pBt. This is for use
** in assert() expressions, so it is only compiled if NDEBUG is not
** defined.
**
** Only write cursors are counted if wrOnly is true. If wrOnly is
** false then all cursors are counted.
**
** For the purposes of this routine, a cursor is any cursor that
** is capable of reading or writing to the database. Cursors that
** have been tripped into the CURSOR_FAULT state are not counted.
*/
static int countValidCursors(BtShared *pBt, int wrOnly){
BtCursor *pCur;
int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
&& pCur->eState!=CURSOR_FAULT ) r++;
}
return r;
}
#endif
/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
** this routine unrefs the first page of the database file which
** has the effect of releasing the read lock.
**
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(BtShared *pBt){
assert( sqlite3_mutex_held(pBt->mutex) );
assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE );
if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
MemPage *pPage1 = pBt->pPage1;
assert( pPage1->aData );
assert( sqlite3PagerRefcount(pBt->pPager)==1 );
pBt->pPage1 = 0;
releasePageOne(pPage1);
}
}
/*
** If pBt points to an empty file then convert that empty file
** into a new empty database by initializing the first page of
** the database.
*/
static int newDatabase(BtShared *pBt){
MemPage *pP1;
unsigned char *data;
int rc;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pBt->nPage>0 ){
return SQLITE_OK;
}
pP1 = pBt->pPage1;
assert( pP1!=0 );
data = pP1->aData;
rc = sqlite3PagerWrite(pP1->pDbPage);
if( rc ) return rc;
memcpy(data, zMagicHeader, sizeof(zMagicHeader));
assert( sizeof(zMagicHeader)==16 );
data[16] = (u8)((pBt->pageSize>>8)&0xff);
data[17] = (u8)((pBt->pageSize>>16)&0xff);
data[18] = 1;
data[19] = 1;
assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize);
data[20] = (u8)(pBt->pageSize - pBt->usableSize);
data[21] = 64;
data[22] = 32;
data[23] = 32;
memset(&data[24], 0, 100-24);
zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
pBt->btsFlags |= BTS_PAGESIZE_FIXED;
#ifndef SQLITE_OMIT_AUTOVACUUM
assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
put4byte(&data[36 + 4*4], pBt->autoVacuum);
put4byte(&data[36 + 7*4], pBt->incrVacuum);
#endif
pBt->nPage = 1;
data[31] = 1;
return SQLITE_OK;
static void btreeEndTransaction(Btree *p){
BtShared *pBt = p->pBt;
sqlite3 *db = p->db;
assert( sqlite3BtreeHoldsMutex(p) );
#ifndef SQLITE_OMIT_AUTOVACUUM
pBt->bDoTruncate = 0;
#endif
if( p->inTrans>TRANS_NONE && db->nVdbeRead>1 ){
/* If there are other active statements that belong to this database
** handle, downgrade to a read-only transaction. The other statements
** may still be reading from the database. */
downgradeAllSharedCacheTableLocks(p);
p->inTrans = TRANS_READ;
}else{
/* If the handle had any kind of transaction open, decrement the
** transaction count of the shared btree. If the transaction count
** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused()
** call below will unlock the pager. */
if( p->inTrans!=TRANS_NONE ){
clearAllSharedCacheTableLocks(p);
pBt->nTransaction--;
if( 0==pBt->nTransaction ){
pBt->inTransaction = TRANS_NONE;
}
}
/* Set the current transaction state to TRANS_NONE and unlock the
** pager if this call closed the only read or write transaction. */
p->inTrans = TRANS_NONE;
unlockBtreeIfUnused(pBt);
}
btreeIntegrity(p);
}
/*
** Commit the transaction currently in progress.
**
** This routine implements the second phase of a 2-phase commit. The
** sqlite3BtreeCommitPhaseOne() routine does the first phase and should
** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne()
** routine did all the work of writing information out to disk and flushing the
** contents so that they are written onto the disk platter. All this
** routine has to do is delete or truncate or zero the header in the
** the rollback journal (which causes the transaction to commit) and
** drop locks.
**
** Normally, if an error occurs while the pager layer is attempting to
** finalize the underlying journal file, this function returns an error and
** the upper layer will attempt a rollback. However, if the second argument
** is non-zero then this b-tree transaction is part of a multi-file
** transaction. In this case, the transaction has already been committed
** (by deleting a super-journal file) and the caller will ignore this
** functions return code. So, even if an error occurs in the pager layer,
** reset the b-tree objects internal state to indicate that the write
** transaction has been closed. This is quite safe, as the pager will have
** transitioned to the error state.
**
** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock.
*/
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
if( p->inTrans==TRANS_NONE ) return SQLITE_OK;
sqlite3BtreeEnter(p);
btreeIntegrity(p);
/* If the handle has a write-transaction open, commit the shared-btrees
** transaction and set the shared state to TRANS_READ.
*/
if( p->inTrans==TRANS_WRITE ){
int rc;
BtShared *pBt = p->pBt;
assert( pBt->inTransaction==TRANS_WRITE );
assert( pBt->nTransaction>0 );
rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
if( rc!=SQLITE_OK && bCleanup==0 ){
sqlite3BtreeLeave(p);
return rc;
}
p->iBDataVersion--; /* Compensate for pPager->iDataVersion++; */
pBt->inTransaction = TRANS_READ;
btreeClearHasContent(pBt);
}
btreeEndTransaction(p);
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
/*
** Do both phases of a commit.
*/
SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){
int rc;
sqlite3BtreeEnter(p);
rc = sqlite3BtreeCommitPhaseOne(p, 0);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeCommitPhaseTwo(p, 0);
}
sqlite3BtreeLeave(p);
return rc;
}
/*
** This routine sets the state to CURSOR_FAULT and the error
** code to errCode for every cursor on any BtShared that pBtree
** references. Or if the writeOnly flag is set to 1, then only
** trip write cursors and leave read cursors unchanged.
**
** Every cursor is a candidate to be tripped, including cursors
** that belong to other database connections that happen to be
** sharing the cache with pBtree.
**
** This routine gets called when a rollback occurs. If the writeOnly
** flag is true, then only write-cursors need be tripped - read-only
** cursors save their current positions so that they may continue
** following the rollback. Or, if writeOnly is false, all cursors are
** tripped. In general, writeOnly is false if the transaction being
** rolled back modified the database schema. In this case b-tree root
** pages may be moved or deleted from the database altogether, making
** it unsafe for read cursors to continue.
**
** If the writeOnly flag is true and an error is encountered while
** saving the current position of a read-only cursor, all cursors,
** including all read-cursors are tripped.
**
** SQLITE_OK is returned if successful, or if an error occurs while
** saving a cursor position, an SQLite error code.
*/
SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
BtCursor *p;
int rc = SQLITE_OK;
assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 );
if( pBtree ){
sqlite3BtreeEnter(pBtree);
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
rc = saveCursorPosition(p);
if( rc!=SQLITE_OK ){
(void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
break;
}
}
}else{
sqlite3BtreeClearCursor(p);
p->eState = CURSOR_FAULT;
p->skipNext = errCode;
}
btreeReleaseAllCursorPages(p);
}
sqlite3BtreeLeave(pBtree);
}
return rc;
}
/*
** Set the pBt->nPage field correctly, according to the current
** state of the database. Assume pBt->pPage1 is valid.
*/
static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){
int nPage = get4byte(&pPage1->aData[28]);
testcase( nPage==0 );
if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
testcase( pBt->nPage!=(u32)nPage );
pBt->nPage = nPage;
}
/*
** Rollback the transaction in progress.
**
** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped).
** Only write cursors are tripped if writeOnly is true but all cursors are
** tripped if writeOnly is false. Any attempt to use
** a tripped cursor will result in an error.
**
** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock.
*/
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
int rc;
BtShared *pBt = p->pBt;
MemPage *pPage1;
assert( writeOnly==1 || writeOnly==0 );
assert( tripCode==SQLITE_ABORT_ROLLBACK || tripCode==SQLITE_OK );
sqlite3BtreeEnter(p);
if( tripCode==SQLITE_OK ){
rc = tripCode = saveAllCursors(pBt, 0, 0);
if( rc ) writeOnly = 0;
}else{
rc = SQLITE_OK;
}
if( tripCode ){
int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly);
assert( rc==SQLITE_OK || (writeOnly==0 && rc2==SQLITE_OK) );
if( rc2!=SQLITE_OK ) rc = rc2;
}
btreeIntegrity(p);
if( p->inTrans==TRANS_WRITE ){
int rc2;
assert( TRANS_WRITE==pBt->inTransaction );
rc2 = sqlite3PagerRollback(pBt->pPager);
if( rc2!=SQLITE_OK ){
rc = rc2;
}
/* The rollback may have destroyed the pPage1->aData value. So
** call btreeGetPage() on page 1 again to make
** sure pPage1->aData is set correctly. */
if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
btreeSetNPage(pBt, pPage1);
releasePageOne(pPage1);
}
assert( countValidCursors(pBt, 1)==0 );
pBt->inTransaction = TRANS_READ;
btreeClearHasContent(pBt);
}
btreeEndTransaction(p);
sqlite3BtreeLeave(p);
return rc;
}
/*
** Start a statement subtransaction. The subtransaction can be rolled
** back independently of the main transaction. You must start a transaction
** before starting a subtransaction. The subtransaction is ended automatically
** if the main transaction commits or rolls back.
**
** Statement subtransactions are used around individual SQL statements
** that are contained within a BEGIN...COMMIT block. If a constraint
** error occurs within the statement, the effect of that one statement
** can be rolled back without having to rollback the entire transaction.
**
** A statement sub-transaction is implemented as an anonymous savepoint. The
int rc;
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
assert( p->inTrans==TRANS_WRITE );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( iStatement>0 );
assert( iStatement>p->db->nSavepoint );
assert( pBt->inTransaction==TRANS_WRITE );
/* At the pager level, a statement transaction is a savepoint with
** an index greater than all savepoints created explicitly using
** SQL statements. It is illegal to open, release or rollback any
** such savepoints while the statement transaction savepoint is active.
*/
rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);
sqlite3BtreeLeave(p);
return rc;
}
/*
** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
** or SAVEPOINT_RELEASE. This function either releases or rolls back the
** savepoint identified by parameter iSavepoint, depending on the value
** of op.
**
** Normally, iSavepoint is greater than or equal to zero. However, if op is
** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
** contents of the entire transaction are rolled back. This is different
** from a normal transaction rollback, as no locks are released and the
** transaction remains open.
*/
SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
int rc = SQLITE_OK;
if( p && p->inTrans==TRANS_WRITE ){
BtShared *pBt = p->pBt;
assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
sqlite3BtreeEnter(p);
if( op==SAVEPOINT_ROLLBACK ){
rc = saveAllCursors(pBt, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
}
if( rc==SQLITE_OK ){
if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
pBt->nPage = 0;
}
rc = newDatabase(pBt);
btreeSetNPage(pBt, pBt->pPage1);
/* pBt->nPage might be zero if the database was corrupt when
** the transaction was started. Otherwise, it must be at least 1. */
assert( CORRUPT_DB || pBt->nPage>0 );
}
sqlite3BtreeLeave(p);
}
return rc;
}
/*
** Create a new cursor for the BTree whose root is on the page
** iTable. If a read-only cursor is requested, it is assumed that
** the caller already has at least a read-only transaction open
** on the database already. If a write-cursor is requested, then
** the caller is assumed to have an open write transaction.
**
** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only
** be used for reading. If the BTREE_WRCSR bit is set, then the cursor
** can be used for reading or for writing if other conditions for writing
** are also met. These are the conditions that must be met in order
** for writing to be allowed:
**
** 1: The cursor must have been opened with wrFlag containing BTREE_WRCSR
**
** 2: Other database connections that share the same pager cache
** but which are not in the READ_UNCOMMITTED state may not have
** cursors open with wrFlag==0 on the same table. Otherwise
** the changes made by this write cursor would be visible to
** the read cursors in the other database connection.
**
** 3: The database must be writable (not on read-only media)
**
** 4: There must be an active transaction.
**
** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR
** is set. If FORDELETE is set, that is a hint to the implementation that
** this cursor will only be used to seek to and delete entries of an index
** as part of a larger DELETE statement. The FORDELETE hint is not used by
** this implementation. But in a hypothetical alternative storage engine
** in which index entries are automatically deleted when corresponding table
** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE
** operations on this cursor can be no-ops and all READ operations can
** return a null row (2-bytes: 0x01 0x00).
**
** No checking is done to make sure that page iTable really is the
** root page of a b-tree. If it is not, then the cursor acquired
** will not work correctly.
**
** It is assumed that the sqlite3BtreeCursorZero() has been called
** on pCur to initialize the memory space prior to invoking this routine.
*/
static int btreeCursor(
Btree *p, /* The btree */
Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to comparison function */
BtCursor *pCur /* Space for new cursor */
){
BtShared *pBt = p->pBt; /* Shared b-tree handle */
BtCursor *pX; /* Looping over other all cursors */
assert( sqlite3BtreeHoldsMutex(p) );
assert( wrFlag==0
|| wrFlag==BTREE_WRCSR
|| wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
);
/* The following assert statements verify that if this is a sharable
** b-tree database, the connection is holding the required table locks,
** and that no other connection has any open cursor that conflicts with
** this lock. The iTable<1 term disables the check for corrupt schemas. */
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1))
|| iTable<1 );
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
/* Assert that the caller has opened the required transaction. */
assert( p->inTrans>TRANS_NONE );
assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
assert( pBt->pPage1 && pBt->pPage1->aData );
assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 );
if( iTable<=1 ){
if( iTable<1 ){
return SQLITE_CORRUPT_BKPT;
}else if( btreePagecount(pBt)==0 ){
assert( wrFlag==0 );
iTable = 0;
}
}
/* Now that no other errors can occur, finish filling in the BtCursor
** variables and link the cursor into the BtShared list. */
pCur->pgnoRoot = iTable;
pCur->iPage = -1;
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
pCur->curFlags = 0;
/* If there are two or more cursors on the same btree, then all such
** cursors *must* have the BTCF_Multiple flag set. */
for(pX=pBt->pCursor; pX; pX=pX->pNext){
if( pX->pgnoRoot==iTable ){
pX->curFlags |= BTCF_Multiple;
pCur->curFlags = BTCF_Multiple;
}
}
pCur->eState = CURSOR_INVALID;
pCur->pNext = pBt->pCursor;
pBt->pCursor = pCur;
if( wrFlag ){
pCur->curFlags |= BTCF_WriteFlag;
pCur->curPagerFlags = 0;
if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt);
}else{
pCur->curPagerFlags = PAGER_GET_READONLY;
}
return SQLITE_OK;
}
static int btreeCursorWithLock(
Btree *p, /* The btree */
Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to comparison function */
BtCursor *pCur /* Space for new cursor */
){
int rc;
sqlite3BtreeEnter(p);
rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
sqlite3BtreeLeave(p);
return rc;
}
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree *p, /* The btree */
Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
BtCursor *pCur /* Write new cursor here */
){
if( p->sharable ){
return btreeCursorWithLock(p, iTable, wrFlag, pKeyInfo, pCur);
}else{
return btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
}
}
/*
** Return the size of a BtCursor object in bytes.
**
** This interfaces is needed so that users of cursors can preallocate
** sufficient storage to hold a cursor. The BtCursor object is opaque
** to users so they cannot do the sizeof() themselves - they must call
** this routine.
*/
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){
return ROUND8(sizeof(BtCursor));
}
#ifdef SQLITE_DEBUG
/*
** Return true if and only if the Btree object will be automatically
** closed with the BtCursor closes. This is used within assert() statements
** only.
*/
SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(
Btree *pBtree, /* the btree object */
BtCursor *pCur /* Corresponding cursor */
){
BtShared *pBt = pBtree->pBt;
if( (pBt->openFlags & BTREE_SINGLE)==0 ) return 0;
if( pBt->pCursor!=pCur ) return 0;
if( pCur->pNext!=0 ) return 0;
if( pCur->pBtree!=pBtree ) return 0;
return 1;
}
#endif
/*
** Initialize memory that will be converted into a BtCursor object.
**
** The simple approach here would be to memset() the entire object
** to zero. But it turns out that the apPage[] and aiIdx[] arrays
** do not need to be zeroed and they are large, so we can save a lot
** of run-time by skipping the initialization of those elements.
*/
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){
memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT));
}
/*
** Close a cursor. The read lock on the database file is released
** when the last cursor is closed.
*/
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
Btree *pBtree = pCur->pBtree;
if( pBtree ){
BtShared *pBt = pCur->pBt;
sqlite3BtreeEnter(pBtree);
assert( pBt->pCursor!=0 );
if( pBt->pCursor==pCur ){
pBt->pCursor = pCur->pNext;
}else{
BtCursor *pPrev = pBt->pCursor;
do{
if( pPrev->pNext==pCur ){
pPrev->pNext = pCur->pNext;
break;
}
pPrev = pPrev->pNext;
}while( ALWAYS(pPrev) );
}
btreeReleaseAllCursorPages(pCur);
unlockBtreeIfUnused(pBt);
sqlite3_free(pCur->aOverflow);
sqlite3_free(pCur->pKey);
if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){
/* Since the BtShared is not sharable, there is no need to
** worry about the missing sqlite3BtreeLeave() call here. */
assert( pBtree->sharable==0 );
sqlite3BtreeClose(pBtree);
}else{
sqlite3BtreeLeave(pBtree);
}
pCur->pBtree = 0;
}
return SQLITE_OK;
}
/*
** Make sure the BtCursor* given in the argument has a valid
** BtCursor.info structure. If it is not already valid, call
** btreeParseCell() to fill it in.
**
** BtCursor.info is a cache of the information in the current cell.
** Using this cache reduces the number of calls to btreeParseCell().
*/
#ifndef NDEBUG
static int cellInfoEqual(CellInfo *a, CellInfo *b){
if( a->nKey!=b->nKey ) return 0;
if( a->pPayload!=b->pPayload ) return 0;
if( a->nPayload!=b->nPayload ) return 0;
if( a->nLocal!=b->nLocal ) return 0;
if( a->nSize!=b->nSize ) return 0;
return 1;
}
static void assertCellInfo(BtCursor *pCur){
CellInfo info;
memset(&info, 0, sizeof(info));
btreeParseCell(pCur->pPage, pCur->ix, &info);
assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) );
}
#else
#define assertCellInfo(x)
#endif
static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
pCur->curFlags |= BTCF_ValidNKey;
btreeParseCell(pCur->pPage,pCur->ix,&pCur->info);
}else{
assertCellInfo(pCur);
}
}
#ifndef NDEBUG /* The next routine used only within assert() statements */
/*
** Return true if the given BtCursor is valid. A valid cursor is one
** that is currently pointing to a row in a (non-empty) table.
** This is a verification routine is used only within assert() statements.
*/
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){
return pCur && pCur->eState==CURSOR_VALID;
}
#endif /* NDEBUG */
SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){
assert( pCur!=0 );
return pCur->eState==CURSOR_VALID;
}
/*
** Return the value of the integer key or "rowid" for a table btree.
** This routine is only valid for a cursor that is pointing into a
** ordinary table btree. If the cursor points to an index btree or
** is invalid, the result of this routine is undefined.
*/
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->curIntKey );
getCellInfo(pCur);
return pCur->info.nKey;
}
/*
** Pin or unpin a cursor.
*/
SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor *pCur){
assert( (pCur->curFlags & BTCF_Pinned)==0 );
pCur->curFlags |= BTCF_Pinned;
}
SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){
assert( (pCur->curFlags & BTCF_Pinned)!=0 );
pCur->curFlags &= ~BTCF_Pinned;
}
/*
** Return the offset into the database file for the start of the
** payload to which the cursor is pointing.
*/
SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
getCellInfo(pCur);
return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) +
(i64)(pCur->info.pPayload - pCur->pPage->aData);
}
/*
** Return the number of bytes of payload for the entry that pCur is
** currently pointing to. For table btrees, this will be the amount
** of data. For index btrees, this will be the size of the key.
**
** The caller must guarantee that the cursor is pointing to a non-NULL
** valid entry. In other words, the calling procedure must guarantee
** that the cursor has Cursor.eState==CURSOR_VALID.
*/
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
getCellInfo(pCur);
return pCur->info.nPayload;
}
/*
** Return an upper bound on the size of any record for the table
** that the cursor is pointing into.
**
** This is an optimization. Everything will still work if this
** routine always returns 2147483647 (which is the largest record
** that SQLite can handle) or more. But returning a smaller value might
** prevent large memory allocations when trying to interpret a
** corrupt database.
**
** The current implementation merely returns the size of the underlying
** database file.
*/
SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
}
/*
** Given the page number of an overflow page in the database (parameter
** ovfl), this function finds the page number of the next page in the
** linked list of overflow pages. If possible, it uses the auto-vacuum
** pointer-map data instead of reading the content of page ovfl to do so.
**
** If an error occurs an SQLite error code is returned. Otherwise:
**
** The page number of the next overflow page in the linked list is
** written to *pPgnoNext. If page ovfl is the last page in its linked
** list, *pPgnoNext is set to zero.
**
** If ppPage is not NULL, and a reference to the MemPage object corresponding
** to page number pOvfl was obtained, then *ppPage is set to point to that
** reference. It is the responsibility of the caller to call releasePage()
** on *ppPage to free the reference. In no reference was obtained (because
** the pointer-map was used to obtain the value for *pPgnoNext), then
** *ppPage is set to zero.
*/
static int getOverflowPage(
BtShared *pBt, /* The database file */
Pgno ovfl, /* Current overflow page number */
MemPage **ppPage, /* OUT: MemPage handle (may be NULL) */
Pgno *pPgnoNext /* OUT: Next overflow page number */
){
Pgno next = 0;
MemPage *pPage = 0;
int rc = SQLITE_OK;
assert( sqlite3_mutex_held(pBt->mutex) );
assert(pPgnoNext);
#ifndef SQLITE_OMIT_AUTOVACUUM
/* Try to find the next page in the overflow list using the
** autovacuum pointer-map pages. Guess that the next page in
** the overflow list is page number (ovfl+1). If that guess turns
** out to be wrong, fall back to loading the data of page
** number ovfl to determine the next page number.
*/
if( pBt->autoVacuum ){
Pgno pgno;
Pgno iGuess = ovfl+1;
u8 eType;
while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){
iGuess++;
}
if( iGuess<=btreePagecount(pBt) ){
rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
if( rc==SQLITE_OK && eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){
next = iGuess;
rc = SQLITE_DONE;
}
}
}
#endif
assert( next==0 || rc==SQLITE_DONE );
if( rc==SQLITE_OK ){
rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? PAGER_GET_READONLY : 0);
assert( rc==SQLITE_OK || pPage==0 );
if( rc==SQLITE_OK ){
next = get4byte(pPage->aData);
}
}
*pPgnoNext = next;
if( ppPage ){
*ppPage = pPage;
}else{
releasePage(pPage);
}
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}
/*
** Copy data from a buffer to a page, or from a page to a buffer.
**
** pPayload is a pointer to data stored on database page pDbPage.
** If argument eOp is false, then nByte bytes of data are copied
** from pPayload to the buffer pointed at by pBuf. If eOp is true,
** then sqlite3PagerWrite() is called on pDbPage and nByte bytes
** of data are copied from the buffer pBuf to pPayload.
**
** SQLITE_OK is returned on success, otherwise an error code.
*/
static int copyPayload(
void *pPayload, /* Pointer to page data */
void *pBuf, /* Pointer to buffer */
int nByte, /* Number of bytes to copy */
int eOp, /* 0 -> copy from page, 1 -> copy to page */
DbPage *pDbPage /* Page containing pPayload */
){
if( eOp ){
/* Copy data from buffer to page (a write operation) */
int rc = sqlite3PagerWrite(pDbPage);
if( rc!=SQLITE_OK ){
return rc;
}
memcpy(pPayload, pBuf, nByte);
}else{
/* Copy data from page to buffer (a read operation) */
memcpy(pBuf, pPayload, nByte);
}
return SQLITE_OK;
}
/*
** This function is used to read or overwrite payload information
** for the entry that the pCur cursor is pointing to. The eOp
** argument is interpreted as follows:
**
** 0: The operation is a read. Populate the overflow cache.
** 1: The operation is a write. Populate the overflow cache.
**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
**
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**
** If the current cursor entry uses one or more overflow pages
** this function may allocate space for and lazily populate
** the overflow page-list cache array (BtCursor.aOverflow).
** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
** Once an overflow page-list cache has been allocated, it must be
** invalidated if some other cursor writes to the same table, or if
** the cursor is moved to a different row. Additionally, in auto-vacuum
** mode, the following events may invalidate an overflow page-list cache.
**
** * An incremental vacuum,
** * A commit in auto_vacuum="full" mode,
** * Creating a table (may require moving an overflow page).
*/
static int accessPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 offset, /* Begin reading this far into payload */
u32 amt, /* Read this many bytes */
unsigned char *pBuf, /* Write the bytes into this buffer */
int eOp /* zero to read. non-zero to write. */
){
unsigned char *aPayload;
int rc = SQLITE_OK;
int iIdx = 0;
MemPage *pPage = pCur->pPage; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
unsigned char * const pBufStart = pBuf; /* Start of original out buffer */
#endif
assert( pPage );
assert( eOp==0 || eOp==1 );
assert( pCur->eState==CURSOR_VALID );
if( pCur->ix>=pPage->nCell ){
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( cursorHoldsMutex(pCur) );
getCellInfo(pCur);
aPayload = pCur->info.pPayload;
assert( offset+amt <= pCur->info.nPayload );
assert( aPayload > pPage->aData );
if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
/* Trying to read or write past the end of the data is an error. The
** conditional above is really:
** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
** but is recast into its current form to avoid integer overflow problems
*/
return SQLITE_CORRUPT_PAGE(pPage);
}
/* Check if data must be read/written to/from the btree page itself. */
if( offset<pCur->info.nLocal ){
int a = amt;
if( a+offset>pCur->info.nLocal ){
a = pCur->info.nLocal - offset;
}
rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
offset = 0;
pBuf += a;
amt -= a;
}else{
offset -= pCur->info.nLocal;
}
if( rc==SQLITE_OK && amt>0 ){
const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
Pgno nextPage;
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
**
** The aOverflow[] array is sized at one entry for each overflow page
** in the overflow chain. The page number of the first overflow page is
** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
** means "not yet known" (the cache is lazily populated).
*/
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
if( pCur->aOverflow==0
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
){
Pgno *aNew;
if( sqlite3FaultSim(413) ){
aNew = 0;
}else{
aNew = (Pgno*)sqlite3Realloc(pCur->aOverflow, nOvfl*2*sizeof(Pgno));
}
if( aNew==0 ){
return SQLITE_NOMEM_BKPT;
}else{
pCur->aOverflow = aNew;
}
}
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/* If all the following are true:
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
** 3) there are no dirty pages in the page-cache
** 4) the database is file-backed, and
** 5) the page is not in the WAL file
** 6) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
if( eOp==0 /* (1) */
&& offset==0 /* (2) */
&& sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */
&& &pBuf[-4]>=pBufStart /* (6) */
){
sqlite3_file *fd = sqlite3PagerFile(pBt->pPager);
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
nextPage = get4byte(aWrite);
memcpy(aWrite, aSave, 4);
}else
#endif
{
DbPage *pDbPage;
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
(eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
sqlite3PagerUnref(pDbPage);
offset = 0;
}
}
amt -= a;
if( amt==0 ) return rc;
pBuf += a;
}
if( rc ) break;
iIdx++;
}
}
if( rc==SQLITE_OK && amt>0 ){
/* Overflow chain ends prematurely */
return SQLITE_CORRUPT_PAGE(pPage);
}
return rc;
}
/*
** Read part of the payload for the row at which that cursor pCur is currently
** pointing. "amt" bytes will be transferred into pBuf[]. The transfer
** begins at "offset".
**
** pCur can be pointing to either a table or an index b-tree.
** If pointing to a table btree, then the content section is read. If
** pCur is pointing to an index b-tree then the key section is read.
**
** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing
** to a valid row in the table. For sqlite3BtreePayloadChecked(), the
** cursor might be invalid or might need to be restored before being read.
**
** Return SQLITE_OK on success or an error code if anything goes
** wrong. An error is returned if "offset+amt" is larger than
** the available payload.
*/
SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 && pCur->pPage );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
/*
** This variant of sqlite3BtreePayload() works even if the cursor has not
** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read()
** interface.
*/
#ifndef SQLITE_OMIT_INCRBLOB
static SQLITE_NOINLINE int accessPayloadChecked(
BtCursor *pCur,
u32 offset,
u32 amt,
void *pBuf
){
int rc;
if ( pCur->eState==CURSOR_INVALID ){
return SQLITE_ABORT;
}
assert( cursorOwnsBtShared(pCur) );
rc = btreeRestoreCursorPosition(pCur);
return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
}
SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
if( pCur->eState==CURSOR_VALID ){
assert( cursorOwnsBtShared(pCur) );
return accessPayload(pCur, offset, amt, pBuf, 0);
}else{
return accessPayloadChecked(pCur, offset, amt, pBuf);
}
}
#endif /* SQLITE_OMIT_INCRBLOB */
/*
** Return a pointer to payload information from the entry that the
** pCur cursor is pointing to. The pointer is to the beginning of
** the key if index btrees (pPage->intKey==0) and is the data for
** table btrees (pPage->intKey==1). The number of bytes of available
** key/data is written into *pAmt. If *pAmt==0, then the value
** returned will not be a valid pointer.
**
** This routine is an optimization. It is common for the entire key
** and data to fit on the local page and for there to be no overflow
** pages. When that is so, this routine can be used to access the
** key and data without making a copy. If the key and/or data spills
** onto overflow pages, then accessPayload() must be used to reassemble
** the key/data and copy it into a preallocated buffer.
**
** The pointer returned by this routine looks directly into the cached
** page of the database. The data might change or move the next time
** any btree routine is called.
*/
static const void *fetchPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 *pAmt /* Write the number of available bytes here */
){
int amt;
assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorOwnsBtShared(pCur) );
assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
assert( pCur->info.nSize>0 );
assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB);
amt = pCur->info.nLocal;
if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
/* There is too little space on the page for the expected amount
** of local content. Database must be corrupt. */
assert( CORRUPT_DB );
amt = MAX(0, (int)(pCur->pPage->aDataEnd - pCur->info.pPayload));
}
*pAmt = (u32)amt;
return (void*)pCur->info.pPayload;
}
/*
** For the entry that cursor pCur is point to, return as
** many bytes of the key or data as are available on the local
** b-tree page. Write the number of available bytes into *pAmt.
**
** The pointer returned is ephemeral. The key/data may move
** or be destroyed on the next call to any Btree routine,
** including calls from other threads against the same cache.
** Hence, a mutex on the BtShared should be held prior to calling
** this routine.
**
** These routines is used to get quick access to key and data
** in the common case where no overflow pages are used.
*/
SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
return fetchPayload(pCur, pAmt);
}
/*
** Move the cursor down to a new child page. The newPgno argument is the
** page number of the child page to move to.
**
** This function returns SQLITE_CORRUPT if the page-header flags field of
** the new child page does not match the flags field of the parent (i.e.
** if an intkey page appears to be the parent of a non-intkey page, or
** vice-versa).
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
int rc;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
assert( pCur->iPage>=0 );
if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
return SQLITE_CORRUPT_BKPT;
}
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->aiIdx[pCur->iPage] = pCur->ix;
pCur->apPage[pCur->iPage] = pCur->pPage;
pCur->ix = 0;
pCur->iPage++;
rc = getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur->curPagerFlags);
assert( pCur->pPage!=0 || rc!=SQLITE_OK );
if( rc==SQLITE_OK
&& (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey)
){
releasePage(pCur->pPage);
rc = SQLITE_CORRUPT_PGNO(newPgno);
}
if( rc ){
pCur->pPage = pCur->apPage[--pCur->iPage];
}
return rc;
}
#ifdef SQLITE_DEBUG
/*
** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
** cell in page pParent. Or, if iIdx is equal to the total number of
** cells in pParent, that page number iChild is the right-child of
** the page.
*/
static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
if( CORRUPT_DB ) return; /* The conditions tested below might not be true
** in a corrupt database */
assert( iIdx<=pParent->nCell );
if( iIdx==pParent->nCell ){
assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild );
}else{
assert( get4byte(findCell(pParent, iIdx))==iChild );
}
}
#else
# define assertParentIndex(x,y,z)
#endif
/*
** Move the cursor up to the parent page.
**
** pCur->idx is set to the cell index that contains the pointer
** to the page we are coming from. If we are coming from the
** right-most child page then pCur->idx is set to one more than
** the largest cell index.
*/
static void moveToParent(BtCursor *pCur){
MemPage *pLeaf;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>0 );
assert( pCur->pPage );
assertParentIndex(
pCur->apPage[pCur->iPage-1],
pCur->aiIdx[pCur->iPage-1],
pCur->pPage->pgno
);
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->ix = pCur->aiIdx[pCur->iPage-1];
pLeaf = pCur->pPage;
pCur->pPage = pCur->apPage[--pCur->iPage];
releasePageNotNull(pLeaf);
}
/*
** Move the cursor to point to the root page of its b-tree structure.
**
** If the table has a virtual root page, then the cursor is moved to point
** to the virtual root page instead of the actual root page. A table has a
** virtual root page when the actual root page contains no cells and a
** single child page. This can only happen with the table rooted at page 1.
**
** If the b-tree structure is empty, the cursor state is set to
** CURSOR_INVALID and this routine returns SQLITE_EMPTY. Otherwise,
** the cursor is set to point to the first cell located on the root
** (or virtual root) page and the cursor state is set to CURSOR_VALID.
**
** If this function returns successfully, it may be assumed that the
** page-header flags indicate that the [virtual] root-page is the expected
** kind of b-tree page (i.e. if when opening the cursor the caller did not
** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D,
** indicating a table b-tree, or if the caller did specify a KeyInfo
** structure the flags byte is set to 0x02 or 0x0A, indicating an index
** b-tree).
*/
static int moveToRoot(BtCursor *pCur){
MemPage *pRoot;
int rc = SQLITE_OK;
assert( cursorOwnsBtShared(pCur) );
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
assert( pCur->eState < CURSOR_REQUIRESEEK || pCur->iPage<0 );
assert( pCur->pgnoRoot>0 || pCur->iPage<0 );
if( pCur->iPage>=0 ){
if( pCur->iPage ){
releasePageNotNull(pCur->pPage);
while( --pCur->iPage ){
releasePageNotNull(pCur->apPage[pCur->iPage]);
}
pRoot = pCur->pPage = pCur->apPage[0];
goto skip_init;
}
}else if( pCur->pgnoRoot==0 ){
pCur->eState = CURSOR_INVALID;
return SQLITE_EMPTY;
}else{
assert( pCur->iPage==(-1) );
if( pCur->eState>=CURSOR_REQUIRESEEK ){
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
return pCur->skipNext;
}
sqlite3BtreeClearCursor(pCur);
}
rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage,
pCur->curPagerFlags);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
}
pCur->iPage = 0;
pCur->curIntKey = pCur->pPage->intKey;
}
pRoot = pCur->pPage;
assert( pRoot->pgno==pCur->pgnoRoot || CORRUPT_DB );
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
** NULL, the caller expects a table b-tree. If this is not the case,
** return an SQLITE_CORRUPT error.
**
** Earlier versions of SQLite assumed that this test could not fail
** if the root page was already loaded when this function was called (i.e.
** if pCur->iPage>=0). But this is not so if the database is corrupted
** in such a way that page pRoot is linked into a second b-tree table
** (or the freelist). */
assert( pRoot->intKey==1 || pRoot->intKey==0 );
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
return SQLITE_CORRUPT_PAGE(pCur->pPage);
}
skip_init:
pCur->ix = 0;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID;
}else if( !pRoot->leaf ){
Pgno subpage;
if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
pCur->eState = CURSOR_VALID;
rc = moveToChild(pCur, subpage);
}else{
pCur->eState = CURSOR_INVALID;
rc = SQLITE_EMPTY;
}
return rc;
}
/*
** Move the cursor down to the left-most leaf entry beneath the
** entry to which it is currently pointing.
**
** The left-most leaf is the one with the smallest key - the first
** in ascending order.
*/
static int moveToLeftmost(BtCursor *pCur){
Pgno pgno;
int rc = SQLITE_OK;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
assert( pCur->ix<pPage->nCell );
pgno = get4byte(findCell(pPage, pCur->ix));
rc = moveToChild(pCur, pgno);
}
return rc;
}
/*
** Move the cursor down to the right-most leaf entry beneath the
** page to which it is currently pointing. Notice the difference
** between moveToLeftmost() and moveToRightmost(). moveToLeftmost()
** finds the left-most entry beneath the *entry* whereas moveToRightmost()
** finds the right-most entry beneath the *page*.
**
** The right-most entry is the one with the largest key - the last
** key in ascending order.
*/
static int moveToRightmost(BtCursor *pCur){
Pgno pgno;
int rc = SQLITE_OK;
MemPage *pPage = 0;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
while( !(pPage = pCur->pPage)->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
pCur->ix = pPage->nCell;
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
}
pCur->ix = pPage->nCell-1;
assert( pCur->info.nSize==0 );
assert( (pCur->curFlags & BTCF_ValidNKey)==0 );
return SQLITE_OK;
}
/* Move the cursor to the first entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
*/
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
int rc;
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
assert( pCur->pPage->nCell>0 );
*pRes = 0;
rc = moveToLeftmost(pCur);
}else if( rc==SQLITE_EMPTY ){
assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) );
*pRes = 1;
rc = SQLITE_OK;
}
return rc;
}
/* Set *pRes to 1 (true) if the BTree pointed to by cursor pCur contains zero
** rows of content. Set *pRes to 0 (false) if the table contains content.
** Return SQLITE_OK on success or some error code (ex: SQLITE_NOMEM) if
** something goes wrong.
*/
SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){
int rc;
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
if( pCur->eState==CURSOR_VALID ){
*pRes = 0;
return SQLITE_OK;
}
rc = moveToRoot(pCur);
if( rc==SQLITE_EMPTY ){
*pRes = 1;
rc = SQLITE_OK;
}else{
*pRes = 0;
}
return rc;
}
#ifdef SQLITE_DEBUG
/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
** this flags are true for a consistent database.
**
** This routine is is called from within assert() statements only.
** It is an internal verification routine and does not appear in production
** builds.
*/
static int cursorIsAtLastEntry(BtCursor *pCur){
int ii;
for(ii=0; ii<pCur->iPage; ii++){
if( pCur->aiIdx[ii]!=pCur->apPage[ii]->nCell ) return 0;
}
return pCur->ix==pCur->pPage->nCell-1 && pCur->pPage->leaf!=0;
}
#endif
/* Move the cursor to the last entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
*/
static SQLITE_NOINLINE int btreeLast(BtCursor *pCur, int *pRes){
int rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
assert( pCur->eState==CURSOR_VALID );
*pRes = 0;
rc = moveToRightmost(pCur);
if( rc==SQLITE_OK ){
pCur->curFlags |= BTCF_AtLast;
}else{
pCur->curFlags &= ~BTCF_AtLast;
}
}else if( rc==SQLITE_EMPTY ){
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
*pRes = 1;
rc = SQLITE_OK;
}
return rc;
}
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
*pRes = 0;
return SQLITE_OK;
}
return btreeLast(pCur, pRes);
}
/* Move the cursor so that it points to an entry in a table (a.k.a INTKEY)
** table near the key intKey. Return a success code.
**
** 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
** were present. The cursor might point to an entry that comes
** before or after the key.
**
** An integer is written into *pRes which is the result of
** comparing the key with the entry to which the cursor is
** pointing. The meaning of the integer written into
** *pRes is as follows:
**
** *pRes<0 The cursor is left pointing at an entry that
** is smaller than intKey or if the table is empty
** and the cursor is therefore left point to nothing.
**
** *pRes==0 The cursor is left pointing at an entry that
** exactly matches intKey.
**
** *pRes>0 The cursor is left pointing at an entry that
** is larger than intKey.
*/
SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
BtCursor *pCur, /* The cursor to be moved */
i64 intKey, /* The table key */
int biasRight, /* If true, bias the search to the high end */
int *pRes /* Write search results here */
){
int rc;
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( pRes );
assert( pCur->pKeyInfo==0 );
assert( pCur->eState!=CURSOR_VALID || pCur->curIntKey!=0 );
/* 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->curFlags & BTCF_ValidNKey)!=0 ){
if( pCur->info.nKey==intKey ){
*pRes = 0;
return SQLITE_OK;
}
if( pCur->info.nKey<intKey ){
if( (pCur->curFlags & BTCF_AtLast)!=0 ){
assert( cursorIsAtLastEntry(pCur) || CORRUPT_DB );
*pRes = -1;
return SQLITE_OK;
}
/* If the requested key is one more than the previous key, then
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
** is still obtained without this case, only a little more slowly. */
if( pCur->info.nKey+1==intKey ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, 0);
if( rc==SQLITE_OK ){
getCellInfo(pCur);
if( pCur->info.nKey==intKey ){
return SQLITE_OK;
}
}else if( rc!=SQLITE_DONE ){
return rc;
}
}
}
}
#ifdef SQLITE_DEBUG
pCur->pBtree->nSeek++; /* Performance measurement during testing */
#endif
rc = moveToRoot(pCur);
if( rc ){
if( rc==SQLITE_EMPTY ){
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
*pRes = -1;
return SQLITE_OK;
}
return rc;
}
assert( pCur->pPage );
assert( pCur->pPage->isInit );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->pPage->nCell > 0 );
assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
assert( pCur->curIntKey );
for(;;){
int lwr, upr, idx, c;
Pgno chldPg;
MemPage *pPage = pCur->pPage;
u8 *pCell; /* Pointer to current cell in pPage */
/* pPage->nCell must be greater than zero. If this is the root-page
** the cursor would have been INVALID above and this for(;;) loop
** not run. If this is not the root-page, then the moveToChild() routine
** would have already detected db corruption. Similarly, pPage must
** be the right kind (index or table) of b-tree page. Otherwise
** a moveToChild() or moveToRoot() call would have detected corruption. */
assert( pPage->nCell>0 );
assert( pPage->intKey );
lwr = 0;
upr = pPage->nCell-1;
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
for(;;){
i64 nCellKey;
pCell = findCellPastPtr(pPage, idx);
if( pPage->intKeyLeaf ){
while( 0x80 <= *(pCell++) ){
if( pCell>=pPage->aDataEnd ){
return SQLITE_CORRUPT_PAGE(pPage);
}
}
}
getVarint(pCell, (u64*)&nCellKey);
if( nCellKey<intKey ){
lwr = idx+1;
if( lwr>upr ){ c = -1; break; }
}else if( nCellKey>intKey ){
upr = idx-1;
if( lwr>upr ){ c = +1; break; }
}else{
assert( nCellKey==intKey );
pCur->ix = (u16)idx;
if( !pPage->leaf ){
lwr = idx;
goto moveto_table_next_layer;
}else{
pCur->curFlags |= BTCF_ValidNKey;
pCur->info.nKey = nCellKey;
pCur->info.nSize = 0;
*pRes = 0;
return SQLITE_OK;
}
}
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
}
assert( lwr==upr+1 || !pPage->leaf );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->ix<pCur->pPage->nCell );
pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto moveto_table_finish;
}
moveto_table_next_layer:
if( lwr>=pPage->nCell ){
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
pCur->ix = (u16)lwr;
if( rc ) break;
}
moveto_table_finish:
pCur->info.nSize = 0;
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
return rc;
}
/*
** Compare the "idx"-th cell on the page pPage against the key
** pointing to by pIdxKey using xRecordCompare. Return negative or
** zero if the cell is less than or equal pIdxKey. Return positive
** if unknown.
**
** Return value negative: Cell at pCur[idx] less than pIdxKey
**
** Return value is zero: Cell at pCur[idx] equals pIdxKey
**
** Return value positive: Nothing is known about the relationship
** of the cell at pCur[idx] and pIdxKey.
**
** This routine is part of an optimization. It is always safe to return
** a positive value as that will cause the optimization to be skipped.
*/
static int indexCellCompare(
MemPage *pPage,
int idx,
UnpackedRecord *pIdxKey,
RecordCompare xRecordCompare
){
int c;
int nCell; /* Size of the pCell cell in bytes */
u8 *pCell = findCellPastPtr(pPage, idx);
nCell = pCell[0];
if( nCell<=pPage->max1bytePayload ){
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* If the record extends into overflow pages, do not attempt
** the optimization. */
c = 99;
}
return c;
}
/*
** Return true (non-zero) if pCur is current pointing to the last
** page of a table.
*/
static int cursorOnLastPage(BtCursor *pCur){
int i;
assert( pCur->eState==CURSOR_VALID );
for(i=0; i<pCur->iPage; i++){
MemPage *pPage = pCur->apPage[i];
if( pCur->aiIdx[i]<pPage->nCell ) return 0;
}
return 1;
}
/* Move the cursor so that it points to an entry in an index table
** near the key pIdxKey. Return a success code.
**
** 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
** were present. The cursor might point to an entry that comes
** before or after the key.
**
** An integer is written into *pRes which is the result of
** comparing the key with the entry to which the cursor is
** pointing. The meaning of the integer written into
** *pRes is as follows:
**
** *pRes<0 The cursor is left pointing at an entry that
** is smaller than pIdxKey or if the table is empty
** and the cursor is therefore left point to nothing.
**
** *pRes==0 The cursor is left pointing at an entry that
** exactly matches pIdxKey.
**
** *pRes>0 The cursor is left pointing at an entry that
** is larger than pIdxKey.
**
** The pIdxKey->eqSeen field is set to 1 if there
** exists an entry in the table that exactly matches pIdxKey.
*/
SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
BtCursor *pCur, /* The cursor to be moved */
UnpackedRecord *pIdxKey, /* Unpacked index key */
int *pRes /* Write search results here */
){
int rc;
RecordCompare xRecordCompare;
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( pRes );
assert( pCur->pKeyInfo!=0 );
#ifdef SQLITE_DEBUG
pCur->pBtree->nSeek++; /* Performance measurement during testing */
#endif
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->errCode = 0;
assert( pIdxKey->default_rc==1
|| pIdxKey->default_rc==0
|| pIdxKey->default_rc==-1
);
/* Check to see if we can skip a lot of work. Two cases:
**
** (1) If the cursor is already pointing to the very last cell
** in the table and the pIdxKey search key is greater than or
** equal to that last cell, then no movement is required.
**
** (2) If the cursor is on the last page of the table and the first
** cell on that last page is less than or equal to the pIdxKey
** search key, then we can start the search on the current page
** without needing to go back to root.
*/
if( pCur->eState==CURSOR_VALID
&& pCur->pPage->leaf
&& cursorOnLastPage(pCur)
){
int c;
if( pCur->ix==pCur->pPage->nCell-1
&& (c = indexCellCompare(pCur->pPage,pCur->ix,pIdxKey,xRecordCompare))<=0
&& pIdxKey->errCode==SQLITE_OK
){
*pRes = c;
return SQLITE_OK; /* Cursor already pointing at the correct spot */
}
if( pCur->iPage>0
&& indexCellCompare(pCur->pPage, 0, pIdxKey, xRecordCompare)<=0
&& pIdxKey->errCode==SQLITE_OK
){
pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
if( !pCur->pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
goto bypass_moveto_root; /* Start search on the current page */
}
pIdxKey->errCode = SQLITE_OK;
}
rc = moveToRoot(pCur);
if( rc ){
if( rc==SQLITE_EMPTY ){
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
*pRes = -1;
return SQLITE_OK;
}
return rc;
}
bypass_moveto_root:
assert( pCur->pPage );
assert( pCur->pPage->isInit );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->pPage->nCell > 0 );
assert( pCur->curIntKey==0 );
assert( pIdxKey!=0 );
for(;;){
int lwr, upr, idx, c;
Pgno chldPg;
MemPage *pPage = pCur->pPage;
u8 *pCell; /* Pointer to current cell in pPage */
/* pPage->nCell must be greater than zero. If this is the root-page
** the cursor would have been INVALID above and this for(;;) loop
** not run. If this is not the root-page, then the moveToChild() routine
** would have already detected db corruption. Similarly, pPage must
** be the right kind (index or table) of b-tree page. Otherwise
** a moveToChild() or moveToRoot() call would have detected corruption. */
assert( pPage->nCell>0 );
assert( pPage->intKey==0 );
lwr = 0;
upr = pPage->nCell-1;
idx = upr>>1; /* idx = (lwr+upr)/2; */
for(;;){
int nCell; /* Size of the pCell cell in bytes */
pCell = findCellPastPtr(pPage, idx);
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is less than 16384 bytes and may be stored as a 2-byte
** varint. This information is used to attempt to avoid parsing
** the entire cell by checking for the cases where the record is
** stored entirely within the b-tree page by inspecting the first
** 2 bytes of the cell.
*/
nCell = pCell[0];
if( nCell<=pPage->max1bytePayload ){
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* The record flows over onto one or more overflow pages. In
** this case the whole cell needs to be parsed, a buffer allocated
** and accessPayload() used to retrieve the record into the
** buffer before VdbeRecordCompare() can be called.
**
** If the record is corrupt, the xRecordCompare routine may read
** up to two varints past the end of the buffer. An extra 18
** bytes of padding is allocated at the end of the buffer in
** case this happens. */
void *pCellKey;
u8 * const pCellBody = pCell - pPage->childPtrSize;
const int nOverrun = 18; /* Size of the overrun padding */
pPage->xParseCell(pPage, pCellBody, &pCur->info);
nCell = (int)pCur->info.nKey;
testcase( nCell<0 ); /* True if key size is 2^32 or more */
testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
rc = SQLITE_CORRUPT_PAGE(pPage);
goto moveto_index_finish;
}
pCellKey = sqlite3Malloc( (u64)nCell+(u64)nOverrun );
if( pCellKey==0 ){
pCur->ix = (u16)idx;
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
goto moveto_index_finish;
}
if( lwr>upr ) break;
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
}
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto moveto_index_finish;
}
if( lwr>=pPage->nCell ){
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
/* This block is similar to an in-lined version of:
**
** pCur->ix = (u16)lwr;
** rc = moveToChild(pCur, chldPg);
** if( rc ) break;
*/
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
return SQLITE_CORRUPT_BKPT;
}
pCur->aiIdx[pCur->iPage] = (u16)lwr;
pCur->apPage[pCur->iPage] = pCur->pPage;
pCur->ix = 0;
pCur->iPage++;
rc = getAndInitPage(pCur->pBt, chldPg, &pCur->pPage, pCur->curPagerFlags);
if( rc==SQLITE_OK
&& (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey)
){
releasePage(pCur->pPage);
rc = SQLITE_CORRUPT_PGNO(chldPg);
}
if( rc ){
pCur->pPage = pCur->apPage[--pCur->iPage];
break;
}
/*
***** End of in-lined moveToChild() call */
}
moveto_index_finish:
pCur->info.nSize = 0;
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
return rc;
}
/*
** Return TRUE if the cursor is not pointing at an entry of the table.
**
** TRUE will be returned after a call to sqlite3BtreeNext() moves
** past the last entry in the table or sqlite3BtreePrev() moves past
** the first entry. TRUE is also returned if the table is empty.
*/
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
/* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries
** have been deleted? This API will need to change to return an error code
** as well as the boolean result value.
*/
return (CURSOR_VALID!=pCur->eState);
}
/*
** Return an estimate for the number of rows in the table that pCur is
** pointing to. Return a negative number if no estimate is currently
** available.
*/
SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
i64 n;
u8 i;
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* Currently this interface is only called by the OP_IfSizeBetween
** opcode and the OP_Count opcode with P3=1. In either case,
** the cursor will always be valid unless the btree is empty. */
if( pCur->eState!=CURSOR_VALID ) return 0;
if( NEVER(pCur->pPage->leaf==0) ) return -1;
n = pCur->pPage->nCell;
for(i=0; i<pCur->iPage; i++){
n *= pCur->apPage[i]->nCell+1;
}
return n;
}
/*
** Advance the cursor to the next entry in the database.
** Return value:
**
** SQLITE_OK success
** SQLITE_DONE cursor is already pointing at the last element
** otherwise some kind of error occurred
**
** The main entry point is sqlite3BtreeNext(). That routine is optimized
** for the common case of merely incrementing the cell counter BtCursor.aiIdx
** to the next cell on the current page. The (slower) btreeNext() helper
** routine is called when it is necessary to move to a different page or
** to restore the cursor.
**
** If bit 0x01 of the F argument in sqlite3BtreeNext(C,F) is 1, then the
** cursor corresponds to an SQL index and this routine could have been
** skipped if the SQL index had been a unique index. The F argument
** is a hint to the implement. SQLite btree implementation does not use
** this hint, but COMDB2 does.
*/
static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
int rc;
int idx;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
if( pCur->eState!=CURSOR_VALID ){
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
if( pCur->skipNext>0 ) return SQLITE_OK;
}
}
pPage = pCur->pPage;
idx = ++pCur->ix;
if( sqlite3FaultSim(412) ) pPage->isInit = 0;
if( !pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
if( rc ) return rc;
return moveToLeftmost(pCur);
}
do{
if( pCur->iPage==0 ){
pCur->eState = CURSOR_INVALID;
return SQLITE_DONE;
}
moveToParent(pCur);
pPage = pCur->pPage;
}while( pCur->ix>=pPage->nCell );
if( pPage->intKey ){
return sqlite3BtreeNext(pCur, 0);
}else{
return SQLITE_OK;
}
}
if( pPage->leaf ){
return SQLITE_OK;
}else{
return moveToLeftmost(pCur);
}
}
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int flags){
MemPage *pPage;
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
pPage = pCur->pPage;
if( (++pCur->ix)>=pPage->nCell ){
pCur->ix--;
return btreeNext(pCur);
}
if( pPage->leaf ){
return SQLITE_OK;
}else{
return moveToLeftmost(pCur);
}
}
/*
** Step the cursor to the back to the previous entry in the database.
** Return values:
**
** SQLITE_OK success
** SQLITE_DONE the cursor is already on the first element of the table
** otherwise some kind of error occurred
**
** The main entry point is sqlite3BtreePrevious(). That routine is optimized
** for the common case of merely decrementing the cell counter BtCursor.aiIdx
** to the previous cell on the current page. The (slower) btreePrevious()
** helper routine is called when it is necessary to move to a different page
** or to restore the cursor.
**
** If bit 0x01 of the F argument to sqlite3BtreePrevious(C,F) is 1, then
** the cursor corresponds to an SQL index and this routine could have been
** skipped if the SQL index had been a unique index. The F argument is a
** hint to the implement. The native SQLite btree implementation does not
** use this hint, but COMDB2 does.
*/
static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
int rc;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){
rc = restoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
if( CURSOR_SKIPNEXT==pCur->eState ){
pCur->eState = CURSOR_VALID;
if( pCur->skipNext<0 ) return SQLITE_OK;
}
}
pPage = pCur->pPage;
if( sqlite3FaultSim(412) ) pPage->isInit = 0;
if( !pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
if( !pPage->leaf ){
int idx = pCur->ix;
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
if( rc ) return rc;
rc = moveToRightmost(pCur);
}else{
while( pCur->ix==0 ){
if( pCur->iPage==0 ){
pCur->eState = CURSOR_INVALID;
return SQLITE_DONE;
}
moveToParent(pCur);
}
assert( pCur->info.nSize==0 );
assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 );
pCur->ix--;
pPage = pCur->pPage;
if( pPage->intKey && !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, 0);
}else{
rc = SQLITE_OK;
}
}
return rc;
}
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
if( pCur->eState!=CURSOR_VALID
|| pCur->ix==0
|| pCur->pPage->leaf==0
){
return btreePrevious(pCur);
}
pCur->ix--;
return SQLITE_OK;
}
/*
** Allocate a new page from the database file.
**
** The new page is marked as dirty. (In other words, sqlite3PagerWrite()
** has already been called on the new page.) The new page has also
** been referenced and the calling routine is responsible for calling
** sqlite3PagerUnref() on the new page when it is done.
**
** SQLITE_OK is returned on success. Any other return value indicates
** an error. *ppPage is set to NULL in the event of an error.
**
** If the "nearby" parameter is not 0, then an effort is made to
** locate a page close to the page number "nearby". This can be used in an
** attempt to keep related pages close to each other in the database file,
** which in turn can make database access faster.
**
** If the eMode parameter is BTALLOC_EXACT and the nearby page exists
** anywhere on the free-list, then it is guaranteed to be returned. If
** eMode is BTALLOC_LT then the page returned will be less than or equal
** to nearby if any such page exists. If eMode is BTALLOC_ANY then there
** are no restrictions on which page is returned.
*/
static int allocateBtreePage(
BtShared *pBt, /* The btree */
MemPage **ppPage, /* Store pointer to the allocated page here */
Pgno *pPgno, /* Store the page number here */
Pgno nearby, /* Search for a page near this one */
u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
){
MemPage *pPage1;
int rc;
u32 n; /* Number of pages on the freelist */
u32 k; /* Number of leaves on the trunk of the freelist */
MemPage *pTrunk = 0;
MemPage *pPrevTrunk = 0;
Pgno mxPage; /* Total size of the database file */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) );
pPage1 = pBt->pPage1;
mxPage = btreePagecount(pBt);
/* EVIDENCE-OF: R-21003-45125 The 4-byte big-endian integer at offset 36
** stores the total number of pages on the freelist. */
n = get4byte(&pPage1->aData[36]);
testcase( n==mxPage-1 );
if( n>=mxPage ){
if( pPage ){
pPage->isInit = 0;
}
releasePage(pPage);
releasePage(pTrunk);
return rc;
}
static void freePage(MemPage *pPage, int *pRC){
if( (*pRC)==SQLITE_OK ){
*pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
}
}
/*
** Free the overflow pages associated with the given Cell.
*/
static SQLITE_NOINLINE int clearCellOverflow(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
CellInfo *pInfo /* Size information about the cell */
){
BtShared *pBt;
Pgno ovflPgno;
int rc;
int nOvfl;
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( pInfo->nLocal!=pInfo->nPayload );
testcase( pCell + pInfo->nSize == pPage->aDataEnd );
testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
if( pCell + pInfo->nSize > pPage->aDataEnd ){
/* Cell extends past end of page */
return SQLITE_CORRUPT_PAGE(pPage);
}
ovflPgno = get4byte(pCell + pInfo->nSize - 4);
pBt = pPage->pBt;
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
assert( nOvfl>0 ||
(CORRUPT_DB && (pInfo->nPayload + ovflPageSize)<ovflPageSize)
);
while( nOvfl-- ){
Pgno iNext = 0;
MemPage *pOvfl = 0;
if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){
/* 0 is not a legal page number and page 1 cannot be an
** overflow page. Therefore if ovflPgno<2 or past the end of the
** file the database must be corrupt. */
return SQLITE_CORRUPT_BKPT;
}
if( nOvfl ){
rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
if( rc ) return rc;
}
if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
&& sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
){
/* There is no reason any cursor should have an outstanding reference
** to an overflow page belonging to a cell that is being deleted/updated.
** So if there exists more than one reference to this page, then it
** must not really be an overflow page and the database must be corrupt.
** It is helpful to detect this before calling freePage2(), as
** freePage2() may zero the page contents if secure-delete mode is
** enabled. If this 'overflow' page happens to be a page that the
** caller is iterating through or using in some other way, this
** can be problematic.
*/
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = freePage2(pBt, pOvfl, ovflPgno);
}
if( pOvfl ){
sqlite3PagerUnref(pOvfl->pDbPage);
}
if( rc ) return rc;
ovflPgno = iNext;
}
return SQLITE_OK;
}
/* Call xParseCell to compute the size of a cell. If the cell contains
** overflow, then invoke cellClearOverflow to clear out that overflow.
** Store the result code (SQLITE_OK or some error code) in rc.
**
** Implemented as macro to force inlining for performance.
*/
#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo) \
pPage->xParseCell(pPage, pCell, &sInfo); \
if( sInfo.nLocal!=sInfo.nPayload ){ \
rc = clearCellOverflow(pPage, pCell, &sInfo); \
}else{ \
rc = SQLITE_OK; \
}
/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[]. Overflow pages are
** allocated and filled in as necessary. The calling procedure
** is responsible for making sure sufficient space has been allocated
** for pCell[].
**
** Note that pCell does not necessary need to point to the pPage->aData
** area. pCell might point to some temporary storage. The cell will
** be constructed in this temporary area then copied into pPage->aData
** later.
*/
static int fillInCell(
MemPage *pPage, /* The page that contains the cell */
unsigned char *pCell, /* Complete text of the cell */
const BtreePayload *pX, /* Payload with which to construct the cell */
int *pnSize /* Write cell size here */
){
int nPayload;
const u8 *pSrc;
int nSrc, n, rc, mn;
int spaceLeft;
** pointer pointing to the new page.
**
** Before returning, all pointer-map entries corresponding to pages
** that the new child-page now contains pointers to are updated. The
** entry corresponding to the new right-child pointer of the root
** page is also updated.
**
** If successful, *ppChild is set to contain a reference to the child
** page and SQLITE_OK is returned. In this case the caller is required
** to call releasePage() on *ppChild exactly once. If an error occurs,
** an error code is returned and *ppChild is set to 0.
*/
static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
int rc; /* Return value from subprocedures */
MemPage *pChild = 0; /* Pointer to a new child page */
Pgno pgnoChild = 0; /* Page number of the new child page */
BtShared *pBt = pRoot->pBt; /* The BTree */
assert( pRoot->nOverflow>0 );
assert( sqlite3_mutex_held(pBt->mutex) );
/* Make pRoot, the root page of the b-tree, writable. Allocate a new
** page that will become the new right-child of pPage. Copy the contents
** of the node stored on pRoot into the new child page.
*/
rc = sqlite3PagerWrite(pRoot->pDbPage);
if( rc==SQLITE_OK ){
rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
copyNodeContent(pRoot, pChild, &rc);
if( ISAUTOVACUUM(pBt) ){
ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc);
}
}
if( rc ){
*ppChild = 0;
releasePage(pChild);
return rc;
}
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
assert( pChild->nCell==pRoot->nCell || CORRUPT_DB );
TRACE(("BALANCE: copy root %u into %u\n", pRoot->pgno, pChild->pgno));
/* Copy the overflow cells from pRoot to pChild */
memcpy(pChild->aiOvfl, pRoot->aiOvfl,
pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
memcpy(pChild->apOvfl, pRoot->apOvfl,
pRoot->nOverflow*sizeof(pRoot->apOvfl[0]));
pChild->nOverflow = pRoot->nOverflow;
/* Zero the contents of pRoot. Then install pChild as the right-child. */
zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF);
put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);
*ppChild = pChild;
return SQLITE_OK;
}
/*
** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
** on the same B-tree as pCur.
**
** This can occur if a database is corrupt with two or more SQL tables
** pointing to the same b-tree. If an insert occurs on one SQL table
** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
** table linked to the same b-tree. If the secondary insert causes a
** rebalance, that can change content out from under the cursor on the
** first SQL table, violating invariants on the first insert.
*/
static int anotherValidCursor(BtCursor *pCur){
BtCursor *pOther;
for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){
if( pOther!=pCur
&& pOther->eState==CURSOR_VALID
&& pOther->pPage==pCur->pPage
){
return SQLITE_CORRUPT_PAGE(pCur->pPage);
}
}
return SQLITE_OK;
}
/*
** The page that pCur currently points to has just been modified in
** some way. This function figures out if this modification means the
** tree needs to be balanced, and if so calls the appropriate balancing
** routine. Balancing routines are:
**
** balance_quick()
** balance_deeper()
** balance_nonroot()
*/
static int balance(BtCursor *pCur){
int rc = SQLITE_OK;
u8 aBalanceQuickSpace[13];
u8 *pFree = 0;
VVA_ONLY( int balance_quick_called = 0 );
VVA_ONLY( int balance_deeper_called = 0 );
do {
int iPage;
MemPage *pPage = pCur->pPage;
if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
if( pPage->nOverflow==0 && pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
/* No rebalance required as long as:
** (1) There are no overflow cells
** (2) The amount of free space on the page is less than 2/3rds of
** the total usable space on the page. */
break;
}else if( (iPage = pCur->iPage)==0 ){
if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
/* The root page of the b-tree is overfull. In this case call the
** balance_deeper() function to create a new child for the root-page
** and copy the current contents of the root-page to it. The
** next iteration of the do-loop will balance the child page.
*/
assert( balance_deeper_called==0 );
VVA_ONLY( balance_deeper_called++ );
rc = balance_deeper(pPage, &pCur->apPage[1]);
if( rc==SQLITE_OK ){
pCur->iPage = 1;
pCur->ix = 0;
pCur->aiIdx[0] = 0;
pCur->apPage[0] = pPage;
pCur->pPage = pCur->apPage[1];
pPage->nOverflow = 0;
/* The next iteration of the do-loop balances the parent page. */
releasePage(pPage);
pCur->iPage--;
assert( pCur->iPage>=0 );
pCur->pPage = pCur->apPage[pCur->iPage];
}
}while( rc==SQLITE_OK );
if( pFree ){
sqlite3PageFree(pFree);
}
return rc;
}
/* Overwrite content from pX into pDest. Only do the write if the
** content is different from what is already there.
*/
static int btreeOverwriteContent(
MemPage *pPage, /* MemPage on which writing will occur */
u8 *pDest, /* Pointer to the place to start writing */
const BtreePayload *pX, /* Source of data to write */
int iOffset, /* Offset of first byte to write */
int iAmt /* Number of bytes to be written */
){
int nData = pX->nData - iOffset;
if( nData<=0 ){
/* Overwriting with zeros */
int i;
for(i=0; i<iAmt && pDest[i]==0; i++){}
if( i<iAmt ){
int rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
memset(pDest + i, 0, iAmt - i);
}
}else{
if( nData<iAmt ){
/* Mixed read data and zeros at the end. Make a recursive call
** to write the zeros then fall through to write the real data */
int rc = btreeOverwriteContent(pPage, pDest+nData, pX, iOffset+nData,
iAmt-nData);
if( rc ) return rc;
iAmt = nData;
}
if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
int rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
/* In a corrupt database, it is possible for the source and destination
** buffers to overlap. This is harmless since the database is already
** corrupt but it does cause valgrind and ASAN warnings. So use
** memmove(). */
memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
}
}
return SQLITE_OK;
}
/*
** Overwrite the cell that cursor pCur is pointing to with fresh content
** contained in pX. In this variant, pCur is pointing to an overflow
** cell.
*/
static SQLITE_NOINLINE int btreeOverwriteOverflowCell(
BtCursor *pCur, /* Cursor pointing to cell to overwrite */
const BtreePayload *pX /* Content to write into the cell */
){
int iOffset; /* Next byte of pX->pData to write */
int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
int rc; /* Return code */
MemPage *pPage = pCur->pPage; /* Page being written */
BtShared *pBt; /* Btree */
Pgno ovflPgno; /* Next overflow page to write */
u32 ovflPageSize; /* Size to write on overflow page */
assert( pCur->info.nLocal<nTotal ); /* pCur is an overflow cell */
/* Overwrite the local portion first */
rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
0, pCur->info.nLocal);
if( rc ) return rc;
/* Now overwrite the overflow pages */
iOffset = pCur->info.nLocal;
assert( nTotal>=0 );
assert( iOffset>=0 );
ovflPgno = get4byte(pCur->info.pPayload + iOffset);
pBt = pPage->pBt;
ovflPageSize = pBt->usableSize - 4;
do{
rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
if( rc ) return rc;
if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || pPage->isInit ){
rc = SQLITE_CORRUPT_PAGE(pPage);
}else{
if( iOffset+ovflPageSize<(u32)nTotal ){
ovflPgno = get4byte(pPage->aData);
}else{
ovflPageSize = nTotal - iOffset;
}
rc = btreeOverwriteContent(pPage, pPage->aData+4, pX,
iOffset, ovflPageSize);
}
sqlite3PagerUnref(pPage->pDbPage);
if( rc ) return rc;
iOffset += ovflPageSize;
}while( iOffset<nTotal );
return SQLITE_OK;
}
/*
** Overwrite the cell that cursor pCur is pointing to with fresh content
** contained in pX.
*/
static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
MemPage *pPage = pCur->pPage; /* Page being written */
if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
|| pCur->info.pPayload < pPage->aData + pPage->cellOffset
){
return SQLITE_CORRUPT_PAGE(pPage);
}
if( pCur->info.nLocal==nTotal ){
/* The entire cell is local */
return btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
0, pCur->info.nLocal);
}else{
/* The cell contains overflow content */
return btreeOverwriteOverflowCell(pCur, pX);
}
}
/*
** Insert a new record into the BTree. The content of the new record
** is described by the pX object. The pCur cursor is used only to
** define what table the record should be inserted into, and is left
** pointing at a random location.
**
** For a table btree (used for rowid tables), only the pX.nKey value of
** the key is used. The pX.pKey value must be NULL. The pX.nKey is the
** rowid or INTEGER PRIMARY KEY of the row. The pX.nData,pData,nZero fields
** hold the content of the row.
**
** For an index btree (used for indexes and WITHOUT ROWID tables), the
** key is an arbitrary byte sequence stored in pX.pKey,nKey. The
** pX.pData,nData,nZero fields must be zero.
**
** If the seekResult parameter is non-zero, then a successful call to
** sqlite3BtreeIndexMoveto() to seek cursor pCur to (pKey,nKey) has already
** been performed. In other words, if seekResult!=0 then the cursor
** is currently pointing to a cell that will be adjacent to the cell
** to be inserted. If seekResult<0 then pCur points to a cell that is
** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell
** that is larger than (pKey,nKey).
**
** If seekResult==0, that means pCur is pointing at some unknown location.
** In that case, this routine must seek the cursor to the correct insertion
** point for (pKey,nKey) before doing the insertion. For index btrees,
** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked
** key values and pX->aMem can be used instead of pX->pKey to avoid having
** to decode the key.
*/
SQLITE_PRIVATE int sqlite3BtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const BtreePayload *pX, /* Content of the row to be inserted */
int flags, /* True if this is likely an append */
int seekResult /* Result of prior IndexMoveto() call */
){
int rc;
int loc = seekResult; /* -1: before desired location +1: after */
int szNew = 0;
int idx;
MemPage *pPage;
Btree *p = pCur->pBtree;
unsigned char *oldCell;
unsigned char *newCell = 0;
assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
/* Save the positions of any other cursors open on this table.
**
** In some cases, the call to btreeMoveto() below is a no-op. For
** example, when inserting data into a table with auto-generated integer
** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
** integer key to use. It then calls this function to actually insert the
** data into the intkey B-Tree. In this case btreeMoveto() recognizes
** that the cursor is already where it needs to be and returns without
** doing any work. To avoid thwarting these optimizations, it is important
** not to clear the cursor here.
*/
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(p->pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
if( loc && pCur->iPage<0 ){
/* This can only happen if the schema is corrupt such that there is more
** than one table or index with the same root page as used by the cursor.
** Which can only happen if the SQLITE_NoSchemaError flag was set when
** the schema was loaded. This cannot be asserted though, as a user might
** set the flag, load the schema, and then unset the flag. */
return SQLITE_CORRUPT_PGNO(pCur->pgnoRoot);
}
}
/* Ensure that the cursor is not in the CURSOR_FAULT state and that it
** points to a valid cell.
*/
if( pCur->eState>=CURSOR_REQUIRESEEK ){
testcase( pCur->eState==CURSOR_REQUIRESEEK );
testcase( pCur->eState==CURSOR_FAULT );
rc = moveToRoot(pCur);
if( rc && rc!=SQLITE_EMPTY ) return rc;
}
assert( cursorOwnsBtShared(pCur) );
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
&& p->pBt->inTransaction==TRANS_WRITE
&& (p->pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
/* Assert that the caller has been consistent. If this cursor was opened
** expecting an index b-tree, then the caller should be inserting blob
** keys with no associated data. If the cursor was opened expecting an
** intkey table, the caller should be inserting integer keys with a
** blob of associated data. */
assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
if( p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
}
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
*/
#ifdef SQLITE_DEBUG
if( flags & BTREE_SAVEPOSITION ){
assert( pCur->curFlags & BTCF_ValidNKey );
assert( pX->nKey==pCur->info.nKey );
assert( loc==0 );
}
#endif
/* On the other hand, BTREE_SAVEPOSITION==0 does not imply
** that the cursor is not pointing to a row to be overwritten.
** So do a complete check.
*/
if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){
/* The cursor is pointing to the entry that is to be
** overwritten */
assert( pX->nData>=0 && pX->nZero>=0 );
if( pCur->info.nSize!=0
&& pCur->info.nPayload==(u32)pX->nData+pX->nZero
){
/* New entry is the same size as the old. Do an overwrite */
return btreeOverwriteCell(pCur, pX);
}
assert( loc==0 );
}else if( loc==0 ){
/* The cursor is *not* pointing to the cell to be overwritten, nor
** to an adjacent cell. Move the cursor so that it is pointing either
** to the cell to be overwritten or an adjacent cell.
*/
rc = sqlite3BtreeTableMoveto(pCur, pX->nKey,
(flags & BTREE_APPEND)!=0, &loc);
if( rc ) return rc;
}
}else{
/* This is an index or a WITHOUT ROWID table */
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
*/
assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 );
/* If the cursor is not already pointing either to the cell to be
** overwritten, or if a new cell is being inserted, if the cursor is
** not pointing to an immediately adjacent cell, then move the cursor
** so that it does.
*/
if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
if( pX->nMem ){
UnpackedRecord r;
r.pKeyInfo = pCur->pKeyInfo;
r.aMem = pX->aMem;
r.nField = pX->nMem;
r.default_rc = 0;
r.eqSeen = 0;
rc = sqlite3BtreeIndexMoveto(pCur, &r, &loc);
}else{
rc = btreeMoveto(pCur, pX->pKey, pX->nKey,
(flags & BTREE_APPEND)!=0, &loc);
}
if( rc ) return rc;
}
/* If the cursor is currently pointing to an entry to be overwritten
** and the new content is the same as as the old, then use the
** overwrite optimization.
*/
if( loc==0 ){
getCellInfo(pCur);
if( pCur->info.nKey==pX->nKey ){
BtreePayload x2;
x2.pData = pX->pKey;
x2.nData = (int)pX->nKey; assert( pX->nKey<=0x7fffffff );
x2.nZero = 0;
return btreeOverwriteCell(pCur, &x2);
}
}
}
assert( pCur->eState==CURSOR_VALID
|| (pCur->eState==CURSOR_INVALID && loc) || CORRUPT_DB );
pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
if( NEVER(pCur->eState>CURSOR_INVALID) ){
/* ^^^^^--- due to the moveToRoot() call above */
rc = SQLITE_CORRUPT_PAGE(pPage);
}else{
rc = btreeComputeFreeSpace(pPage);
}
if( rc ) return rc;
}
TRACE(("INSERT: table=%u nkey=%lld ndata=%u page=%u %s\n",
pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
assert( pPage->isInit || CORRUPT_DB );
newCell = p->pBt->pTmpSpace;
assert( newCell!=0 );
assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT );
if( flags & BTREE_PREFORMAT ){
rc = SQLITE_OK;
szNew = p->pBt->nPreformatSize;
if( szNew<4 ){
szNew = 4;
newCell[3] = 0;
}
if( ISAUTOVACUUM(p->pBt) && szNew>pPage->maxLocal ){
CellInfo info;
pPage->xParseCell(pPage, newCell, &info);
if( info.nPayload!=info.nLocal ){
Pgno ovfl = get4byte(&newCell[szNew-4]);
ptrmapPut(p->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
if( NEVER(rc) ) goto end_insert;
}
}
}else{
rc = fillInCell(pPage, newCell, pX, &szNew);
if( rc ) goto end_insert;
}
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(p->pBt) );
idx = pCur->ix;
pCur->info.nSize = 0;
if( loc==0 ){
CellInfo info;
assert( idx>=0 );
if( idx>=pPage->nCell ){
return SQLITE_CORRUPT_PAGE(pPage);
}
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
goto end_insert;
}
oldCell = findCell(pPage, idx);
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
testcase( pCur->curFlags & BTCF_ValidOvfl );
invalidateOverflowCache(pCur);
if( info.nSize==szNew && info.nLocal==info.nPayload
&& (!ISAUTOVACUUM(p->pBt) || szNew<pPage->minLocal)
){
/* Overwrite the old cell with the new if they are the same size.
** We could also try to do this if the old cell is smaller, then add
** the leftover space to the free list. But experiments show that
** doing that is no faster then skipping this optimization and just
** calling dropCell() and insertCell().
**
** This optimization cannot be used on an autovacuum database if the
** new entry uses overflow pages, as the insertCell() call below is
** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
if( oldCell < pPage->aData+pPage->hdrOffset+10 ){
return SQLITE_CORRUPT_PAGE(pPage);
}
if( oldCell+szNew > pPage->aDataEnd ){
return SQLITE_CORRUPT_PAGE(pPage);
}
memcpy(oldCell, newCell, szNew);
return SQLITE_OK;
}
dropCell(pPage, idx, info.nSize, &rc);
if( rc ) goto end_insert;
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
idx = ++pCur->ix;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
}else{
assert( pPage->leaf );
}
rc = insertCellFast(pPage, idx, newCell, szNew);
assert( pPage->nOverflow==0 || rc==SQLITE_OK );
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
/* If no error has occurred and pPage has an overflow cell, call balance()
** to redistribute the cells within the tree. Since balance() may move
** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
** variables.
**
** Previous versions of SQLite called moveToRoot() to move the cursor
** back to the root page as balance() used to invalidate the contents
** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that,
** set the cursor state to "invalid". This makes common insert operations
** slightly faster.
**
** There is a subtle but important optimization here too. When inserting
** multiple records into an intkey b-tree using a single cursor (as can
** happen while processing an "INSERT INTO ... SELECT" statement), it
** is advantageous to leave the cursor pointing to the last entry in
** the b-tree if possible. If the cursor is left pointing to the last
** entry in the table, and the next row inserted has an integer key
** larger than the largest existing key, it is possible to insert the
** row without seeking the cursor. This can be a big performance boost.
*/
if( pPage->nOverflow ){
assert( rc==SQLITE_OK );
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
** fails. Internal data structure corruption will result otherwise.
** Also, set the cursor state to invalid. This stops saveCursorPosition()
** from trying to save the current position of the cursor. */
pCur->pPage->nOverflow = 0;
pCur->eState = CURSOR_INVALID;
if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){
btreeReleaseAllCursorPages(pCur);
if( pCur->pKeyInfo ){
assert( pCur->pKey==0 );
pCur->pKey = sqlite3Malloc( pX->nKey );
if( pCur->pKey==0 ){
rc = SQLITE_NOMEM;
}else{
memcpy(pCur->pKey, pX->pKey, pX->nKey);
}
}
pCur->eState = CURSOR_REQUIRESEEK;
pCur->nKey = pX->nKey;
}
}
assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 );
end_insert:
return rc;
}
/*
** This function is used as part of copying the current row from cursor
** pSrc into cursor pDest. If the cursors are open on intkey tables, then
** parameter iKey is used as the rowid value when the record is copied
** into pDest. Otherwise, the record is copied verbatim.
**
** This function does not actually write the new value to cursor pDest.
** Instead, it creates and populates any required overflow pages and
** writes the data for the new cell into the BtShared.pTmpSpace buffer
** for the destination database. The size of the cell, in bytes, is left
** in BtShared.nPreformatSize. The caller completes the insertion by
** calling sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
BtShared *pBt = pDest->pBt;
u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */
const u8 *aIn; /* Pointer to next input buffer */
u32 nIn; /* Size of input buffer aIn[] */
u32 nRem; /* Bytes of data still to copy */
getCellInfo(pSrc);
if( pSrc->info.nPayload<0x80 ){
*(aOut++) = (u8)pSrc->info.nPayload;
}else{
aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload);
}
if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
nIn = pSrc->info.nLocal;
aIn = pSrc->info.pPayload;
if( aIn+nIn>pSrc->pPage->aDataEnd ){
return SQLITE_CORRUPT_PAGE(pSrc->pPage);
}
nRem = pSrc->info.nPayload;
if( nIn==nRem && nIn<pDest->pPage->maxLocal ){
memcpy(aOut, aIn, nIn);
pBt->nPreformatSize = nIn + (int)(aOut - pBt->pTmpSpace);
return SQLITE_OK;
}else{
int rc = SQLITE_OK;
Pager *pSrcPager = pSrc->pBt->pPager;
u8 *pPgnoOut = 0;
Pgno ovflIn = 0;
DbPage *pPageIn = 0;
MemPage *pPageOut = 0;
u32 nOut; /* Size of output buffer aOut[] */
nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
pBt->nPreformatSize = (int)nOut + (int)(aOut - pBt->pTmpSpace);
if( nOut<pSrc->info.nPayload ){
pPgnoOut = &aOut[nOut];
pBt->nPreformatSize += 4;
}
if( nRem>nIn ){
if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
return SQLITE_CORRUPT_PAGE(pSrc->pPage);
}
ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
}
do {
nRem -= nOut;
do{
assert( nOut>0 );
if( nIn>0 ){
int nCopy = MIN(nOut, nIn);
memcpy(aOut, aIn, nCopy);
nOut -= nCopy;
nIn -= nCopy;
aOut += nCopy;
aIn += nCopy;
}
if( nOut>0 ){
sqlite3PagerUnref(pPageIn);
pPageIn = 0;
rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
if( rc==SQLITE_OK ){
aIn = (const u8*)sqlite3PagerGetData(pPageIn);
ovflIn = get4byte(aIn);
aIn += 4;
nIn = pSrc->pBt->usableSize - 4;
}
}
}while( rc==SQLITE_OK && nOut>0 );
if( rc==SQLITE_OK && nRem>0 && ALWAYS(pPgnoOut) ){
Pgno pgnoNew;
MemPage *pNew = 0;
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
put4byte(pPgnoOut, pgnoNew);
if( ISAUTOVACUUM(pBt) && pPageOut ){
ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
}
releasePage(pPageOut);
pPageOut = pNew;
if( pPageOut ){
pPgnoOut = pPageOut->aData;
put4byte(pPgnoOut, 0);
aOut = &pPgnoOut[4];
nOut = MIN(pBt->usableSize - 4, nRem);
}
}
}while( nRem>0 && rc==SQLITE_OK );
releasePage(pPageOut);
sqlite3PagerUnref(pPageIn);
return rc;
}
}
/*
** Delete the entry that the cursor is pointing to.
**
** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
** the cursor is left pointing at an arbitrary location after the delete.
** But if that bit is set, then the cursor is left in a state such that
** the next call to BtreeNext() or BtreePrev() moves it to the same row
** as it would have been on if the call to BtreeDelete() had been omitted.
**
** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes
** associated with a single table entry and its indexes. Only one of those
** deletes is considered the "primary" delete. The primary delete occurs
** on a cursor that is not a BTREE_FORDELETE cursor. All but one delete
** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag.
** The BTREE_AUXDELETE bit is a hint that is not used by this implementation,
** but which might be used by alternative storage engines.
*/
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
Btree *p = pCur->pBtree;
BtShared *pBt = p->pBt;
int rc; /* Return code */
MemPage *pPage; /* Page to delete cell from */
unsigned char *pCell; /* Pointer to cell to delete */
int iCellIdx; /* Index of cell to delete */
int iCellDepth; /* Depth of node containing pCell */
CellInfo info; /* Size of the cell being deleted */
u8 bPreserve; /* Keep cursor valid. 2 for CURSOR_SKIPNEXT */
assert( cursorOwnsBtShared(pCur) );
assert( pBt->inTransaction==TRANS_WRITE );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
if( pCur->eState!=CURSOR_VALID ){
if( pCur->eState>=CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
}else{
return SQLITE_CORRUPT_PGNO(pCur->pgnoRoot);
}
}
assert( pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
pPage = pCur->pPage;
if( pPage->nCell<=iCellIdx ){
return SQLITE_CORRUPT_PAGE(pPage);
}
pCell = findCell(pPage, iCellIdx);
if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){
return SQLITE_CORRUPT_PAGE(pPage);
}
if( pCell<&pPage->aCellIdx[pPage->nCell] ){
return SQLITE_CORRUPT_PAGE(pPage);
}
/* If the BTREE_SAVEPOSITION bit is on, then the cursor position must
** be preserved following this delete operation. If the current delete
** will cause a b-tree rebalance, then this is done by saving the cursor
** key and leaving the cursor in CURSOR_REQUIRESEEK state before
** returning.
**
** If the current delete will not cause a rebalance, then the cursor
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
** before or after the deleted entry.
**
** The bPreserve value records which path is required:
**
** bPreserve==0 Not necessary to save the cursor position
** bPreserve==1 Use CURSOR_REQUIRESEEK to save the cursor position
** bPreserve==2 Cursor won't move. Set CURSOR_SKIPNEXT.
*/
bPreserve = (flags & BTREE_SAVEPOSITION)!=0;
if( bPreserve ){
if( !pPage->leaf
|| (pPage->nFree+pPage->xCellSize(pPage,pCell)+2) >
(int)(pBt->usableSize*2/3)
|| pPage->nCell==1 /* See dbfuzz001.test for a test case */
){
/* A b-tree rebalance will be required after deleting this entry.
** Save the cursor key. */
rc = saveCursorKey(pCur);
if( rc ) return rc;
}else{
bPreserve = 2;
}
}
/* If the page containing the entry to delete is not a leaf page, move
** the cursor to the largest entry in the tree that is smaller than
** the entry being deleted. This cell will replace the cell being deleted
** from the internal node. The 'previous' entry is used for this instead
** of the 'next' entry, as the previous entry is always a part of the
** sub-tree headed by the child page of the cell being deleted. This makes
** balancing the tree following the delete operation easier. */
if( !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, 0);
assert( rc!=SQLITE_DONE );
if( rc ) return rc;
}
/* Save the positions of any other cursors open on this table before
** making any modifications. */
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
}
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
/* Make the page containing the entry to be deleted writable. Then free any
** overflow pages associated with the entry and finally remove the cell
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
BTREE_CLEAR_CELL(rc, pPage, pCell, info);
dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
/* If the cell deleted was not located on a leaf page, then the cursor
** is currently pointing to the largest entry in the sub-tree headed
** by the child-page of the cell that was just deleted from an internal
** node. The cell from the leaf node needs to be moved to the internal
** node to replace the deleted cell. */
if( !pPage->leaf ){
MemPage *pLeaf = pCur->pPage;
int nCell;
Pgno n;
unsigned char *pTmp;
if( pLeaf->nFree<0 ){
rc = btreeComputeFreeSpace(pLeaf);
if( rc ) return rc;
}
if( iCellDepth<pCur->iPage-1 ){
n = pCur->apPage[iCellDepth+1]->pgno;
}else{
n = pCur->pPage->pgno;
}
pCell = findCell(pLeaf, pLeaf->nCell-1);
if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_PAGE(pLeaf);
nCell = pLeaf->xCellSize(pLeaf, pCell);
assert( MX_CELL_SIZE(pBt) >= nCell );
pTmp = pBt->pTmpSpace;
assert( pTmp!=0 );
rc = sqlite3PagerWrite(pLeaf->pDbPage);
if( rc==SQLITE_OK ){
rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n);
}
dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
if( rc ) return rc;
}
/* Balance the tree. If the entry deleted was located on a leaf page,
** then the cursor still points to that page. In this case the first
** call to balance() repairs the tree, and the if(...) condition is
** never true.
**
** Otherwise, if the entry deleted was on an internal node page, then
** pCur is pointing to the leaf page from which a cell was removed to
** replace the cell deleted from the internal node. This is slightly
** tricky as the leaf node may be underfull, and the internal node may
** be either under or overfull. In this case run the balancing algorithm
** on the leaf node first. If the balance proceeds far enough up the
** tree that we can be sure that any problem in the internal node has
** been corrected, so be it. Otherwise, after balancing the leaf node,
** walk the cursor up the tree to the internal node and balance it as
** well. */
assert( pCur->pPage->nOverflow==0 );
assert( pCur->pPage->nFree>=0 );
if( pCur->pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
/* Optimization: If the free space is less than 2/3rds of the page,
** then balance() will always be a no-op. No need to invoke it. */
rc = SQLITE_OK;
}else{
rc = balance(pCur);
}
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
releasePageNotNull(pCur->pPage);
pCur->iPage--;
while( pCur->iPage>iCellDepth ){
releasePage(pCur->apPage[pCur->iPage--]);
}
pCur->pPage = pCur->apPage[pCur->iPage];
rc = balance(pCur);
}
if( rc==SQLITE_OK ){
if( bPreserve>1 ){
assert( (pCur->iPage==iCellDepth || CORRUPT_DB) );
assert( pPage==pCur->pPage || CORRUPT_DB );
assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
pCur->eState = CURSOR_SKIPNEXT;
if( iCellIdx>=pPage->nCell ){
pCur->skipNext = -1;
pCur->ix = pPage->nCell-1;
}else{
pCur->skipNext = 1;
}
}else{
rc = moveToRoot(pCur);
if( bPreserve ){
btreeReleaseAllCursorPages(pCur);
pCur->eState = CURSOR_REQUIRESEEK;
}
if( rc==SQLITE_EMPTY ) rc = SQLITE_OK;
}
}
return rc;
}
/*
** Create a new BTree table. Write into *piTable the page
** number for the root page of the new table.
**
** The type of type is determined by the flags parameter. Only the
** following values of flags are currently in use. Other values for
** flags might not work:
**
** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys
** BTREE_ZERODATA Used for SQL indices
*/
static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){
BtShared *pBt = p->pBt;
MemPage *pRoot;
Pgno pgnoRoot;
int rc;
int ptfFlags; /* Page-type flags for the root page of new table */
assert( sqlite3BtreeHoldsMutex(p) );
assert( pBt->inTransaction==TRANS_WRITE );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
#ifdef SQLITE_OMIT_AUTOVACUUM
rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
if( rc ){
return rc;
}
#else
if( pBt->autoVacuum ){
Pgno pgnoMove; /* Move a page here to make room for the root-page */
MemPage *pPageMove; /* The page to move to. */
/* Creating a new table may probably require moving an existing database
** to make room for the new tables root page. In case this page turns
** out to be an overflow page, delete all overflow page-map caches
** held by open cursors.
*/
invalidateAllOverflowCache(pBt);
/* Read the value of meta[3] from the database to determine where the
** root page of the new table should go. meta[3] is the largest root-page
** created so far, so the new root-page is (meta[3]+1).
*/
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot);
if( pgnoRoot>btreePagecount(pBt) ){
return SQLITE_CORRUPT_PGNO(pgnoRoot);
}
pgnoRoot++;
/* The new root-page may not be allocated on a pointer-map page, or the
** PENDING_BYTE page.
*/
while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) ||
pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
pgnoRoot++;
}
assert( pgnoRoot>=3 );
/* Allocate a page. The page that currently resides at pgnoRoot will
** be moved to the allocated page (unless the allocated page happens
** to reside at pgnoRoot).
*/
rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
if( rc!=SQLITE_OK ){
return rc;
}
if( pgnoMove!=pgnoRoot ){
/* pgnoRoot is the page that will be used for the root-page of
** the new table (assuming an error did not occur). But we were
** allocated pgnoMove. If required (i.e. if it was not allocated
** by extending the file), the current page at position pgnoMove
** is already journaled.
*/
u8 eType = 0;
Pgno iPtrPage = 0;
/* Save the positions of any open cursors. This is required in
** case they are holding a reference to an xFetch reference
** corresponding to page pgnoRoot. */
rc = saveAllCursors(pBt, 0, 0);
releasePage(pPageMove);
if( rc!=SQLITE_OK ){
return rc;
}
/* Move the page currently at pgnoRoot to pgnoMove. */
rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
if( rc!=SQLITE_OK ){
return rc;
}
rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
rc = SQLITE_CORRUPT_PGNO(pgnoRoot);
}
if( rc!=SQLITE_OK ){
releasePage(pRoot);
return rc;
}
assert( eType!=PTRMAP_ROOTPAGE );
assert( eType!=PTRMAP_FREEPAGE );
rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
releasePage(pRoot);
/* Obtain the page at pgnoRoot */
if( rc!=SQLITE_OK ){
return rc;
}
rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
if( rc!=SQLITE_OK ){
return rc;
}
rc = sqlite3PagerWrite(pRoot->pDbPage);
if( rc!=SQLITE_OK ){
releasePage(pRoot);
return rc;
}
}else{
pRoot = pPageMove;
}
/* Update the pointer-map and meta-data with the new root-page number. */
ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc);
if( rc ){
releasePage(pRoot);
return rc;
}
/* When the new root page was allocated, page 1 was made writable in
** order either to increase the database filesize, or to decrement the
** freelist count. Hence, the sqlite3BtreeUpdateMeta() call cannot fail.
*/
assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) );
rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot);
if( NEVER(rc) ){
releasePage(pRoot);
return rc;
}
BtShared *pBt, /* The BTree that contains the table */
Pgno pgno, /* Page number to clear */
int freePageFlag, /* Deallocate page if true */
i64 *pnChange /* Add number of Cells freed to this counter */
){
MemPage *pPage;
int rc;
unsigned char *pCell;
int i;
int hdr;
CellInfo info;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_PGNO(pgno);
}
rc = getAndInitPage(pBt, pgno, &pPage, 0);
if( rc ) return rc;
if( (pBt->openFlags & BTREE_SINGLE)==0
&& sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1))
){
rc = SQLITE_CORRUPT_PAGE(pPage);
goto cleardatabasepage_out;
}
hdr = pPage->hdrOffset;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
BTREE_CLEAR_CELL(rc, pPage, pCell, info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
if( pPage->intKey ) pnChange = 0;
}
if( pnChange ){
testcase( !pPage->intKey );
*pnChange += pPage->nCell;
}
if( freePageFlag ){
freePage(pPage, &rc);
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
}
cleardatabasepage_out:
releasePage(pPage);
return rc;
}
/*
** Delete all information from a single table in the database. iTable is
** the page number of the root of the table. After this routine returns,
** the root page is empty, but still exists.
**
** This routine will fail with SQLITE_LOCKED if there are any open
** read cursors on the table. Open write cursors are moved to the
** root of the table.
**
** If pnChange is not NULL, then the integer value pointed to by pnChange
** is incremented by the number of entries in the table.
*/
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){
int rc;
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
assert( p->inTrans==TRANS_WRITE );
rc = saveAllCursors(pBt, (Pgno)iTable, 0);
if( SQLITE_OK==rc ){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
if( p->hasIncrblobCur ){
invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
}
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlite3BtreeLeave(p);
return rc;
}
/*
** Delete all information from the single table that pCur is open on.
**
** This routine only work for pCur on an ephemeral table.
*/
SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0);
}
/*
** Erase all information in a table and add the root of the table to
** the freelist. Except, the root of the principle table (the one on
** page 1) is never added to the freelist.
**
** This routine will fail with SQLITE_LOCKED if there are any open
** cursors on the table.
**
** If AUTOVACUUM is enabled and the page at iTable is not the last
** root page in the database file, then the last root page
** in the database file is moved into the slot formerly occupied by
** iTable and that last slot formerly occupied by the last root page
** is added to the freelist instead of iTable. In this say, all
** root pages are kept at the beginning of the database file, which
** is necessary for AUTOVACUUM to work right. *piMoved is set to the
** page number that used to be the last root page in the file before
** the move. If no page gets moved, *piMoved is set to 0.
** The last root page is recorded in meta[3] and the value of
** meta[3] is updated by this procedure.
*/
static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
int rc;
MemPage *pPage = 0;
BtShared *pBt = p->pBt;
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->inTrans==TRANS_WRITE );
assert( iTable>=2 );
if( iTable>btreePagecount(pBt) ){
return SQLITE_CORRUPT_PGNO(iTable);
}
rc = sqlite3BtreeClearTable(p, iTable, 0);
if( rc ) return rc;
rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( NEVER(rc) ){
releasePage(pPage);
return rc;
}
*piMoved = 0;
#ifdef SQLITE_OMIT_AUTOVACUUM
freePage(pPage, &rc);
releasePage(pPage);
#else
if( pBt->autoVacuum ){
Pgno maxRootPgno;
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno);
if( iTable==maxRootPgno ){
/* If the table being dropped is the table with the largest root-page
** number in the database, put the root page on the free list.
*/
freePage(pPage, &rc);
releasePage(pPage);
if( rc!=SQLITE_OK ){
return rc;
}
}else{
/* The table being dropped does not have the largest root-page
** number in the database. So move the page that does into the
** gap left by the deleted root-page.
*/
MemPage *pMove;
releasePage(pPage);
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
** from the pager. The BTREE_DATA_VERSION value is not actually stored in the
** database file. It is a number computed by the pager. But its access
** pattern is the same as header meta values, and so it is convenient to
** read it from this routine.
*/
SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE );
assert( SQLITE_OK==querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK) );
assert( pBt->pPage1 );
assert( idx>=0 && idx<=15 );
if( idx==BTREE_DATA_VERSION ){
*pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion;
}else{
*pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
}
/* If auto-vacuum is disabled in this build and this is an auto-vacuum
** database, mark the database as read-only. */
#ifdef SQLITE_OMIT_AUTOVACUUM
if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){
pBt->btsFlags |= BTS_READ_ONLY;
}
#endif
sqlite3BtreeLeave(p);
}
/*
** Write meta-information back into the database. Meta[0] is
** read-only and may not be written.
*/
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
BtShared *pBt = p->pBt;
unsigned char *pP1;
int rc;
assert( idx>=1 && idx<=15 );
sqlite3BtreeEnter(p);
assert( p->inTrans==TRANS_WRITE );
assert( pBt->pPage1!=0 );
pP1 = pBt->pPage1->aData;
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc==SQLITE_OK ){
put4byte(&pP1[36 + idx*4], iMeta);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( idx==BTREE_INCR_VACUUM ){
assert( pBt->autoVacuum || iMeta==0 );
assert( iMeta==0 || iMeta==1 );
pBt->incrVacuum = (u8)iMeta;
}
#endif
}
sqlite3BtreeLeave(p);
return rc;
}
/*
** The first argument, pCur, is a cursor opened on some b-tree. Count the
** number of entries in the b-tree and write the result to *pnEntry.
**
** SQLITE_OK is returned if the operation is successfully executed.
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */
rc = moveToRoot(pCur);
if( rc==SQLITE_EMPTY ){
*pnEntry = 0;
return SQLITE_OK;
}
/* Unless an error occurs, the following loop runs one iteration for each
** page in the B-Tree structure (not including overflow pages).
*/
while( rc==SQLITE_OK && !AtomicLoad(&db->u1.isInterrupted) ){
int iIdx; /* Index of child node in parent */
MemPage *pPage; /* Current page of the b-tree */
/* If this is a leaf page or the tree is not an int-key tree, then
** this page contains countable entries. Increment the entry counter
** accordingly.
*/
pPage = pCur->pPage;
if( pPage->leaf || !pPage->intKey ){
nEntry += pPage->nCell;
}
/* pPage is a leaf node. This loop navigates the cursor so that it
** points to the first interior cell that it points to the parent of
** the next page in the tree that has not yet been visited. The
** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell
** of the page, or to the number of cells in the page if the next page
** to visit is the right-child of its parent.
**
** If all pages in the tree have been visited, return SQLITE_OK to the
** caller.
*/
if( pPage->leaf ){
do {
if( pCur->iPage==0 ){
/* All pages of the b-tree have been visited. Return successfully. */
*pnEntry = nEntry;
return moveToRoot(pCur);
}
moveToParent(pCur);
}while ( pCur->ix>=pCur->pPage->nCell );
pCur->ix++;
pPage = pCur->pPage;
}
/* Descend to the child node of the cell that the cursor currently
** points at. This is the right-child if (iIdx==pPage->nCell).
*/
iIdx = pCur->ix;
if( iIdx==pPage->nCell ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
}else{
rc = moveToChild(pCur, get4byte(findCell(pPage, iIdx)));
}
}
/* An error has occurred. Return an error code. */
return rc;
}
/*
** Return the pager associated with a BTree. This routine is used for
** testing and debugging only.
*/
SQLITE_PRIVATE Pager *sqlite3BtreePager(Btree *p){
return p->pBt->pPager;
}
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Record an OOM error during integrity_check
*/
static void checkOom(IntegrityCk *pCheck){
pCheck->rc = SQLITE_NOMEM;
pCheck->mxErr = 0; /* Causes integrity_check processing to stop */
if( pCheck->nErr==0 ) pCheck->nErr++;
}
/*
** Invoke the progress handler, if appropriate. Also check for an
** interrupt.
*/
static void checkProgress(IntegrityCk *pCheck){
sqlite3 *db = pCheck->db;
if( AtomicLoad(&db->u1.isInterrupted) ){
pCheck->rc = SQLITE_INTERRUPT;
pCheck->nErr++;
pCheck->mxErr = 0;
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
assert( db->nProgressOps>0 );
pCheck->nStep++;
if( (pCheck->nStep % db->nProgressOps)==0
&& db->xProgress(db->pProgressArg)
){
pCheck->rc = SQLITE_INTERRUPT;
pCheck->nErr++;
pCheck->mxErr = 0;
}
}
#endif
}
/*
** Append a message to the error message string.
** xFree argument when the memory allocation was made is invoked on the
** blob of allocated memory. The xFree function should not call sqlite3_free()
** on the memory, the btree layer does that.
*/
SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
BtShared *pBt = p->pBt;
assert( nBytes==0 || nBytes==sizeof(Schema) );
sqlite3BtreeEnter(p);
if( !pBt->pSchema && nBytes ){
pBt->pSchema = sqlite3DbMallocZero(0, nBytes);
pBt->xFreeSchema = xFree;
}
sqlite3BtreeLeave(p);
return pBt->pSchema;
}
/*
** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
** btree as the argument handle holds an exclusive lock on the
** sqlite_schema table. Otherwise SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){
int rc;
UNUSED_PARAMETER(p); /* only used in DEBUG builds */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE );
sqlite3BtreeLeave(p);
return rc;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** Obtain a lock on the table whose root page is iTab. The
** lock is a write lock if isWritelock is true or a read lock
** if it is false.
*/
SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
int rc = SQLITE_OK;
assert( p->inTrans!=TRANS_NONE );
if( p->sharable ){
u8 lockType = READ_LOCK + isWriteLock;
assert( READ_LOCK+1==WRITE_LOCK );
assert( isWriteLock==0 || isWriteLock==1 );
sqlite3BtreeEnter(p);
rc = querySharedCacheTableLock(p, iTab, lockType);
if( rc==SQLITE_OK ){
rc = setSharedCacheTableLock(p, iTab, lockType);
}
sqlite3BtreeLeave(p);
}
return rc;
}
#endif
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Argument pCsr must be a cursor opened for writing on an
** INTKEY table currently pointing at a valid table entry.
** This function modifies the data stored as part of that entry.
**
** Only the data content may only be modified, it is not possible to
** change the length of the data stored. If this function is called with
** parameters that attempt to write past the end of the existing data,
** no modifications are made and SQLITE_CORRUPT is returned.
*/
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
int rc;
assert( cursorOwnsBtShared(pCsr) );
assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
assert( pCsr->curFlags & BTCF_Incrblob );
rc = restoreCursorPosition(pCsr);
if( rc!=SQLITE_OK ){
return rc;
}
assert( pCsr->eState!=CURSOR_REQUIRESEEK );
if( pCsr->eState!=CURSOR_VALID ){
return SQLITE_ABORT;
}
/* Save the positions of all other cursors open on this table. This is
** required in case any of them are holding references to an xFetch
** version of the b-tree page modified by the accessPayload call below.
**
** Note that pCsr must be open on a INTKEY table and saveCursorPosition()
** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence
** saveAllCursors can only return SQLITE_OK.
*/
VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
assert( rc==SQLITE_OK );
/* Check some assumptions:
** (a) the cursor is open for writing,
** (b) there is a read/write transaction open,
** (c) the connection holds a write-lock on the table (if required),
** (d) there are no conflicting read-locks, and
** (e) the cursor points at a valid row of an intKey table.
*/
if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){
return SQLITE_READONLY;
}
assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
&& pCsr->pBt->inTransaction==TRANS_WRITE );
assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
assert( pCsr->pPage->intKey );
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}
/*
** Mark this cursor as an incremental blob cursor.
*/
SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
pCur->curFlags |= BTCF_Incrblob;
pCur->pBtree->hasIncrblobCur = 1;
}
#endif
/*
** Set both the "read version" (single byte at byte offset 18) and
** "write version" (single byte at byte offset 19) fields in the database
** header to iVersion.
*/
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
BtShared *pBt = pBtree->pBt;
int rc; /* Return code */
assert( iVersion==1 || iVersion==2 );
/* If setting the version fields to 1, do not automatically open the
** WAL connection, even if the version fields are currently set to 2.
*/
pBt->btsFlags &= ~BTS_NO_WAL;
if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
rc = sqlite3BtreeBeginTrans(pBtree, 0, 0);
if( rc==SQLITE_OK ){
u8 *aData = pBt->pPage1->aData;
if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
rc = sqlite3BtreeBeginTrans(pBtree, 2, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc==SQLITE_OK ){
aData[18] = (u8)iVersion;
aData[19] = (u8)iVersion;
}
}
}
}
pBt->btsFlags &= ~BTS_NO_WAL;
return rc;
}
/*
** Return true if the cursor has a hint specified. This routine is
** only used from within assert() statements
*/
SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
return (pCsr->hints & mask)!=0;
}
/*
** Return true if the given Btree is read-only.
*/
SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *p){
return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
}
/*
** Return the size of the header added to each page by this module.
*/
SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
/*
** If no transaction is active and the database is not a temp-db, clear
** the in-memory pager cache.
*/
SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree *p){
BtShared *pBt = p->pBt;
if( pBt->inTransaction==TRANS_NONE ){
sqlite3PagerClearCache(pBt->pPager);
}
}
#if !defined(SQLITE_OMIT_SHARED_CACHE)
/*
** Return true if the Btree passed as the only argument is sharable.
*/
SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){
return p->sharable;
}
/*
** Return the number of connections to the BtShared object accessed by
** the Btree handle passed as the only argument. For private caches
** this is always 1. For shared caches it may be 1 or greater.
*/
SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){
testcase( p->sharable );
return p->pBt->nRef;
}
#endif
/************** End of btree.c ***********************************************/
/************** Begin file backup.c ******************************************/
/*
** 2009 January 28
**
** 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.
**
**
** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
*/
SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
int hasAbort = 0;
int hasFkCounter = 0;
int hasCreateTable = 0;
int hasCreateIndex = 0;
int hasInitCoroutine = 0;
Op *pOp;
VdbeOpIter sIter;
if( v==0 ) return 0;
memset(&sIter, 0, sizeof(sIter));
sIter.v = v;
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
|| opcode==OP_VCreate
|| opcode==OP_ParseSchema
|| opcode==OP_Function || opcode==OP_PureFunc
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
hasAbort = 1;
break;
}
if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
if( mayAbort ){
/* hasCreateIndex may also be set for some DELETE statements that use
** OP_Clear. So this routine may end up returning true in the case
** where a "DELETE FROM tbl" has a statement-journal but does not
** require one. This is not so bad - it is an inefficiency, not a bug. */
if( opcode==OP_CreateBtree && pOp->p3==BTREE_BLOBKEY ) hasCreateIndex = 1;
if( opcode==OP_Clear ) hasCreateIndex = 1;
}
if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
hasFkCounter = 1;
}
#endif
}
sqlite3DbFree(v->db, sIter.apSub);
/* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
** If malloc failed, then the while() loop above may not have iterated
** through all opcodes and hasAbort may be set incorrectly. Return
** true for this case to prevent the assert() in the callers frame
** from failing. */
return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter
|| (hasCreateTable && hasInitCoroutine) || hasCreateIndex
);
}
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
#ifdef SQLITE_DEBUG
/*
** Increment the nWrite counter in the VDBE if the cursor is not an
** ephemeral cursor, or if the cursor argument is NULL.
*/
SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){
if( pC==0
|| (pC->eCurType!=CURTYPE_SORTER
&& pC->eCurType!=CURTYPE_PSEUDO
&& !pC->isEphemeral)
){
p->nWrite++;
}
}
#endif
#ifdef SQLITE_DEBUG
/*
** Assert if an Abort at this point in time might result in a corrupt
** database.
*/
SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){
assert( p->nWrite==0 || p->usesStmtJournal );
}
#endif
/*
** This routine is called after all opcodes have been inserted. It loops
** through all the opcodes and fixes up some details.
**
** (1) For each jump instruction with a negative P2 value (a label)
** resolve the P2 value to an actual address.
**
** (2) Compute the maximum number of arguments used by the xUpdate/xFilter
** methods of any virtual table and store that value in *pMaxVtabArgs.
**
** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
** indicate what the prepared statement actually does.
**
** (4) (discontinued)
**
** (5) Reclaim the memory allocated for storing labels.
**
** This routine will only function correctly if the mkopcodeh.tcl generator
** script numbers the opcodes correctly. Changes to this routine must be
** coordinated with changes to mkopcodeh.tcl.
*/
static void resolveP2Values(Vdbe *p, int *pMaxVtabArgs){
int nMaxVtabArgs = *pMaxVtabArgs;
Op *pOp;
Parse *pParse = p->pParse;
int *aLabel = pParse->aLabel;
assert( pParse->db->mallocFailed==0 ); /* tag-20230419-1 */
p->readOnly = 1;
p->bIsReader = 0;
pOp = &p->aOp[p->nOp-1];
assert( p->aOp[0].opcode==OP_Init );
while( 1 /* Loop terminates when it reaches the OP_Init opcode */ ){
/* Only JUMP opcodes and the short list of special opcodes in the switch
** below need to be considered. The mkopcodeh.tcl generator script groups
** all these opcodes together near the front of the opcode list. Skip
** any opcode that does not need processing by virtual of the fact that
** it is larger than SQLITE_MX_JUMP_OPCODE, as a performance optimization.
#if defined(SQLITE_DEBUG)
int i;
#endif
assert( p!=0 );
assert( p->eVdbeState==VDBE_INIT_STATE
|| p->eVdbeState==VDBE_READY_STATE
|| p->eVdbeState==VDBE_HALT_STATE );
/* There should be at least one opcode.
*/
assert( p->nOp>0 );
p->eVdbeState = VDBE_READY_STATE;
#ifdef SQLITE_DEBUG
for(i=0; i<p->nMem; i++){
assert( p->aMem[i].db==p->db );
}
#endif
p->pc = -1;
p->rc = SQLITE_OK;
p->errorAction = OE_Abort;
p->nChange = 0;
p->cacheCtr = 1;
p->minWriteFileFormat = 255;
p->iStatement = 0;
p->nFkConstraint = 0;
#ifdef VDBE_PROFILE
for(i=0; i<p->nOp; i++){
p->aOp[i].nExec = 0;
p->aOp[i].nCycle = 0;
}
#endif
}
/*
** Prepare a virtual machine for execution for the first time after
** creating the virtual machine. This involves things such
** as allocating registers and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqlite3VdbeExec().
**
** This function may be called exactly once on each virtual machine.
** After this routine is called the VM has been "packaged" and is ready
** to run. After this routine is called, further calls to
** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
** the Vdbe from the Parse object that helped generate it so that the
** the Vdbe becomes an independent entity and the Parse object can be
** destroyed.
**
** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back
** to its initial state after it has been run.
*/
SQLITE_PRIVATE void sqlite3VdbeMakeReady(
Vdbe *p, /* The VDBE */
Parse *pParse /* Parsing context */
){
sqlite3 *db; /* The database connection */
int nVar; /* Number of parameters */
int nMem; /* Number of VM memory registers */
int nCursor; /* Number of cursors required */
int nArg; /* Max number args to xFilter or xUpdate */
int n; /* Loop counter */
struct ReusableSpace x; /* Reusable bulk memory */
assert( p!=0 );
assert( p->nOp>0 );
assert( pParse!=0 );
assert( p->eVdbeState==VDBE_INIT_STATE );
assert( pParse==p->pParse );
assert( pParse->db==p->db );
p->pVList = pParse->pVList;
pParse->pVList = 0;
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
nMem = pParse->nMem;
nCursor = pParse->nTab;
nArg = pParse->nMaxArg;
/* Each cursor uses a memory cell. The first cursor (cursor 0) can
** use aMem[0] which is not otherwise used by the VDBE program. Allocate
** space at the end of aMem[] for cursors 1 and greater.
** See also: allocateCursor().
*/
nMem += nCursor;
if( nCursor==0 && nMem>0 ) nMem++; /* Space for aMem[0] even if not used */
/* Figure out how much reusable memory is available at the end of the
** opcode array. This extra memory will be reallocated for other elements
** of the prepared statement.
*/
n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
assert( x.nFree>=0 );
assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
if( pParse->explain ){
if( nMem<10 ) nMem = 10;
p->explain = pParse->explain;
p->nResColumn = 12 - 4*p->explain;
}
p->expired = 0;
/* Memory for registers, parameters, cursor, etc, is allocated in one or two
** passes. On the first pass, we try to reuse unused memory at the
** end of the opcode array. If we are unable to satisfy all memory
** requirements by reusing the opcode array tail, then the second
** pass will fill in the remainder using a fresh memory allocation.
**
** This two-pass approach that reuses as much memory as possible from
** the leftover memory at the end of the opcode array. This can significantly
** reduce the amount of memory held by a prepared statement.
*/
x.nNeeded = 0;
p->aMem = allocSpace(&x, 0, nMem*sizeof(Mem));
p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem));
p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*));
p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*));
if( x.nNeeded ){
x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
x.nFree = x.nNeeded;
if( !db->mallocFailed ){
p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
}
}
#ifdef SQLITE_DEBUG
p->napArg = nArg;
#endif
if( db->mallocFailed ){
p->nVar = 0;
p->nCursor = 0;
p->nMem = 0;
}else{
p->nCursor = nCursor;
p->nVar = (ynVar)nVar;
initMemArray(p->aVar, nVar, db, MEM_Null);
p->nMem = nMem;
initMemArray(p->aMem, nMem, db, MEM_Undefined);
memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*));
}
sqlite3VdbeRewind(p);
}
/*
** Close a VDBE cursor and release all the resources that cursor
** happens to hold.
*/
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
if( pCx ) sqlite3VdbeFreeCursorNN(p,pCx);
}
static SQLITE_NOINLINE void freeCursorWithCache(Vdbe *p, VdbeCursor *pCx){
VdbeTxtBlbCache *pCache = pCx->pCache;
assert( pCx->colCache );
pCx->colCache = 0;
pCx->pCache = 0;
if( pCache->pCValue ){
sqlite3RCStrUnref(pCache->pCValue);
pCache->pCValue = 0;
}
sqlite3DbFree(p->db, pCache);
sqlite3VdbeFreeCursorNN(p, pCx);
}
SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe *p, VdbeCursor *pCx){
if( pCx->colCache ){
freeCursorWithCache(p, pCx);
return;
}
switch( pCx->eCurType ){
case CURTYPE_SORTER: {
sqlite3VdbeSorterClose(p->db, pCx);
break;
}
case CURTYPE_BTREE: {
assert( pCx->uc.pCursor!=0 );
sqlite3BtreeCloseCursor(pCx->uc.pCursor);
break;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
case CURTYPE_VTAB: {
sqlite3_vtab_cursor *pVCur = pCx->uc.pVCur;
const sqlite3_module *pModule = pVCur->pVtab->pModule;
assert( pVCur->pVtab->nRef>0 );
pVCur->pVtab->nRef--;
pModule->xClose(pVCur);
break;
}
#endif
}
}
/*
** Close all cursors in the current frame.
*/
static void closeCursorsInFrame(Vdbe *p){
int i;
for(i=0; i<p->nCursor; i++){
VdbeCursor *pC = p->apCsr[i];
if( pC ){
sqlite3VdbeFreeCursorNN(p, pC);
p->apCsr[i] = 0;
}
}
}
/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
** control to the main program.
*/
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
Vdbe *v = pFrame->v;
closeCursorsInFrame(v);
v->aOp = pFrame->aOp;
v->nOp = pFrame->nOp;
v->aMem = pFrame->aMem;
v->nMem = pFrame->nMem;
v->apCsr = pFrame->apCsr;
v->nCursor = pFrame->nCursor;
v->db->lastRowid = pFrame->lastRowid;
v->nChange = pFrame->nChange;
v->db->nChange = pFrame->nDbChange;
sqlite3VdbeDeleteAuxData(v->db, &v->pAuxData, -1, 0);
v->pAuxData = pFrame->pAuxData;
pFrame->pAuxData = 0;
return pFrame->pc;
}
/*
** Close all cursors.
**
** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
** cell array. This is necessary as the memory cell array may contain
** pointers to VdbeFrame objects, which may in turn contain pointers to
** open cursors.
*/
static void closeAllCursors(Vdbe *p){
if( p->pFrame ){
VdbeFrame *pFrame;
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
sqlite3VdbeFrameRestore(pFrame);
p->pFrame = 0;
p->nFrame = 0;
}
assert( p->nFrame==0 );
closeCursorsInFrame(p);
releaseMemArray(p->aMem, p->nMem);
while( p->pDelFrame ){
VdbeFrame *pDel = p->pDelFrame;
p->pDelFrame = pDel->pParent;
sqlite3VdbeFrameDelete(pDel);
}
/* Delete any auxdata allocations made by the VM */
if( p->pAuxData ) sqlite3VdbeDeleteAuxData(p->db, &p->pAuxData, -1, 0);
assert( p->pAuxData==0 );
}
/*
** Set the number of result columns that will be returned by this SQL
** statement. This is now set at compile time, rather than during
** execution of the vdbe program so that sqlite3_column_count() can
** be called on an SQL statement before sqlite3_step().
*/
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
int n;
sqlite3 *db = p->db;
if( p->nResAlloc ){
releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N);
sqlite3DbFree(db, p->aColName);
}
n = nResColumn*COLNAME_N;
p->nResColumn = p->nResAlloc = (u16)nResColumn;
p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
if( p->aColName==0 ) return;
initMemArray(p->aColName, n, db, MEM_Null);
}
/*
** Set the name of the idx'th column to be returned by the SQL statement.
** zName must be a pointer to a nul terminated string.
**
** This call must be made after a call to sqlite3VdbeSetNumCols().
**
** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC
** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed
** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed.
*/
SQLITE_PRIVATE int sqlite3VdbeSetColName(
Vdbe *p, /* Vdbe being configured */
int idx, /* Index of column zName applies to */
int var, /* One of the COLNAME_* constants */
const char *zName, /* Pointer to buffer containing name */
void (*xDel)(void*) /* Memory management strategy for zName */
assert( p->db==0 || p->db==db );
if( p->aColName ){
releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N);
sqlite3DbNNFreeNN(db, p->aColName);
}
for(pSub=p->pProgram; pSub; pSub=pNext){
pNext = pSub->pNext;
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
sqlite3DbFree(db, pSub);
}
if( p->eVdbeState!=VDBE_INIT_STATE ){
releaseMemArray(p->aVar, p->nVar);
if( p->pVList ) sqlite3DbNNFreeNN(db, p->pVList);
if( p->pFree ) sqlite3DbNNFreeNN(db, p->pFree);
}
vdbeFreeOpArray(db, p->aOp, p->nOp);
if( p->zSql ) sqlite3DbNNFreeNN(db, p->zSql);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3DbFree(db, p->zNormSql);
{
DblquoteStr *pThis, *pNxt;
for(pThis=p->pDblStr; pThis; pThis=pNxt){
pNxt = pThis->pNextStr;
sqlite3DbFree(db, pThis);
}
}
#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
{
int i;
for(i=0; i<p->nScan; i++){
sqlite3DbFree(db, p->aScan[i].zName);
}
sqlite3DbFree(db, p->aScan);
}
#endif
}
/*
** Delete an entire VDBE.
*/
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
sqlite3 *db;
assert( p!=0 );
db = p->db;
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
sqlite3VdbeClearObject(db, p);
if( db->pnBytesFreed==0 ){
assert( p->ppVPrev!=0 );
*p->ppVPrev = p->pVNext;
if( p->pVNext ){
p->pVNext->ppVPrev = p->ppVPrev;
}
}
sqlite3DbNNFreeNN(db, p);
}
/*
** The cursor "p" has a pending seek operation that has not yet been
** carried out. Seek the cursor now. If an error occurs, return
** the appropriate error code.
*/
SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){
int res, rc;
#ifdef SQLITE_TEST
extern int sqlite3_search_count;
#endif
assert( p->deferredMoveto );
assert( p->isTable );
assert( p->eCurType==CURTYPE_BTREE );
rc = sqlite3BtreeTableMoveto(p->uc.pCursor, p->movetoTarget, 0, &res);
if( rc ) return rc;
if( res!=0 ) return SQLITE_CORRUPT_BKPT;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
p->deferredMoveto = 0;
p->cacheStatus = CACHE_STALE;
return SQLITE_OK;
}
/*
** Something has moved cursor "p" out of place. Maybe the row it was
** pointed to was deleted out from under it. Or maybe the btree was
** rebalanced. Whatever the cause, try to restore "p" to the place it
** is supposed to be pointing. If the row was deleted out from under the
** cursor, set the cursor to point to a NULL row.
*/
SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p){
int isDifferentRow, rc;
assert( p->eCurType==CURTYPE_BTREE );
assert( p->uc.pCursor!=0 );
assert( sqlite3BtreeCursorHasMoved(p->uc.pCursor) );
rc = sqlite3BtreeCursorRestore(p->uc.pCursor, &isDifferentRow);
p->cacheStatus = CACHE_STALE;
if( isDifferentRow ) p->nullRow = 1;
return rc;
}
/*
** Check to ensure that the cursor is valid. Restore the cursor
** if need be. Return any I/O error from the restore operation.
*/
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){
assert( p->eCurType==CURTYPE_BTREE || IsNullCursor(p) );
if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
return sqlite3VdbeHandleMovedCursor(p);
}
return SQLITE_OK;
}
/*
** The following functions:
**
** sqlite3VdbeSerialType()
** sqlite3VdbeSerialTypeLen()
** sqlite3VdbeSerialLen()
** sqlite3VdbeSerialPut() <--- in-lined into OP_MakeRecord as of 2022-04-02
** sqlite3VdbeSerialGet()
**
** encapsulate the code that serializes values for storage in SQLite
** data and index records. Each serialized value consists of a
** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
** integer, stored as a varint.
**
** In an SQLite index record, the serial type is stored directly before
** the blob of data that it corresponds to. In a table record, all serial
** types are stored at the start of the record, and the blobs of data at
** the end. Hence these functions allow the caller to handle the
** serial-type and data blob separately.
**
** The following table describes the various storage classes for data:
**
** serial type bytes of data type
** -------------- --------------- ---------------
** 0 0 NULL
** 1 1 signed integer
** 2 2 signed integer
** 3 3 signed integer
** 4 4 signed integer
** 5 6 signed integer
** 6 8 signed integer
** 7 8 IEEE float
** 8 0 Integer constant 0
** 9 0 Integer constant 1
** 10,11 reserved for expansion
** N>=12 and even (N-12)/2 BLOB
** N>=13 and odd (N-13)/2 text
**
** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions
** of SQLite will not understand those serial types.
*/
#if 0 /* Inlined into the OP_MakeRecord opcode */
/*
** Return the serial-type for the value stored in pMem.
**
** This routine might convert a large MEM_IntReal value into MEM_Real.
**
** 2019-07-11: The primary user of this subroutine was the OP_MakeRecord
** opcode in the byte-code engine. But by moving this routine in-line, we
** than 2GiB are support - anything large must be database corruption.
** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
** this code can safely assume that nCellKey is 32-bits
*/
assert( sqlite3BtreeCursorIsValid(pCur) );
nCellKey = sqlite3BtreePayloadSize(pCur);
assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
/* Read in the complete content of the index entry */
sqlite3VdbeMemInit(&m, db, 0);
rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
if( rc ){
return rc;
}
/* The index entry must begin with a header size */
getVarint32NR((u8*)m.z, szHdr);
testcase( szHdr==3 );
testcase( szHdr==(u32)m.n );
testcase( szHdr>0x7fffffff );
assert( m.n>=0 );
if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
goto idx_rowid_corruption;
}
/* The last field of the index should be an integer - the ROWID.
** Verify that the last entry really is an integer. */
getVarint32NR((u8*)&m.z[szHdr-1], typeRowid);
testcase( typeRowid==1 );
testcase( typeRowid==2 );
testcase( typeRowid==3 );
testcase( typeRowid==4 );
testcase( typeRowid==5 );
testcase( typeRowid==6 );
testcase( typeRowid==8 );
testcase( typeRowid==9 );
if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){
goto idx_rowid_corruption;
}
lenRowid = sqlite3SmallTypeSizes[typeRowid];
testcase( (u32)m.n==szHdr+lenRowid );
if( unlikely((u32)m.n<szHdr+lenRowid) ){
goto idx_rowid_corruption;
}
/* Fetch the integer off the end of the index record */
sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
*rowid = v.u.i;
sqlite3VdbeMemReleaseMalloc(&m);
return SQLITE_OK;
/* Jump here if database corruption is detected after m has been
** allocated. Free the m object and return SQLITE_CORRUPT. */
idx_rowid_corruption:
testcase( m.szMalloc!=0 );
sqlite3VdbeMemReleaseMalloc(&m);
return SQLITE_CORRUPT_BKPT;
}
/*
** Compare the key of the index entry that cursor pC is pointing to against
** the key string in pUnpacked. Write into *pRes a number
** that is negative, zero, or positive if pC is less than, equal to,
** or greater than pUnpacked. Return SQLITE_OK on success.
**
** pUnpacked is either created without a rowid or is truncated so that it
** omits the rowid at the end. The rowid at the end of the index entry
** is ignored as well. Hence, this routine only compares the prefixes
** of the keys prior to the final rowid, not the entire key.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
sqlite3 *db, /* Database connection */
VdbeCursor *pC, /* The cursor to compare against */
UnpackedRecord *pUnpacked, /* Unpacked version of key */
int *res /* Write the comparison result here */
){
i64 nCellKey = 0;
int rc;
BtCursor *pCur;
Mem m;
assert( pC->eCurType==CURTYPE_BTREE );
pCur = pC->uc.pCursor;
assert( sqlite3BtreeCursorIsValid(pCur) );
nCellKey = sqlite3BtreePayloadSize(pCur);
/* nCellKey will always be between 0 and 0xffffffff because of the way
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
if( nCellKey<=0 || nCellKey>0x7fffffff ){
*res = 0;
return SQLITE_CORRUPT_BKPT;
}
sqlite3VdbeMemInit(&m, db, 0);
rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
if( rc ){
return rc;
}
*res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0);
sqlite3VdbeMemReleaseMalloc(&m);
return SQLITE_OK;
}
/*
** This routine sets the value to be returned by subsequent calls to
** sqlite3_changes() on the database handle 'db'.
*/
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, i64 nChange){
assert( sqlite3_mutex_held(db->mutex) );
db->nChange = nChange;
db->nTotalChange += nChange;
}
/*
** Set a flag in the vdbe to update the change counter when it is finalised
** or reset.
*/
SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){
v->changeCntOn = 1;
}
/*
** Mark every prepared statement associated with a database connection
** as expired.
**
** An expired statement means that recompilation of the statement is
** recommend. Statements expire when things happen that make their
** programs obsolete. Removing user-defined functions or collating
** sequences, or changing an authorization function are the types of
** things that make prepared statements obsolete.
**
** If iCode is 1, then expiration is advisory. The statement should
** be reprepared before being restarted, but if it is already running
** it is allowed to run to completion.
**
}
#endif /* SQLITE_OMIT_DATETIME_FUNCS */
#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
/*
** This Walker callback is used to help verify that calls to
** sqlite3BtreeCursorHint() with opcode BTREE_HINT_RANGE have
** byte-code register values correctly initialized.
*/
SQLITE_PRIVATE int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_REGISTER ){
assert( (pWalker->u.aMem[pExpr->iTable].flags & MEM_Undefined)==0 );
}
return WRC_Continue;
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS && SQLITE_DEBUG */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/
SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
if( pVtab->zErrMsg ){
sqlite3 *db = p->db;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = 0;
}
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** If the second argument is not NULL, release any allocations associated
** with the memory cells in the p->aMem[] array. Also free the UnpackedRecord
** structure itself, using sqlite3DbFree().
**
** This function is used to free UnpackedRecord structures allocated by
** the vdbeUnpackRecord() function found in vdbeapi.c.
*/
static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
assert( db!=0 );
if( p ){
int i;
for(i=0; i<nField; i++){
Mem *pMem = &p->aMem[i];
if( pMem->zMalloc ) sqlite3VdbeMemReleaseMalloc(pMem);
}
sqlite3DbNNFreeNN(db, p);
}
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** Invoke the pre-update hook. If this is an UPDATE or DELETE pre-update call,
** then cursor passed as the second argument should point to the row about
** to be update or deleted. If the application calls sqlite3_preupdate_old(),
** the required value will be read from the row the cursor points to.
*/
SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
Vdbe *v, /* Vdbe pre-update hook is invoked by */
VdbeCursor *pCsr, /* Cursor to grab old.* values from */
int op, /* SQLITE_INSERT, UPDATE or DELETE */
const char *zDb, /* Database name */
Table *pTab, /* Modified table */
i64 iKey1, /* Initial key value */
int iReg, /* Register for new.* record */
int iBlobWrite
){
sqlite3 *db = v->db;
i64 iKey2;
PreUpdate preupdate;
const char *zTbl = pTab->zName;
#ifdef SQLITE_DEBUG
int nRealCol;
if( pTab->tabFlags & TF_WithoutRowid ){
nRealCol = sqlite3PrimaryKeyIndex(pTab)->nColumn;
}else if( pTab->tabFlags & TF_HasVirtual ){
nRealCol = pTab->nNVCol;
}else{
nRealCol = pTab->nCol;
}
#endif
assert( db->pPreUpdate==0 );
memset(&preupdate, 0, sizeof(PreUpdate));
if( HasRowid(pTab)==0 ){
iKey1 = iKey2 = 0;
preupdate.pPk = sqlite3PrimaryKeyIndex(pTab);
}else{
if( op==SQLITE_UPDATE ){
iKey2 = v->aMem[iReg].u.i;
}else{
iKey2 = iKey1;
}
}
assert( pCsr!=0 );
assert( pCsr->eCurType==CURTYPE_BTREE );
assert( pCsr->nField==nRealCol
|| (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1)
);
preupdate.v = v;
preupdate.pCsr = pCsr;
preupdate.op = op;
preupdate.iNewReg = iReg;
preupdate.pKeyinfo = (KeyInfo*)&preupdate.uKey;
preupdate.pKeyinfo->db = db;
preupdate.pKeyinfo->enc = ENC(db);
preupdate.pKeyinfo->nKeyField = pTab->nCol;
preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
preupdate.iBlobWrite = iBlobWrite;
db->pPreUpdate = &preupdate;
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned int lo, hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (sqlite_uint64)hi << 32 | lo;
}
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
unsigned long junk;
__asm__ __volatile__ ("\n\
1: mftbu %1\n\
mftb %L0\n\
mftbu %0\n\
cmpw %0,%1\n\
bne 1b"
: "=r" (retval), "=r" (junk));
return retval;
}
#else
/*
** asm() is needed for hardware timing support. Without asm(),
** disable the sqlite3Hwtime() routine.
**
** sqlite3Hwtime() is only used for some obscure debugging
** and analysis configurations, not in any deliverable, so this
** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
#endif
#endif /* !defined(SQLITE_HWTIME_H) */
/************** End of hwtime.h **********************************************/
/************** Continuing where we left off in vdbe.c ***********************/
#endif
/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell. This macro verifies that shallow copies are
** not misused. A shallow copy of a string or blob just copies a
** pointer to the string or blob, not the content. If the original
** is changed while the copy is still in use, the string or blob might
** be changed out from under the copy. This macro verifies that nothing
** like that ever happens.
*/
#ifdef SQLITE_DEBUG
# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
#else
# define memAboutToChange(P,M)
#endif
/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
** procedures use this information to make sure that indices are
** working correctly. This variable has no function other than to
** help verify the correct operation of the library.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_search_count = 0;
#endif
/*
** When this global variable is positive, it gets decremented once before
** each instruction in the VDBE. When it reaches zero, the u1.isInterrupted
** field of the sqlite3 structure is set in order to simulate an interrupt.
**
** This facility is used for testing purposes only. It does not function
** in an ordinary build.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_interrupt_count = 0;
#endif
/*
** The next global variable is incremented each type the OP_Sort opcode
** is executed. The test procedures use this information to make sure that
** sorting is occurring or not occurring at appropriate times. This variable
** has no function other than to help verify the correct operation of the
** library.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_sort_count = 0;
#endif
/*
** The next global variable records the size of the largest MEM_Blob
** or MEM_Str that has been used by a VDBE opcode. The test procedures
** use this information to make sure that the zero-blob functionality
** is working correctly. This variable has no function other than to
** help verify the correct operation of the library.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_max_blobsize = 0;
static void updateMaxBlobsize(Mem *p){
if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){
sqlite3_max_blobsize = p->n;
}
}
#endif
/*
** This macro evaluates to true if either the update hook or the preupdate
** hook are enabled for database connect DB.
*/
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
# define HAS_UPDATE_HOOK(DB) ((DB)->xPreUpdateCallback||(DB)->xUpdateCallback)
#else
# define HAS_UPDATE_HOOK(DB) ((DB)->xUpdateCallback)
#endif
/*
** The next global variable is incremented each time the OP_Found opcode
** Since only a line number is retained, not the filename, this macro
** only works for amalgamation builds. But that is ok, since these macros
** should be no-ops except for special builds used to measure test coverage.
*/
#if !defined(SQLITE_VDBE_COVERAGE)
# define VdbeBranchTaken(I,M)
#else
# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
static void vdbeTakeBranch(u32 iSrcLine, u8 I, u8 M){
u8 mNever;
assert( I<=2 ); /* 0: fall through, 1: taken, 2: alternate taken */
assert( M<=4 ); /* 2: two-way branch, 3: three-way branch, 4: OP_Jump */
assert( I<M ); /* I can only be 2 if M is 3 or 4 */
/* Transform I from a integer [0,1,2] into a bitmask of [1,2,4] */
I = 1<<I;
/* The upper 8 bits of iSrcLine are flags. The lower three bits of
** the flags indicate directions that the branch can never go. If
** a branch really does go in one of those directions, assert right
** away. */
mNever = iSrcLine >> 24;
assert( (I & mNever)==0 );
if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
/* Invoke the branch coverage callback with three arguments:
** iSrcLine - the line number of the VdbeCoverage() macro, with
** flags removed.
** I - Mask of bits 0x07 indicating which cases are are
** fulfilled by this instance of the jump. 0x01 means
** fall-thru, 0x02 means taken, 0x04 means NULL. Any
** impossible cases (ex: if the comparison is never NULL)
** are filled in automatically so that the coverage
** measurement logic does not flag those impossible cases
** as missed coverage.
** M - Type of jump. Same as M argument above
*/
I |= mNever;
if( M==2 ) I |= 0x04;
if( M==4 ){
I |= 0x08;
if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/
}
sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
iSrcLine&0xffffff, I, M);
}
#endif
/*
** 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
** does not control the string, it might be deleted without the register
** knowing it.
**
** This routine converts an ephemeral string into a dynamically allocated
** string that the register itself controls. In other words, it
** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
*/
#define Deephemeralize(P) \
if( ((P)->flags&MEM_Ephem)!=0 \
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
#define isSorter(x) ((x)->eCurType==CURTYPE_SORTER)
/*
** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
** if we run out of memory.
*/
static VdbeCursor *allocateCursor(
Vdbe *p, /* The virtual machine */
int iCur, /* Index of the new VdbeCursor */
int nField, /* Number of fields in the table or index */
u8 eCurType /* Type of the new cursor */
){
/* Find the memory cell that will be used to store the blob of memory
** required for this VdbeCursor structure. It is convenient to use a
** vdbe memory cell to manage the memory allocation required for a
** VdbeCursor 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.
**
** The memory cell for cursor 0 is aMem[0]. The rest are allocated from
** the top of the register space. Cursor 1 is at Mem[p->nMem-1].
** Cursor 2 is at Mem[p->nMem-2]. And so forth.
*/
Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;
i64 nByte;
VdbeCursor *pCx = 0;
nByte = SZ_VDBECURSOR(nField);
assert( ROUND8(nByte)==nByte );
if( eCurType==CURTYPE_BTREE ) nByte += sqlite3BtreeCursorSize();
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
/* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
** the pMem used to hold space for the cursor has enough storage available
** in pMem->zMalloc. But for the special case of the aMem[] entries used
** to hold cursors, it is faster to in-line the logic. */
assert( pMem->flags==MEM_Undefined );
assert( (pMem->flags & MEM_Dyn)==0 );
assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
if( pMem->szMalloc<nByte ){
if( pMem->szMalloc>0 ){
sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
}
pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
if( pMem->zMalloc==0 ){
pMem->szMalloc = 0;
return 0;
}
pMem->szMalloc = (int)nByte;
}
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
pCx->eCurType = eCurType;
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( eCurType==CURTYPE_BTREE ){
assert( ROUND8(SZ_VDBECURSOR(nField))==SZ_VDBECURSOR(nField) );
pCx->uc.pCursor = (BtCursor*)&pMem->z[SZ_VDBECURSOR(nField)];
sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
}
/*
** The string in pRec is known to look like an integer and to have a
** floating point value of rValue. Return true and set *piValue to the
** integer value if the string is in range to be an integer. Otherwise,
** return false.
*/
static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){
i64 iValue;
iValue = sqlite3RealToI64(rValue);
if( sqlite3RealSameAsInt(rValue,iValue) ){
*piValue = iValue;
return 1;
}
return 0==sqlite3Atoi64(pRec->z, piValue, pRec->n, pRec->enc);
}
/*
** Try to convert a value into a numeric representation if we can
** do so without loss of information. In other words, if the string
** looks like a number, convert it into a number. If it does not
** look like a number, leave it alone.
**
** If the bTryForInt flag is true, then extra effort is made to give
** an integer representation. Strings that look like floating point
** values but which have no fractional component (example: '48.00')
** will have a MEM_Int representation when bTryForInt is true.
**
** If bTryForInt is false, then if the input string contains a decimal
** point or exponential notation, the result is only MEM_Real, even
** if there is an exact integer representation of the quantity.
*/
static void applyNumericAffinity(Mem *pRec, int bTryForInt){
}
#endif
/*
** Return the register of pOp->p2 after first preparing it to be
** overwritten with an integer value.
*/
static SQLITE_NOINLINE Mem *out2PrereleaseWithClear(Mem *pOut){
sqlite3VdbeMemSetNull(pOut);
pOut->flags = MEM_Int;
return pOut;
}
static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
Mem *pOut;
assert( pOp->p2>0 );
assert( pOp->p2<=(p->nMem+1 - p->nCursor) );
pOut = &p->aMem[pOp->p2];
memAboutToChange(p, pOut);
if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/
return out2PrereleaseWithClear(pOut);
}else{
pOut->flags = MEM_Int;
return pOut;
}
}
/*
** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning
** with pOp->p3. Return the hash.
*/
static u64 filterHash(const Mem *aMem, const Op *pOp){
int i, mx;
u64 h = 0;
assert( pOp->p4type==P4_INT32 );
for(i=pOp->p3, mx=i+pOp->p4.i; i<mx; i++){
const Mem *p = &aMem[i];
if( p->flags & (MEM_Int|MEM_IntReal) ){
h += p->u.i;
}else if( p->flags & MEM_Real ){
h += sqlite3VdbeIntValue(p);
}else if( p->flags & (MEM_Str|MEM_Blob) ){
/* All strings have the same hash and all blobs have the same hash,
** though, at least, those hashes are different from each other and
** from NULL. */
h += 4093 + (p->flags & (MEM_Str|MEM_Blob));
}
}
return h;
}
/*
** For OP_Column, factor out the case where content is loaded from
** overflow pages, so that the code to implement this case is separate
** the common case where all content fits on the page. Factoring out
** the code reduces register pressure and helps the common case
** to run faster.
*/
static SQLITE_NOINLINE int vdbeColumnFromOverflow(
VdbeCursor *pC, /* The BTree cursor from which we are reading */
int iCol, /* The column to read */
u32 t, /* The serial-type code for the column value */
i64 iOffset, /* Offset to the start of the content value */
u32 cacheStatus, /* Current Vdbe.cacheCtr value */
u32 colCacheCtr, /* Current value of the column cache counter */
Mem *pDest /* Store the value into this register. */
){
int rc;
sqlite3 *db = pDest->db;
int encoding = pDest->enc;
int len = sqlite3VdbeSerialTypeLen(t);
assert( pC->eCurType==CURTYPE_BTREE );
if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) return SQLITE_TOOBIG;
if( len > 4000 && pC->pKeyInfo==0 ){
/* Cache large column values that are on overflow pages using
** an RCStr (reference counted string) so that if they are reloaded,
** that do not have to be copied a second time. The overhead of
** creating and managing the cache is such that this is only
** profitable for larger TEXT and BLOB values.
**
** Only do this on table-btrees so that writes to index-btrees do not
** need to clear the cache. This buys performance in the common case
** in exchange for generality.
*/
VdbeTxtBlbCache *pCache;
char *pBuf;
if( pC->colCache==0 ){
pC->pCache = sqlite3DbMallocZero(db, sizeof(VdbeTxtBlbCache) );
if( pC->pCache==0 ) return SQLITE_NOMEM;
pC->colCache = 1;
}
pCache = pC->pCache;
if( pCache->pCValue==0
|| pCache->iCol!=iCol
|| pCache->cacheStatus!=cacheStatus
|| pCache->colCacheCtr!=colCacheCtr
|| pCache->iOffset!=sqlite3BtreeOffset(pC->uc.pCursor)
){
if( pCache->pCValue ) sqlite3RCStrUnref(pCache->pCValue);
pBuf = pCache->pCValue = sqlite3RCStrNew( len+3 );
if( pBuf==0 ) return SQLITE_NOMEM;
rc = sqlite3BtreePayload(pC->uc.pCursor, iOffset, len, pBuf);
if( rc ) return rc;
pBuf[len] = 0;
pBuf[len+1] = 0;
pBuf[len+2] = 0;
pCache->iCol = iCol;
pCache->cacheStatus = cacheStatus;
pCache->colCacheCtr = colCacheCtr;
pCache->iOffset = sqlite3BtreeOffset(pC->uc.pCursor);
}else{
pBuf = pCache->pCValue;
}
assert( t>=12 );
sqlite3RCStrRef(pBuf);
if( t&1 ){
rc = sqlite3VdbeMemSetStr(pDest, pBuf, len, encoding,
sqlite3RCStrUnref);
pDest->flags |= MEM_Term;
}else{
** See also: InitCoroutine
*/
case OP_EndCoroutine: { /* in1 */
VdbeOp *pCaller;
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags==MEM_Int );
assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
pCaller = &aOp[pIn1->u.i];
assert( pCaller->opcode==OP_Yield );
assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
pIn1->u.i = (int)(pOp - p->aOp) - 1;
pOp = &aOp[pCaller->p2 - 1];
break;
}
/* Opcode: Yield P1 P2 * * *
**
** Swap the program counter with the value in register P1. This
** has the effect of yielding to a coroutine.
**
** If the coroutine that is launched by this instruction ends with
** Yield or Return then continue to the next instruction. But if
** the coroutine launched by this instruction ends with
** EndCoroutine, then jump to P2 rather than continuing with the
** next instruction.
**
** See also: InitCoroutine
*/
case OP_Yield: { /* in1, jump0 */
int pcDest;
pIn1 = &aMem[pOp->p1];
assert( VdbeMemDynamic(pIn1)==0 );
pIn1->flags = MEM_Int;
pcDest = (int)pIn1->u.i;
pIn1->u.i = (int)(pOp - aOp);
REGISTER_TRACE(pOp->p1, pIn1);
pOp = &aOp[pcDest];
break;
}
/* Opcode: HaltIfNull P1 P2 P3 P4 P5
** Synopsis: if r[P3]=null halt
**
** Check the value in register P3. If it is NULL then Halt using
** parameter P1, P2, and P4 as if this were a Halt instruction. If the
** value in register P3 is not NULL, then this routine is a no-op.
** The P5 parameter should be 1.
*/
case OP_HaltIfNull: { /* in3 */
pIn3 = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
if( (pIn3->flags & MEM_Null)==0 ) break;
/* Fall through into OP_Halt */
/* no break */ deliberate_fall_through
}
/* Opcode: Halt P1 P2 P3 P4 P5
**
** Exit immediately. All open cursors, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0).
** For errors, it can be some other value. If P1!=0 then P2 will determine
** whether or not to rollback the current transaction. Do not rollback
** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
** then back out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
** If P3 is not zero and P4 is NULL, then P3 is a register that holds the
** text of an error message.
**
** If P3 is zero and P4 is not null then the error message string is held
** in P4.
**
** P5 is a value between 1 and 4, inclusive, then the P4 error message
** string is modified as follows:
**
** 1: NOT NULL constraint failed: P4
** 2: UNIQUE constraint failed: P4
** 3: CHECK constraint failed: P4
** 4: FOREIGN KEY constraint failed: P4
**
** If P3 is zero and P5 is not zero and P4 is NULL, then everything after
** the ":" is omitted.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program. So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
VdbeFrame *pFrame;
int pcx;
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
assert( pOp->p4type==P4_NOTUSED
|| pOp->p4type==P4_STATIC
|| pOp->p4type==P4_DYNAMIC );
/* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
** something is wrong with the code generator. Raise an assertion in order
** to bring this to the attention of fuzzers and other testing tools. */
assert( pOp->p1!=SQLITE_INTERNAL );
if( p->pFrame && pOp->p1==SQLITE_OK ){
/* Halt the sub-program. Return control to the parent frame. */
pFrame = p->pFrame;
p->pFrame = pFrame->pParent;
p->nFrame--;
sqlite3VdbeSetChanges(db, p->nChange);
pcx = sqlite3VdbeFrameRestore(pFrame);
if( pOp->p2==OE_Ignore ){
/* Instruction pcx is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
** instruction is set to OE_Ignore, then the sub-program is throwing
** an IGNORE exception. In this case jump to the address specified
** as the p2 of the calling OP_Program. */
p->pFrame->aOnce[iAddr/8] |= 1<<(iAddr & 7);
}else{
if( p->aOp[0].p1==pOp->p1 ){
VdbeBranchTaken(1, 2);
goto jump_to_p2;
}
}
VdbeBranchTaken(0, 2);
pOp->p1 = p->aOp[0].p1;
break;
}
/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true. The value
** is considered true if it is numeric and non-zero. If the value
** in P1 is NULL then take the jump if and only if P3 is non-zero.
*/
case OP_If: { /* jump, in1 */
int c;
c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3);
VdbeBranchTaken(c!=0, 2);
if( c ) goto jump_to_p2;
break;
}
/* Opcode: IfNot P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is False. The value
** is considered false if it has a numeric value of zero. If the value
** in P1 is NULL then take the jump if and only if P3 is non-zero.
*/
case OP_IfNot: { /* jump, in1 */
int c;
c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3);
VdbeBranchTaken(c!=0, 2);
if( c ) goto jump_to_p2;
break;
}
/* Opcode: IsNull P1 P2 * * *
** Synopsis: if r[P1]==NULL goto P2
**
** Jump to P2 if the value in register P1 is NULL.
*/
case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
if( (pIn1->flags & MEM_Null)!=0 ){
goto jump_to_p2;
}
break;
}
/* Opcode: IsType P1 P2 P3 P4 P5
** Synopsis: if typeof(P1.P3) in P5 goto P2
**
** Jump to P2 if the type of a column in a btree is one of the types specified
** by the P5 bitmask.
**
** P1 is normally a cursor on a btree for which the row decode cache is
** valid through at least column P3. In other words, there should have been
** a prior OP_Column for column P3 or greater. If the cursor is not valid,
** then this opcode might give spurious results.
** The the btree row has fewer than P3 columns, then use P4 as the
** datatype.
**
** If P1 is -1, then P3 is a register number and the datatype is taken
** from the value in that register.
**
** P5 is a bitmask of data types. SQLITE_INTEGER is the least significant
** (0x01) bit. SQLITE_FLOAT is the 0x02 bit. SQLITE_TEXT is 0x04.
** SQLITE_BLOB is 0x08. SQLITE_NULL is 0x10.
**
** WARNING: This opcode does not reliably distinguish between NULL and REAL
** when P1>=0. If the database contains a NaN value, this opcode will think
** that the datatype is REAL when it should be NULL. When P1<0 and the value
** is already stored in register P3, then this opcode does reliably
** distinguish between NULL and REAL. The problem only arises then P1>=0.
**
** Take the jump to address P2 if and only if the datatype of the
** value determined by P1 and P3 corresponds to one of the bits in the
** P5 bitmask.
**
*/
case OP_IsType: { /* jump */
VdbeCursor *pC;
u16 typeMask;
u32 serialType;
assert( pOp->p1>=(-1) && pOp->p1<p->nCursor );
assert( pOp->p1>=0 || (pOp->p3>=0 && pOp->p3<=(p->nMem+1 - p->nCursor)) );
if( pOp->p1>=0 ){
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pOp->p3>=0 );
if( pOp->p3<pC->nHdrParsed ){
serialType = pC->aType[pOp->p3];
if( serialType>=12 ){
if( serialType&1 ){
typeMask = 0x04; /* SQLITE_TEXT */
}else{
typeMask = 0x08; /* SQLITE_BLOB */
}
}else{
static const unsigned char aMask[] = {
0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2,
0x01, 0x01, 0x10, 0x10
};
testcase( serialType==0 );
testcase( serialType==1 );
testcase( serialType==2 );
testcase( serialType==3 );
testcase( serialType==4 );
testcase( serialType==5 );
testcase( serialType==6 );
testcase( serialType==7 );
testcase( serialType==8 );
testcase( serialType==9 );
testcase( serialType==10 );
testcase( serialType==11 );
typeMask = aMask[serialType];
}
}else{
typeMask = 1 << (pOp->p4.i - 1);
testcase( typeMask==0x01 );
testcase( typeMask==0x02 );
testcase( typeMask==0x04 );
testcase( typeMask==0x08 );
testcase( typeMask==0x10 );
}
}else{
assert( memIsValid(&aMem[pOp->p3]) );
typeMask = 1 << (sqlite3_value_type((sqlite3_value*)&aMem[pOp->p3])-1);
testcase( typeMask==0x01 );
testcase( typeMask==0x02 );
testcase( typeMask==0x04 );
testcase( typeMask==0x08 );
testcase( typeMask==0x10 );
}
VdbeBranchTaken( (typeMask & pOp->p5)!=0, 2);
if( typeMask & pOp->p5 ){
goto jump_to_p2;
}
break;
}
/* Opcode: ZeroOrNull P1 P2 P3 * *
** Synopsis: r[P2] = 0 OR NULL
**
** If both registers P1 and P3 are NOT NULL, then store a zero in
** register P2. If either registers P1 or P3 are NULL then put
** a NULL in register P2.
*/
case OP_ZeroOrNull: { /* in1, in2, out2, in3 */
if( (aMem[pOp->p1].flags & MEM_Null)!=0
|| (aMem[pOp->p3].flags & MEM_Null)!=0
){
sqlite3VdbeMemSetNull(aMem + pOp->p2);
}else{
sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0);
}
break;
}
/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
** Jump to P2 if the value in register P1 is not NULL.
*/
case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2);
if( (pIn1->flags & MEM_Null)==0 ){
goto jump_to_p2;
}
break;
}
/* Opcode: IfNullRow P1 P2 P3 * *
** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2
**
** Check the cursor P1 to see if it is currently pointing at a NULL row.
** If it is, then set register P3 to NULL and jump immediately to P2.
** If P1 is not on a NULL row, then fall through without making any
** changes.
**
** If P1 is not an open cursor, then this opcode is a no-op.
*/
case OP_IfNullRow: { /* jump */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
if( pC && pC->nullRow ){
sqlite3VdbeMemSetNull(aMem + pOp->p3);
goto jump_to_p2;
}
break;
}
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
/* Opcode: Offset P1 P2 P3 * *
** Synopsis: r[P3] = sqlite_offset(P1)
**
** Store in register r[P3] the byte offset into the database file that is the
** start of the payload for the record at which that cursor P1 is currently
** pointing.
**
** P2 is the column number for the argument to the sqlite_offset() function.
** This opcode does not use P2 itself, but the P2 value is used by the
** code generator. The P1, P2, and P3 operands to this opcode are the
** same as for OP_Column.
**
** This opcode is only available if SQLite is compiled with the
** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option.
*/
case OP_Offset: { /* out3 */
VdbeCursor *pC; /* The VDBE cursor */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
pOut = &p->aMem[pOp->p3];
if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){
sqlite3VdbeMemSetNull(pOut);
}else{
if( pC->deferredMoveto ){
rc = sqlite3VdbeFinishMoveto(pC);
if( rc ) goto abort_due_to_error;
}
if( sqlite3BtreeEof(pC->uc.pCursor) ){
sqlite3VdbeMemSetNull(pOut);
}else{
sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
}
}
break;
}
#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
/* Opcode: Column P1 P2 P3 P4 P5
** Synopsis: r[P3]=PX cursor P1 column P2
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction. (See the MakeRecord opcode for additional
** information about the format of the data.) Extract the P2-th column
** from this record. If there are less than (P2+1)
** values in the record, extract a NULL.
**
** The value extracted is stored in register P3.
**
** If the record contains fewer than P2 fields, then extract a NULL. Or,
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
** If the OPFLAG_LENGTHARG bit is set in P5 then the result is guaranteed
** to only be used by the length() function or the equivalent. The content
** of large blobs is not loaded, thus saving CPU cycles. If the
** OPFLAG_TYPEOFARG bit is set then the result will only be used by the
** typeof() function or the IS NULL or IS NOT NULL operators or the
** equivalent. In this case, all content loading can be omitted.
*/
case OP_Column: { /* ncycle */
u32 p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
BtCursor *pCrsr; /* The B-Tree cursor corresponding to pC */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
int len; /* The length of the serialized data for the column */
int i; /* Loop counter */
Mem *pDest; /* Where to write the extracted value */
Mem sMem; /* For storing the record being decoded */
const u8 *zData; /* Part of the record being decoded */
const u8 *zHdr; /* Next unparsed byte of the header */
const u8 *zEndHdr; /* Pointer to first byte after the header */
u64 offset64; /* 64-bit offset */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pC = p->apCsr[pOp->p1];
p2 = (u32)pOp->p2;
op_column_restart:
assert( pC!=0 );
assert( p2<(u32)pC->nField
|| (pC->eCurType==CURTYPE_PSEUDO && pC->seekResult==0) );
aOffset = pC->aOffset;
assert( aOffset==pC->aType+pC->nField );
assert( pC->eCurType!=CURTYPE_VTAB );
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
assert( pC->eCurType!=CURTYPE_SORTER );
if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/
if( pC->nullRow ){
if( pC->eCurType==CURTYPE_PSEUDO && pC->seekResult>0 ){
/* For the special case of as pseudo-cursor, the seekResult field
** identifies the register that holds the record */
pReg = &aMem[pC->seekResult];
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
pC->payloadSize = pC->szRow = pReg->n;
pC->aRow = (u8*)pReg->z;
}else{
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
sqlite3VdbeMemSetNull(pDest);
goto op_column_out;
}
}else{
pCrsr = pC->uc.pCursor;
if( pC->deferredMoveto ){
u32 iMap;
assert( !pC->isEphemeral );
if( pC->ub.aAltMap && (iMap = pC->ub.aAltMap[1+p2])>0 ){
pC = pC->pAltCursor;
p2 = iMap - 1;
goto op_column_restart;
}
rc = sqlite3VdbeFinishMoveto(pC);
if( rc ) goto abort_due_to_error;
}else if( sqlite3BtreeCursorHasMoved(pCrsr) ){
rc = sqlite3VdbeHandleMovedCursor(pC);
if( rc ) goto abort_due_to_error;
goto op_column_restart;
}
assert( pC->eCurType==CURTYPE_BTREE );
assert( pCrsr );
assert( sqlite3BtreeCursorIsValid(pCrsr) );
pC->payloadSize = sqlite3BtreePayloadSize(pCrsr);
pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow);
assert( pC->szRow<=pC->payloadSize );
assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */
}
pC->cacheStatus = p->cacheCtr;
if( (aOffset[0] = pC->aRow[0])<0x80 ){
pC->iHdrOffset = 1;
}else{
pC->iHdrOffset = sqlite3GetVarint32(pC->aRow, aOffset);
}
pC->nHdrParsed = 0;
if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/
/* pC->aRow does not have to hold the entire row, but it does at least
** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
** dynamically allocated. */
pC->aRow = 0;
pC->szRow = 0;
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
**
** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
** types use so much data space that there can only be 4096 and 32 of
** them, respectively. So the maximum header length results from a
** 3-byte type for each of the maximum of 32768 columns plus three
/* NULL value. No change in zPayload */
}else{
u64 v;
if( serial_type==7 ){
assert( sizeof(v)==sizeof(pRec->u.r) );
memcpy(&v, &pRec->u.r, sizeof(v));
swapMixedEndianFloat(v);
}else{
v = pRec->u.i;
}
len = sqlite3SmallTypeSizes[serial_type];
assert( len>=1 && len<=8 && len!=5 && len!=7 );
switch( len ){
default: zPayload[7] = (u8)(v&0xff); v >>= 8;
zPayload[6] = (u8)(v&0xff); v >>= 8;
/* no break */ deliberate_fall_through
case 6: zPayload[5] = (u8)(v&0xff); v >>= 8;
zPayload[4] = (u8)(v&0xff); v >>= 8;
/* no break */ deliberate_fall_through
case 4: zPayload[3] = (u8)(v&0xff); v >>= 8;
/* no break */ deliberate_fall_through
case 3: zPayload[2] = (u8)(v&0xff); v >>= 8;
/* no break */ deliberate_fall_through
case 2: zPayload[1] = (u8)(v&0xff); v >>= 8;
/* no break */ deliberate_fall_through
case 1: zPayload[0] = (u8)(v&0xff);
}
zPayload += len;
}
}else if( serial_type<0x80 ){
*(zHdr++) = serial_type;
if( serial_type>=14 && pRec->n>0 ){
assert( pRec->z!=0 );
memcpy(zPayload, pRec->z, pRec->n);
zPayload += pRec->n;
}
}else{
zHdr += sqlite3PutVarint(zHdr, serial_type);
if( pRec->n ){
assert( pRec->z!=0 );
assert( pRec->z!=(const char*)sqlite3CtypeMap );
memcpy(zPayload, pRec->z, pRec->n);
zPayload += pRec->n;
}
}
if( pRec==pLast ) break;
pRec++;
}
assert( nHdr==(int)(zHdr - (u8*)pOut->z) );
assert( nByte==(int)(zPayload - (u8*)pOut->z) );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
REGISTER_TRACE(pOp->p3, pOut);
break;
}
/* Opcode: Count P1 P2 P3 * *
** Synopsis: r[P2]=count()
**
** Store the number of entries (an integer value) in the table or index
** opened by cursor P1 in register P2.
**
** If P3==0, then an exact count is obtained, which involves visiting
** every btree page of the table. But if P3 is non-zero, an estimate
** is returned based on the current cursor position.
*/
case OP_Count: { /* out2 */
i64 nEntry;
BtCursor *pCrsr;
assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
assert( pCrsr );
if( pOp->p3 ){
nEntry = sqlite3BtreeRowCountEst(pCrsr);
}else{
nEntry = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
if( rc ) goto abort_due_to_error;
}
pOut = out2Prerelease(p, pOp);
pOut->u.i = nEntry;
goto check_for_interrupt;
}
/* Opcode: Savepoint P1 * * P4 *
**
** Open, release or rollback the savepoint named by parameter P4, depending
** on the value of P1. To open a new savepoint set P1==0 (SAVEPOINT_BEGIN).
** To release (commit) an existing savepoint set P1==1 (SAVEPOINT_RELEASE).
** To rollback an existing savepoint set P1==2 (SAVEPOINT_ROLLBACK).
*/
case OP_Savepoint: {
int p1; /* Value of P1 operand */
char *zName; /* Name of savepoint */
int nName;
Savepoint *pNew;
Savepoint *pSavepoint;
Savepoint *pTmp;
int iSavepoint;
int ii;
p1 = pOp->p1;
zName = pOp->p4.z;
/* Assert that the p1 parameter is valid. Also that if there is no open
** transaction, then there cannot be any savepoints.
*/
assert( db->pSavepoint==0 || db->autoCommit==0 );
assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK );
assert( db->pSavepoint || db->isTransactionSavepoint==0 );
assert( checkSavepointCount(db) );
assert( p->bIsReader );
if( p1==SAVEPOINT_BEGIN ){
if( db->nVdbeWrite>0 ){
/* A new savepoint cannot be created if there are active write
** statements (i.e. open read/write incremental blob handles).
*/
sqlite3VdbeError(p, "cannot open savepoint - SQL statements in progress");
rc = SQLITE_BUSY;
}else{
nName = sqlite3Strlen30(zName);
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
}
/* Store the current value of the database handles deferred constraint
** counter. If the statement transaction needs to be rolled back,
** the value of this counter needs to be restored too. */
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
if( rc==SQLITE_OK
&& pOp->p5
&& (iMeta!=pOp->p3 || pDb->pSchema->iGeneration!=pOp->p4.i)
){
/*
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
** version is checked to ensure that the schema has not changed since the
** SQL statement was prepared.
*/
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
** stored with the in-memory representation of the schema, do
** not reload the schema from the database file.
**
** If virtual-tables are in use, this is not just an optimization.
** Often, v-tables store their data in other SQLite tables, which
** are queried from within xNext() and other v-table methods using
** prepared queries. If such a query is out-of-date, we do not want to
** discard the database schema, as the user code implementing the
** v-table would have to be ready for the sqlite3_vtab structure itself
** to be invalidated whenever sqlite3_step() is called from within
** a v-table method.
*/
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
sqlite3ResetOneSchema(db, pOp->p1);
}
p->expired = 1;
rc = SQLITE_SCHEMA;
/* Set changeCntOn to 0 to prevent the value returned by sqlite3_changes()
** from being modified in sqlite3VdbeHalt(). If this statement is
** reprepared, changeCntOn will be set again. */
p->changeCntOn = 0;
}
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: ReadCookie P1 P2 P3 * *
**
** Read cookie number P3 from database P1 and write it into register P2.
** P3==1 is the schema version. P3==2 is the database format.
** P3==3 is the recommended pager cache size, and so forth. P1==0 is
** the main database file and P1==1 is the database file used to store
** temporary tables.
**
** There must be a read-lock on the database (either a transaction
** must be started or there must be an open cursor) before
** executing this instruction.
*/
case OP_ReadCookie: { /* out2 */
int iMeta;
int iDb;
int iCookie;
assert( p->bIsReader );
iDb = pOp->p1;
iCookie = pOp->p3;
assert( pOp->p3<SQLITE_N_BTREE_META );
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 );
assert( DbMaskTest(p->btreeMask, iDb) );
sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
pOut = out2Prerelease(p, pOp);
pOut->u.i = iMeta;
break;
}
/* Opcode: SetCookie P1 P2 P3 * P5
**
** Write the integer value P3 into cookie number P2 of database P1.
** P2==1 is the schema version. P2==2 is the database format.
** P2==3 is the recommended pager cache
** size, and so forth. P1==0 is the main database file and P1==1 is the
** database file used to store temporary tables.
**
** A transaction must be started before executing this opcode.
**
** If P2 is the SCHEMA_VERSION cookie (cookie number 1) then the internal
** schema version is set to P3-P5. The "PRAGMA schema_version=N" statement
** has P5 set to 1, so that the internal schema version will be different
** from the database schema version, resulting in a schema reset.
*/
case OP_SetCookie: {
Db *pDb;
sqlite3VdbeIncrWriteCounter(p, 0);
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( p->readOnly==0 );
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
/* See note about index shifting on OP_ReadCookie */
rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3);
if( pOp->p2==BTREE_SCHEMA_VERSION ){
/* When the schema cookie changes, record the new cookie internally */
*(u32*)&pDb->pSchema->schema_cookie = *(u32*)&pOp->p3 - pOp->p5;
db->mDbFlags |= DBFLAG_SchemaChange;
sqlite3FkClearTriggerCache(db, pOp->p1);
}else if( pOp->p2==BTREE_FILE_FORMAT ){
/* Record changes in the file format */
pDb->pSchema->file_format = pOp->p3;
}
if( pOp->p1==1 ){
/* Invalidate all prepared statements whenever the TEMP database
** schema is changed. Ticket #1644 */
sqlite3ExpirePreparedStatements(db, 0);
p->expired = 0;
}
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: OpenRead P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
** Open a read-only cursor for the database table whose root page is
** P2 in a database file. The database file is determined by P3.
** P3==0 means the main database, P3==1 means the database used for
** temporary tables, and P3>1 means used the corresponding attached
** database. Give the new cursor an identifier of P1. The P1
** values need not be contiguous but all P1 values should be small integers.
** It is an error for P1 to be negative.
**
** Allowed P5 bits:
** <ul>
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
** of OP_SeekLE/OP_IdxLT)
** </ul>
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
** object, then table being opened must be an [index b-tree] where the
** KeyInfo object defines the content and collating
** sequence of that index b-tree. Otherwise, if P4 is an integer
** value, then the table being opened must be a [table b-tree] with a
** number of columns no less than the value of P4.
**
** See also: OpenWrite, ReopenIdx
*/
/* Opcode: ReopenIdx P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
** The ReopenIdx opcode works like OP_OpenRead except that it first
** checks to see if the cursor on P1 is already open on the same
** b-tree and if it is this opcode becomes a no-op. In other words,
** if the cursor is already open, do not reopen it.
**
** The ReopenIdx opcode may only be used with P5==0 or P5==OPFLAG_SEEKEQ
** and with P4 being a P4_KEYINFO object. Furthermore, the P3 value must
** be the same as every other ReopenIdx or OpenRead for the same cursor
** number.
**
** Allowed P5 bits:
** <ul>
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
** of OP_SeekLE/OP_IdxLT)
** </ul>
**
** See also: OP_OpenRead, OP_OpenWrite
*/
/* Opcode: OpenWrite P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
** Open a read/write cursor named P1 on the table or index whose root
** page is P2 (or whose root page is held in register P2 if the
** OPFLAG_P2ISREG bit is set in P5 - see below).
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
** object, then table being opened must be an [index b-tree] where the
** KeyInfo object defines the content and collating
** sequence of that index b-tree. Otherwise, if P4 is an integer
** value, then the table being opened must be a [table b-tree] with a
** number of columns no less than the value of P4.
**
** Allowed P5 bits:
** <ul>
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
** of OP_SeekLE/OP_IdxLT)
** <li> <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek
** and subsequently delete entries in an index btree. This is a
** hint to the storage engine that the storage engine is allowed to
** ignore. The hint is not used by the official SQLite b*tree storage
** engine, but is used by COMDB2.
** <li> <b>0x10 OPFLAG_P2ISREG</b>: Use the content of register P2
** as the root page, not the value of P2 itself.
** </ul>
**
** This instruction works like OpenRead except that it opens the cursor
** in read/write mode.
**
** See also: OP_OpenRead, OP_ReopenIdx
*/
case OP_ReopenIdx: { /* ncycle */
int nField;
KeyInfo *pKeyInfo;
u32 p2;
int iDb;
int wrFlag;
Btree *pX;
VdbeCursor *pCur;
Db *pDb;
assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( pOp->p4type==P4_KEYINFO );
pCur = p->apCsr[pOp->p1];
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
assert( pCur->eCurType==CURTYPE_BTREE );
sqlite3BtreeClearCursor(pCur->uc.pCursor);
goto open_cursor_set_hints;
}
/* If the cursor is not currently open or is open on a different
** index, then fall through into OP_OpenRead to force a reopen */
case OP_OpenRead: /* ncycle */
case OP_OpenWrite:
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( p->bIsReader );
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|| p->readOnly==0 );
if( p->expired==1 ){
rc = SQLITE_ABORT_ROLLBACK;
goto abort_due_to_error;
}
nField = 0;
pKeyInfo = 0;
p2 = (u32)pOp->p2;
iDb = pOp->p3;
assert( iDb>=0 && iDb<db->nDb );
assert( DbMaskTest(p->btreeMask, iDb) );
pDb = &db->aDb[iDb];
pX = pDb->pBt;
assert( pX!=0 );
if( pOp->opcode==OP_OpenWrite ){
assert( OPFLAG_FORDELETE==BTREE_FORDELETE );
wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
p->minWriteFileFormat = pDb->pSchema->file_format;
}
if( pOp->p5 & OPFLAG_P2ISREG ){
assert( p2>0 );
assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
pIn2 = &aMem[p2];
assert( memIsValid(pIn2) );
assert( (pIn2->flags & MEM_Int)!=0 );
sqlite3VdbeMemIntegerify(pIn2);
p2 = (int)pIn2->u.i;
/* The p2 value always comes from a prior OP_CreateBtree opcode and
** that opcode will always set the p2 value to 2 or more or else fail.
** If there were a failure, the prepared statement would have halted
** before reaching this instruction. */
assert( p2>=2 );
}
}else{
wrFlag = 0;
assert( (pOp->p5 & OPFLAG_P2ISREG)==0 );
}
if( pOp->p4type==P4_KEYINFO ){
pKeyInfo = pOp->p4.pKeyInfo;
assert( pKeyInfo->enc==ENC(db) );
assert( pKeyInfo->db==db );
nField = pKeyInfo->nAllField;
}else if( pOp->p4type==P4_INT32 ){
nField = pOp->p4.i;
}
assert( pOp->p1>=0 );
assert( nField>=0 );
testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
pCur = allocateCursor(p, pOp->p1, nField, CURTYPE_BTREE);
if( pCur==0 ) goto no_mem;
pCur->iDb = iDb;
pCur->nullRow = 1;
pCur->isOrdered = 1;
pCur->pgnoRoot = p2;
#ifdef SQLITE_DEBUG
pCur->wrFlag = wrFlag;
#endif
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->uc.pCursor);
pCur->pKeyInfo = pKeyInfo;
/* Set the VdbeCursor.isTable variable. Previous versions of
** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has
** since moved into the btree layer. */
pCur->isTable = pOp->p4type!=P4_KEYINFO;
open_cursor_set_hints:
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
testcase( pOp->p5 & OPFLAG_BULKCSR );
testcase( pOp->p2 & OPFLAG_SEEKEQ );
sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: OpenDup P1 P2 * * *
**
** Open a new cursor P1 that points to the same ephemeral table as
** cursor P2. The P2 cursor must have been opened by a prior OP_OpenEphemeral
** opcode. Only ephemeral cursors may be duplicated.
**
** Duplicate ephemeral cursors are used for self-joins of materialized views.
*/
case OP_OpenDup: { /* ncycle */
VdbeCursor *pOrig; /* The original cursor to be duplicated */
VdbeCursor *pCx; /* The new cursor */
pOrig = p->apCsr[pOp->p2];
assert( pOrig );
assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */
pCx = allocateCursor(p, pOp->p1, pOrig->nField, CURTYPE_BTREE);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->isEphemeral = 1;
pCx->pKeyInfo = pOrig->pKeyInfo;
pCx->isTable = pOrig->isTable;
pCx->pgnoRoot = pOrig->pgnoRoot;
pCx->isOrdered = pOrig->isOrdered;
pCx->ub.pBtx = pOrig->ub.pBtx;
pCx->noReuse = 1;
pOrig->noReuse = 1;
rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pCx->pKeyInfo, pCx->uc.pCursor);
/* The sqlite3BtreeCursor() routine can only fail for the first cursor
** opened for a database. Since there is already an open cursor when this
** opcode is run, the sqlite3BtreeCursor() cannot fail */
assert( rc==SQLITE_OK );
break;
}
/* Opcode: OpenEphemeral P1 P2 P3 P4 P5
** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if
** the main database is read-only. The ephemeral
** table is deleted automatically when the cursor is closed.
**
** If the cursor P1 is already opened on an ephemeral table, the table
** is cleared (all content is erased).
**
** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
**
** The P5 parameter can be a mask of the BTREE_* flags defined
** in btree.h. These flags control aspects of the operation of
** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
** added automatically.
**
** If P3 is positive, then reg[P3] is modified slightly so that it
** can be used as zero-length data for OP_Insert. This is an optimization
** that avoids an extra OP_Blob opcode to initialize that register.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
** Synopsis: nColumn=P2
**
** This opcode works the same as OP_OpenEphemeral. It has a
** different name to distinguish its use. Tables created using
** by this opcode will be used for automatically created transient
** indices in joins.
*/
case OP_OpenAutoindex: /* ncycle */
case OP_OpenEphemeral: { /* ncycle */
VdbeCursor *pCx;
KeyInfo *pKeyInfo;
static const int vfsFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
if( pOp->p3>0 ){
/* Make register reg[P3] into a value that can be used as the data
** form sqlite3BtreeInsert() where the length of the data is zero. */
assert( pOp->p2==0 ); /* Only used when number of columns is zero */
assert( pOp->opcode==OP_OpenEphemeral );
assert( aMem[pOp->p3].flags & MEM_Null );
aMem[pOp->p3].n = 0;
aMem[pOp->p3].z = "";
}
pCx = p->apCsr[pOp->p1];
if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){
/* If the ephemeral table is already open and has no duplicates from
** OP_OpenDup, then erase all existing content so that the table is
** empty again, rather than creating a new table. */
assert( pCx->isEphemeral );
pCx->seqCount = 0;
pCx->cacheStatus = CACHE_STALE;
rc = sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0);
}else{
pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE);
if( pCx==0 ) goto no_mem;
pCx->isEphemeral = 1;
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5,
vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0);
assert( pOp->p4type==P4_KEYINFO );
rc = sqlite3BtreeCreateTable(pCx->ub.pBtx, &pCx->pgnoRoot,
BTREE_BLOBKEY | pOp->p5);
if( rc==SQLITE_OK ){
assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
assert( pKeyInfo->db==db );
assert( pKeyInfo->enc==ENC(db) );
rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pKeyInfo, pCx->uc.pCursor);
}
pCx->isTable = 0;
}else{
pCx->pgnoRoot = SCHEMA_ROOT;
rc = sqlite3BtreeCursor(pCx->ub.pBtx, SCHEMA_ROOT, BTREE_WRCSR,
0, pCx->uc.pCursor);
pCx->isTable = 1;
}
}
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
assert( p->apCsr[pOp->p1]==pCx );
if( rc ){
assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
sqlite3BtreeClose(pCx->ub.pBtx);
p->apCsr[pOp->p1] = 0; /* Not required; helps with static analysis */
}else{
assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
}
}
}
if( rc ) goto abort_due_to_error;
pCx->nullRow = 1;
break;
}
/* Opcode: SorterOpen P1 P2 P3 P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
** tables using an external merge-sort algorithm.
**
** If argument P3 is non-zero, then it indicates that the sorter may
** assume that a stable sort considering the first P3 fields of each
** key is sufficient to produce the required results.
*/
case OP_SorterOpen: {
VdbeCursor *pCx;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER);
if( pCx==0 ) goto no_mem;
pCx->pKeyInfo = pOp->p4.pKeyInfo;
assert( pCx->pKeyInfo->db==db );
assert( pCx->pKeyInfo->enc==ENC(db) );
rc = sqlite3VdbeSorterInit(db, pOp->p3, pCx);
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: SequenceTest P1 P2 * * *
** Synopsis: if( cursor[P1].ctr++ ) pc = P2
**
** P1 is a sorter cursor. If the sequence counter is currently zero, jump
** to P2. Regardless of whether or not the jump is taken, increment the
** the sequence value.
*/
case OP_SequenceTest: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
if( (pC->seqCount++)==0 ){
goto jump_to_p2;
}
break;
}
/* Opcode: OpenPseudo P1 P2 P3 * *
** Synopsis: P3 columns in r[P2]
**
** Open a new cursor that points to a fake table that contains a single
** row of data. The content of that one row is the content of memory
** register P2. In other words, cursor P1 becomes an alias for the
** MEM_Blob content contained in register P2.
**
** A pseudo-table created by this opcode is used to hold a single
** row output from the sorter so that the row can be decomposed into
** individual columns using the OP_Column opcode. The OP_Column opcode
** is the only cursor opcode that works with a pseudo-table.
**
** P3 is the number of fields in the records that will be stored by
** the pseudo-table. If P2 is 0 or negative then the pseudo-cursor
** will return NULL for every column.
*/
case OP_OpenPseudo: {
VdbeCursor *pCx;
assert( pOp->p1>=0 );
assert( pOp->p3>=0 );
pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->seekResult = pOp->p2;
pCx->isTable = 1;
/* Give this pseudo-cursor a fake BtCursor pointer so that pCx
** can be safely passed to sqlite3VdbeCursorMoveto(). This avoids a test
** for pCx->eCurType==CURTYPE_BTREE inside of sqlite3VdbeCursorMoveto()
** which is a performance optimization */
pCx->uc.pCursor = sqlite3BtreeFakeValidCursor();
assert( pOp->p5==0 );
break;
}
/* Opcode: Close P1 * * * *
**
** Close a cursor previously opened as P1. If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: { /* ncycle */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
p->apCsr[pOp->p1] = 0;
break;
}
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
/* Opcode: ColumnsUsed P1 * * P4 *
**
** This opcode (which only exists if SQLite was compiled with
** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the
** table or index for cursor P1 are used. P4 is a 64-bit integer
** (P4_INT64) in which the first 63 bits are one for each of the
** first 63 columns of the table or index that are actually used
** by the cursor. The high-order bit is set if any column after
** the 64th is used.
*/
case OP_ColumnsUsed: {
VdbeCursor *pC;
pC = p->apCsr[pOp->p1];
assert( pC->eCurType==CURTYPE_BTREE );
pC->maskUsed = *(u64*)pOp->p4.pI64;
break;
}
#endif
/* Opcode: SeekGE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
** use the value in register P3 as the 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.
**
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
** opcode will either land on a record that exactly matches the key, or
** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ,
** this opcode must be followed by an IdxLE opcode with the same arguments.
** The IdxGT opcode will be skipped if this opcode succeeds, but the
** IdxGT opcode will be used on subsequent loop iterations. The
** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this
** is an equality search.
**
** This opcode leaves the cursor configured to move in forward order,
** from the beginning toward the end. In other words, the cursor is
** configured to use Next, not Prev.
**
** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
*/
/* Opcode: SeekGT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
** use the 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 the key value. If there are no records greater than
** the key and P2 is not zero, then jump to P2.
**
** This opcode leaves the cursor configured to move in forward order,
** from the beginning toward the end. In other words, the cursor is
** configured to use Next, not Prev.
**
** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
*/
/* Opcode: SeekLT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
** use the 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.
**
** This opcode leaves the cursor configured to move in reverse order,
** from the end toward the beginning. In other words, the cursor is
** configured to use Prev, not Next.
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
*/
/* Opcode: SeekLE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
** use the 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 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.
**
** This opcode leaves the cursor configured to move in reverse order,
** from the end toward the beginning. In other words, the cursor is
** configured to use Prev, not Next.
**
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
** opcode will either land on a record that exactly matches the key, or
** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ,
** this opcode must be followed by an IdxLE opcode with the same arguments.
** The IdxGE opcode will be skipped if this opcode succeeds, but the
** IdxGE opcode will be used on subsequent loop iterations. The
** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this
** is an equality search.
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLT: /* jump0, in3, group, ncycle */
case OP_SeekLE: /* jump0, in3, group, ncycle */
case OP_SeekGE: /* jump0, in3, group, ncycle */
case OP_SeekGT: { /* jump0, in3, group, ncycle */
int res; /* Comparison result */
int oc; /* Opcode */
VdbeCursor *pC; /* The cursor to seek */
UnpackedRecord r; /* The key to seek for */
int nField; /* Number of columns or fields in the key */
i64 iKey; /* The rowid we are to seek to */
int eqOnly; /* Only interested in == results */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p2!=0 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( OP_SeekLE == OP_SeekLT+1 );
assert( OP_SeekGE == OP_SeekLT+2 );
assert( OP_SeekGT == OP_SeekLT+3 );
assert( pC->isOrdered );
assert( pC->uc.pCursor!=0 );
oc = pOp->opcode;
eqOnly = 0;
pC->nullRow = 0;
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
if( pC->isTable ){
u16 flags3, newType;
/* The OPFLAG_SEEKEQ/BTREE_SEEK_EQ flag is only set on index cursors */
assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
|| CORRUPT_DB );
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
** the seek, so convert it. */
pIn3 = &aMem[pOp->p3];
flags3 = pIn3->flags;
if( (flags3 & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3, 0);
}
iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */
newType = pIn3->flags; /* Record the type after applying numeric affinity */
pIn3->flags = flags3; /* But convert the type back to its original */
/* If the P3 value could not be converted into an integer without
** loss of information, then special processing is required... */
if( (newType & (MEM_Int|MEM_IntReal))==0 ){
int c;
if( (newType & MEM_Real)==0 ){
if( (newType & MEM_Null) || oc>=OP_SeekGE ){
VdbeBranchTaken(1,2);
goto jump_to_p2;
}else{
rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
goto seek_not_found;
}
}
c = sqlite3IntFloatCompare(iKey, pIn3->u.r);
/* If the approximation iKey is larger than the actual real search
** term, substitute >= for > and < for <=. e.g. if the search term
** is 4.9 and the integer approximation 5:
**
** (x > 4.9) -> (x >= 5)
** (x <= 4.9) -> (x < 5)
*/
if( c>0 ){
assert( OP_SeekGE==(OP_SeekGT-1) );
assert( OP_SeekLT==(OP_SeekLE-1) );
assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
}
/* If the approximation iKey is smaller than the actual real search
** term, substitute <= for < and > for >=. */
else if( c<0 ){
assert( OP_SeekLE==(OP_SeekLT+1) );
assert( OP_SeekGT==(OP_SeekGE+1) );
assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
}
}
rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)iKey, 0, &res);
pC->movetoTarget = iKey; /* Used by OP_Delete */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
}else{
/* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the
** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be
** immediately followed by an OP_IdxGT or OP_IdxLT opcode, respectively,
** with the same key.
*/
if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){
eqOnly = 1;
assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
assert( pOp->opcode==OP_SeekGE || pOp[1].opcode==OP_IdxLT );
assert( pOp->opcode==OP_SeekLE || pOp[1].opcode==OP_IdxGT );
assert( pOp[1].p1==pOp[0].p1 );
assert( pOp[1].p2==pOp[0].p2 );
assert( pOp[1].p3==pOp[0].p3 );
assert( pOp[1].p4.i==pOp[0].p4.i );
}
nField = pOp->p4.i;
assert( pOp->p4type==P4_INT32 );
assert( nField>0 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)nField;
/* The next line of code computes as follows, only faster:
** if( oc==OP_SeekGT || oc==OP_SeekLE ){
** r.default_rc = -1;
** }else{
** r.default_rc = +1;
** }
*/
r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1);
assert( oc!=OP_SeekGT || r.default_rc==-1 );
assert( oc!=OP_SeekLE || r.default_rc==-1 );
assert( oc!=OP_SeekGE || r.default_rc==+1 );
assert( oc!=OP_SeekLT || r.default_rc==+1 );
r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
{
int i;
for(i=0; i<r.nField; i++){
assert( memIsValid(&r.aMem[i]) );
if( i>0 ) REGISTER_TRACE(pOp->p3+i, &r.aMem[i]);
}
}
#endif
r.eqSeen = 0;
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( eqOnly && r.eqSeen==0 ){
assert( res!=0 );
goto seek_not_found;
}
}
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT );
if( res<0 || (res==0 && oc==OP_SeekGT) ){
}else{
goto abort_due_to_error;
}
}
}else{
res = 0;
}
}else{
assert( oc==OP_SeekLT || oc==OP_SeekLE );
if( res>0 || (res==0 && oc==OP_SeekLT) ){
res = 0;
rc = sqlite3BtreePrevious(pC->uc.pCursor, 0);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
res = 1;
}else{
goto abort_due_to_error;
}
}
}else{
/* res might be negative because the table is empty. Check to
** see if this is the case.
*/
res = sqlite3BtreeEof(pC->uc.pCursor);
}
}
seek_not_found:
assert( pOp->p2>0 );
VdbeBranchTaken(res!=0,2);
if( res ){
goto jump_to_p2;
}else if( eqOnly ){
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
}
break;
}
/* Opcode: SeekScan P1 P2 * * P5
** Synopsis: Scan-ahead up to P1 rows
**
** This opcode is a prefix opcode to OP_SeekGE. In other words, this
** opcode must be immediately followed by OP_SeekGE. This constraint is
** checked by assert() statements.
**
** This opcode uses the P1 through P4 operands of the subsequent
** OP_SeekGE. In the text that follows, the operands of the subsequent
** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only
** the P1, P2 and P5 operands of this opcode are also used, and are called
** This.P1, This.P2 and This.P5.
**
** This opcode helps to optimize IN operators on a multi-column index
** where the IN operator is on the later terms of the index by avoiding
** unnecessary seeks on the btree, substituting steps to the next row
** of the b-tree instead. A correct answer is obtained if this opcode
** is omitted or is a no-op.
**
** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which
** is the desired entry that we want the cursor SeekGE.P1 to be pointing
** to. Call this SeekGE.P3/P4 row the "target".
**
** If the SeekGE.P1 cursor is not currently pointing to a valid row,
** then this opcode is a no-op and control passes through into the OP_SeekGE.
**
** If the SeekGE.P1 cursor is pointing to a valid row, then that row
** might be the target row, or it might be near and slightly before the
** target row, or it might be after the target row. If the cursor is
** currently before the target row, then this opcode attempts to position
** the cursor on or after the target row by invoking sqlite3BtreeStep()
** on the cursor between 1 and This.P1 times.
**
** The This.P5 parameter is a flag that indicates what to do if the
** cursor ends up pointing at a valid row that is past the target
** row. If This.P5 is false (0) then a jump is made to SeekGE.P2. If
** This.P5 is true (non-zero) then a jump is made to This.P2. The P5==0
** case occurs when there are no inequality constraints to the right of
** the IN constraint. The jump to SeekGE.P2 ends the loop. The P5!=0 case
** occurs when there are inequality constraints to the right of the IN
** operator. In that case, the This.P2 will point either directly to or
** to setup code prior to the OP_IdxGT or OP_IdxGE opcode that checks for
** loop terminate.
**
** Possible outcomes from this opcode:<ol>
**
** <li> If the cursor is initially not pointed to any valid row, then
** fall through into the subsequent OP_SeekGE opcode.
**
** <li> If the cursor is left pointing to a row that is before the target
** row, even after making as many as This.P1 calls to
** sqlite3BtreeNext(), then also fall through into OP_SeekGE.
**
** <li> If the cursor is left pointing at the target row, either because it
** was at the target row to begin with or because one or more
** sqlite3BtreeNext() calls moved the cursor to the target row,
** then jump to This.P2..,
**
** <li> If the cursor started out before the target row and a call to
** to sqlite3BtreeNext() moved the cursor off the end of the index
** (indicating that the target row definitely does not exist in the
** btree) then jump to SeekGE.P2, ending the loop.
**
** <li> If the cursor ends up on a valid row that is past the target row
** (indicating that the target row does not exist in the btree) then
** jump to SeekOP.P2 if This.P5==0 or to This.P2 if This.P5>0.
** </ol>
*/
case OP_SeekScan: { /* ncycle */
VdbeCursor *pC;
int res;
int nStep;
UnpackedRecord r;
assert( pOp[1].opcode==OP_SeekGE );
/* If pOp->p5 is clear, then pOp->p2 points to the first instruction past the
** OP_IdxGT that follows the OP_SeekGE. Otherwise, it points to the first
** opcode past the OP_SeekGE itself. */
assert( pOp->p2>=(int)(pOp-aOp)+2 );
#ifdef SQLITE_DEBUG
if( pOp->p5==0 ){
/* There are no inequality constraints following the IN constraint. */
assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
assert( aOp[pOp->p2-1].opcode==OP_IdxGT
|| aOp[pOp->p2-1].opcode==OP_IdxGE );
testcase( aOp[pOp->p2-1].opcode==OP_IdxGE );
}else{
/* There are inequality constraints. */
assert( pOp->p2==(int)(pOp-aOp)+2 );
assert( aOp[pOp->p2-1].opcode==OP_SeekGE );
}
#endif
assert( pOp->p1>0 );
pC = p->apCsr[pOp[1].p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( !pC->isTable );
if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("... cursor not valid - fall through\n");
}
#endif
break;
}
nStep = pOp->p1;
assert( nStep>=1 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp[1].p4.i;
r.default_rc = 0;
r.aMem = &aMem[pOp[1].p3];
#ifdef SQLITE_DEBUG
{
int i;
for(i=0; i<r.nField; i++){
assert( memIsValid(&r.aMem[i]) );
REGISTER_TRACE(pOp[1].p3+i, &aMem[pOp[1].p3+i]);
}
}
#endif
res = 0; /* Not needed. Only used to silence a warning. */
while(1){
rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
if( rc ) goto abort_due_to_error;
if( res>0 && pOp->p5==0 ){
seekscan_search_fail:
/* Jump to SeekGE.P2, ending the loop */
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("... %d steps and then skip\n", pOp->p1 - nStep);
}
#endif
VdbeBranchTaken(1,3);
pOp++;
goto jump_to_p2;
}
if( res>=0 ){
/* Jump to This.P2, bypassing the OP_SeekGE opcode */
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("... %d steps and then success\n", pOp->p1 - nStep);
}
#endif
VdbeBranchTaken(2,3);
goto jump_to_p2;
break;
}
if( nStep<=0 ){
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("... fall through after %d steps\n", pOp->p1);
}
#endif
VdbeBranchTaken(0,3);
break;
}
nStep--;
pC->cacheStatus = CACHE_STALE;
rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
if( rc ){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
goto seekscan_search_fail;
}else{
goto abort_due_to_error;
}
}
}
break;
}
/* Opcode: SeekHit P1 P2 P3 * *
** Synopsis: set P2<=seekHit<=P3
**
** Increase or decrease the seekHit value for cursor P1, if necessary,
** so that it is no less than P2 and no greater than P3.
**
** The seekHit integer represents the maximum of terms in an index for which
** there is known to be at least one match. If the seekHit value is smaller
** than the total number of equality terms in an index lookup, then the
** OP_IfNoHope opcode might run to see if the IN loop can be abandoned
** early, thus saving work. This is part of the IN-early-out optimization.
**
** P1 must be a valid b-tree cursor.
*/
case OP_SeekHit: { /* ncycle */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pOp->p3>=pOp->p2 );
if( pC->seekHit<pOp->p2 ){
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p2);
}
#endif
pC->seekHit = pOp->p2;
}else if( pC->seekHit>pOp->p3 ){
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p3);
}
#endif
pC->seekHit = pOp->p3;
}
break;
}
/* Opcode: IfNotOpen P1 P2 * * *
** Synopsis: if( !csr[P1] ) goto P2
**
** If cursor P1 is not open or if P1 is set to a NULL row using the
** OP_NullRow opcode, then jump to instruction P2. Otherwise, fall through.
*/
case OP_IfNotOpen: { /* jump */
VdbeCursor *pCur;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pCur = p->apCsr[pOp->p1];
VdbeBranchTaken(pCur==0 || pCur->nullRow, 2);
if( pCur==0 || pCur->nullRow ){
goto jump_to_p2_and_check_for_interrupt;
}
break;
}
/* Opcode: Found P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
** record.
**
** Cursor P1 is on an index btree. If the record identified by P3 and P4
** is a prefix of any entry in P1 then a jump is made to P2 and
** P1 is left pointing at the matching entry.
**
** This operation leaves the cursor in a state where it can be
** advanced in the forward direction. The Next instruction will work,
** but not the Prev instruction.
**
** See also: NotFound, NoConflict, NotExists. SeekGe
*/
/* Opcode: NotFound P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
** record.
**
** Cursor P1 is on an index btree. If the record identified by P3 and P4
** is not the prefix of any entry in P1 then a jump is made to P2. If P1
** does contain an entry whose prefix matches the P3/P4 record then control
** falls through to the next instruction and P1 is left pointing at the
** matching entry.
**
** This operation leaves the cursor in a state where it cannot be
** advanced in either direction. In other words, the Next and Prev
** opcodes do not work after this operation.
**
** See also: Found, NotExists, NoConflict, IfNoHope
*/
/* Opcode: IfNoHope P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** Register P3 is the first of P4 registers that form an unpacked
** record. Cursor P1 is an index btree. P2 is a jump destination.
** In other words, the operands to this opcode are the same as the
** operands to OP_NotFound and OP_IdxGT.
**
** This opcode is an optimization attempt only. If this opcode always
** falls through, the correct answer is still obtained, but extra work
** is performed.
**
** A value of N in the seekHit flag of cursor P1 means that there exists
** a key P3:N that will match some record in the index. We want to know
** if it is possible for a record P3:P4 to match some record in the
** index. If it is not possible, we can skip some work. So if seekHit
** is less than P4, attempt to find out if a match is possible by running
** OP_NotFound.
**
** This opcode is used in IN clause processing for a multi-column key.
** If an IN clause is attached to an element of the key other than the
** left-most element, and if there are no matches on the most recent
** seek over the whole key, then it might be that one of the key element
** to the left is prohibiting a match, and hence there is "no hope" of
** any match regardless of how many IN clause elements are checked.
** In such a case, we abandon the IN clause search early, using this
** opcode. The opcode name comes from the fact that the
** jump is taken if there is "no hope" of achieving a match.
**
** See also: NotFound, SeekHit
*/
/* Opcode: NoConflict P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
** record.
**
** Cursor P1 is on an index btree. If the record identified by P3 and P4
** contains any NULL value, jump immediately to P2. If all terms of the
** record are not-NULL then a check is done to determine if any row in the
** P1 index btree has a matching key prefix. If there are no matches, jump
** immediately to P2. If there is a match, fall through and leave the P1
** cursor pointing to the matching row.
**
** This opcode is similar to OP_NotFound with the exceptions that the
** branch is always taken if any part of the search key input is NULL.
**
** This operation leaves the cursor in a state where it cannot be
** advanced in either direction. In other words, the Next and Prev
** opcodes do not work after this operation.
**
** See also: NotFound, Found, NotExists
*/
case OP_IfNoHope: { /* jump, in3, ncycle */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("seekHit is %d\n", pC->seekHit);
}
#endif
if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
case OP_NoConflict: /* jump, in3, ncycle */
case OP_NotFound: /* jump, in3, ncycle */
case OP_Found: { /* jump, in3, ncycle */
int alreadyExists;
int ii;
VdbeCursor *pC;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
#ifdef SQLITE_TEST
if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
#endif
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p4type==P4_INT32 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
r.aMem = &aMem[pOp->p3];
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( pC->isTable==0 );
r.nField = (u16)pOp->p4.i;
if( r.nField>0 ){
/* Key values in an array of registers */
r.pKeyInfo = pC->pKeyInfo;
r.default_rc = 0;
#ifdef SQLITE_DEBUG
(void)sqlite3FaultSim(50); /* For use by --counter in TH3 */
for(ii=0; ii<r.nField; ii++){
assert( memIsValid(&r.aMem[ii]) );
assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
}
#endif
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &pC->seekResult);
}else{
/* Composite key generated by OP_MakeRecord */
assert( r.aMem->flags & MEM_Blob );
assert( pOp->opcode!=OP_NoConflict );
rc = ExpandBlob(r.aMem);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
if( rc ) goto no_mem;
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
if( pIdxKey==0 ) goto no_mem;
sqlite3VdbeRecordUnpack(r.aMem->n, r.aMem->z, pIdxKey);
pIdxKey->default_rc = 0;
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
sqlite3DbFreeNN(db, pIdxKey);
}
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
alreadyExists = (pC->seekResult==0);
pC->nullRow = 1-alreadyExists;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
if( pOp->opcode==OP_Found ){
VdbeBranchTaken(alreadyExists!=0,2);
if( alreadyExists ) goto jump_to_p2;
}else{
if( !alreadyExists ){
VdbeBranchTaken(1,2);
goto jump_to_p2;
}
if( pOp->opcode==OP_NoConflict ){
/* For the OP_NoConflict opcode, take the jump if any of the
** input fields are NULL, since any key with a NULL will not
** conflict */
for(ii=0; ii<r.nField; ii++){
if( r.aMem[ii].flags & MEM_Null ){
VdbeBranchTaken(1,2);
goto jump_to_p2;
}
}
}
VdbeBranchTaken(0,2);
if( pOp->opcode==OP_IfNoHope ){
pC->seekHit = pOp->p4.i;
}
}
break;
}
/* Opcode: SeekRowid P1 P2 P3 * *
** Synopsis: intkey=r[P3]
**
** P1 is the index of a cursor open on an SQL table btree (with integer
** keys). If register P3 does not contain an integer or if P1 does not
** contain a record with rowid P3 then jump immediately to P2.
** Or, if P2 is 0, raise an SQLITE_CORRUPT error. If P1 does contain
** a record with rowid P3 then
** leave the cursor pointing at that record and fall through to the next
** instruction.
**
** The OP_NotExists opcode performs the same operation, but with OP_NotExists
** the P3 register must be guaranteed to contain an integer value. With this
** opcode, register P3 might not contain an integer.
**
** The OP_NotFound opcode performs the same operation on index btrees
** (with arbitrary multi-value keys).
**
** This opcode leaves the cursor in a state where it cannot be advanced
** in either direction. In other words, the Next and Prev opcodes will
** not work following this opcode.
**
** See also: Found, NotFound, NoConflict, SeekRowid
*/
/* Opcode: NotExists P1 P2 P3 * *
** Synopsis: intkey=r[P3]
**
** P1 is the index of a cursor open on an SQL table btree (with integer
** keys). P3 is an integer rowid. If P1 does not contain a record with
** rowid P3 then jump immediately to P2. Or, if P2 is 0, raise an
** SQLITE_CORRUPT error. If P1 does contain a record with rowid P3 then
** leave the cursor pointing at that record and fall through to the next
** instruction.
**
** The OP_SeekRowid opcode performs the same operation but also allows the
** P3 register to contain a non-integer value, in which case the jump is
** always taken. This opcode requires that P3 always contain an integer.
**
** The OP_NotFound opcode performs the same operation on index btrees
** (with arbitrary multi-value keys).
**
** This opcode leaves the cursor in a state where it cannot be advanced
** in either direction. In other words, the Next and Prev opcodes will
** not work following this opcode.
**
** See also: Found, NotFound, NoConflict, SeekRowid
*/
case OP_SeekRowid: { /* jump0, in3, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
u64 iKey;
pIn3 = &aMem[pOp->p3];
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_IntReal );
testcase( pIn3->flags & MEM_Real );
testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str );
if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
/* If pIn3->u.i does not contain an integer, compute iKey as the
** integer value of pIn3. Jump to P2 if pIn3 cannot be converted
** into an integer without loss of information. Take care to avoid
** changing the datatype of pIn3, however, as it is used by other
** parts of the prepared statement. */
Mem x = pIn3[0];
applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding);
if( (x.flags & MEM_Int)==0 ) goto jump_to_p2;
iKey = x.u.i;
goto notExistsWithKey;
}
/* Fall through into OP_NotExists */
/* no break */ deliberate_fall_through
case OP_NotExists: /* jump, in3, ncycle */
pIn3 = &aMem[pOp->p3];
assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
iKey = pIn3->u.i;
notExistsWithKey:
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid;
#endif
assert( pC->isTable );
assert( pC->eCurType==CURTYPE_BTREE );
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
res = 0;
rc = sqlite3BtreeTableMoveto(pCrsr, iKey, 0, &res);
assert( rc==SQLITE_OK || res==0 );
pC->movetoTarget = iKey; /* Used by OP_Delete */
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
pC->deferredMoveto = 0;
VdbeBranchTaken(res!=0,2);
pC->seekResult = res;
if( res!=0 ){
assert( rc==SQLITE_OK );
if( pOp->p2==0 ){
rc = SQLITE_CORRUPT_BKPT;
}else{
goto jump_to_p2;
}
}
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: Sequence P1 P2 * * *
** Synopsis: r[P2]=cursor[P1].ctr++
**
** Find the next available sequence number for cursor P1.
** Write the sequence number into register P2.
** The sequence number on the cursor is incremented after this
** instruction.
*/
case OP_Sequence: { /* out2 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( p->apCsr[pOp->p1]!=0 );
assert( p->apCsr[pOp->p1]->eCurType!=CURTYPE_VTAB );
pOut = out2Prerelease(p, pOp);
pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
break;
}
/* Opcode: NewRowid P1 P2 P3 * *
** Synopsis: r[P2]=rowid
**
** Get a new integer record number (a.k.a "rowid") used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to. The new record number is written
** written to register P2.
**
** If P3>0 then P3 is a register in the root frame of this VDBE that holds
** the largest previously generated record number. No new record numbers are
** allowed to be less than this value. When this value reaches its maximum,
** an SQLITE_FULL error is generated. The P3 register is updated with the '
** generated record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
case OP_NewRowid: { /* out2 */
i64 v; /* The new rowid */
VdbeCursor *pC; /* Cursor of table to get the new rowid */
int res; /* Result of an sqlite3BtreeLast() */
int cnt; /* Counter to limit the number of searches */
#ifndef SQLITE_OMIT_AUTOINCREMENT
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
VdbeFrame *pFrame; /* Root frame of VDBE */
#endif
v = 0;
res = 0;
pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->isTable );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
{
/* The next rowid or record number (different terms for the same
** thing) is obtained in a two-step algorithm.
**
** First we attempt to find the largest existing rowid and add one
** to that. But if the largest existing rowid is already the maximum
** positive integer, we have to fall through to the second
** probabilistic algorithm
**
** The second algorithm is to select a rowid at random and see if
** it already exists in the table. If it does not exist, we have
** succeeded. If the random rowid does exist, we select a new one
** and try again, up to 100 times.
*/
assert( pC->isTable );
#ifdef SQLITE_32BIT_ROWID
# define MAX_ROWID 0x7fffffff
#else
/* Some compilers complain about constants of the form 0x7fffffffffffffff.
** Others complain about 0x7ffffffffffffffffLL. The following macro seems
** to provide the constant while making all compilers happy.
*/
# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
#endif
if( !pC->useRandomRowid ){
rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( res ){
/* Assert that P3 is a valid memory cell. */
assert( pOp->p3>0 );
if( p->pFrame ){
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
/* Assert that P3 is a valid memory cell. */
assert( pOp->p3<=pFrame->nMem );
pMem = &pFrame->aMem[pOp->p3];
}else{
/* Assert that P3 is a valid memory cell. */
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
pMem = &aMem[pOp->p3];
memAboutToChange(p, pMem);
}
assert( memIsValid(pMem) );
REGISTER_TRACE(pOp->p3, pMem);
sqlite3VdbeMemIntegerify(pMem);
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
rc = SQLITE_FULL; /* IMP: R-17817-00630 */
goto abort_due_to_error;
}
if( v<pMem->u.i+1 ){
v = pMem->u.i + 1;
}
pMem->u.i = v;
}
#endif
if( pC->useRandomRowid ){
/* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
** largest possible integer (9223372036854775807) then the database
** engine starts picking positive candidate ROWIDs at random until
** it finds one that is not previously used. */
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
** an AUTOINCREMENT table. */
cnt = 0;
do{
sqlite3_randomness(sizeof(v), &v);
v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
}while( ((rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)v,
0, &res))==SQLITE_OK)
&& (res==0)
&& (++cnt<100));
if( rc ) goto abort_due_to_error;
if( res==0 ){
rc = SQLITE_FULL; /* IMP: R-38219-53002 */
goto abort_due_to_error;
}
assert( v>0 ); /* EV: R-40812-03570 */
}
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
pOut->u.i = v;
break;
}
/* Opcode: Insert P1 P2 P3 P4 P5
** Synopsis: intkey=r[P3] data=r[P2]
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten. The data is the value MEM_Blob stored in register
** number P2. The key is stored in register P3. The key must
** be a MEM_Int.
**
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set,
** then rowid is stored for subsequent return by the
** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
**
** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
** run faster by avoiding an unnecessary seek on cursor P1. However,
** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
** seeks on the cursor or if the most recent seek used a key equal to P3.
**
** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
** UPDATE operation. Otherwise (if the flag is clear) then this opcode
** is part of an INSERT operation. The difference is only important to
** the update hook.
**
** Parameter P4 may point to a Table structure, or may be NULL. If it is
** not NULL, then the update-hook (sqlite3.xUpdateCallback) is invoked
** following a successful insert.
**
** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically
** allocated, then ownership of P2 is transferred to the pseudo-cursor
** and register P2 becomes ephemeral. If the cursor is changed, the
** value of register P2 will then change. Make sure this does not
** cause any problems.)
**
** This instruction only works on tables. The equivalent instruction
** for indices is OP_IdxInsert.
*/
case OP_Insert: {
Mem *pData; /* MEM cell holding data for the record to be inserted */
Mem *pKey; /* MEM cell holding key for the record */
VdbeCursor *pC; /* Cursor to table into which insert is written */
int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
const char *zDb; /* database name - used by the update hook */
Table *pTab; /* Table structure - used by update and pre-update hooks */
BtreePayload x; /* Payload to be inserted */
pData = &aMem[pOp->p2];
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( memIsValid(pData) );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->deferredMoveto==0 );
assert( pC->uc.pCursor!=0 );
assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
REGISTER_TRACE(pOp->p2, pData);
sqlite3VdbeIncrWriteCounter(p, pC);
pKey = &aMem[pOp->p3];
assert( pKey->flags & MEM_Int );
assert( memIsValid(pKey) );
REGISTER_TRACE(pOp->p3, pKey);
x.nKey = pKey->u.i;
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
assert( pC->iDb>=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
}else{
pTab = 0;
zDb = 0;
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update hook, if any */
if( pTab ){
if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
sqlite3VdbePreUpdateHook(p,pC,SQLITE_INSERT,zDb,pTab,x.nKey,pOp->p2,-1);
}
if( db->xUpdateCallback==0 || pTab->aCol==0 ){
/* Prevent post-update hook from running in cases when it should not */
pTab = 0;
}
}
if( pOp->p5 & OPFLAG_ISNOOP ) break;
#endif
assert( (pOp->p5 & OPFLAG_LASTROWID)==0 || (pOp->p5 & OPFLAG_NCHANGE)!=0 );
if( pOp->p5 & OPFLAG_NCHANGE ){
p->nChange++;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
}
assert( (pData->flags & (MEM_Blob|MEM_Str))!=0 || pData->n==0 );
x.pData = pData->z;
x.nData = pData->n;
seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
if( pData->flags & MEM_Zero ){
x.nZero = pData->u.nZero;
}else{
x.nZero = 0;
}
x.pKey = 0;
assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT );
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
colCacheCtr++;
/* Invoke the update-hook if required. */
if( rc ) goto abort_due_to_error;
if( pTab ){
assert( db->xUpdateCallback!=0 );
assert( pTab->aCol!=0 );
db->xUpdateCallback(db->pUpdateArg,
(pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT,
zDb, pTab->zName, x.nKey);
}
break;
}
/* Opcode: RowCell P1 P2 P3 * *
**
** P1 and P2 are both open cursors. Both must be opened on the same type
** of table - intkey or index. This opcode is used as part of copying
** the current row from P2 into P1. If the cursors are opened on intkey
** tables, register P3 contains the rowid to use with the new record in
** P1. If they are opened on index tables, P3 is not used.
**
** This opcode must be followed by either an Insert or InsertIdx opcode
** with the OPFLAG_PREFORMAT flag set to complete the insert operation.
*/
case OP_RowCell: {
VdbeCursor *pDest; /* Cursor to write to */
VdbeCursor *pSrc; /* Cursor to read from */
i64 iKey; /* Rowid value to insert with */
assert( pOp[1].opcode==OP_Insert || pOp[1].opcode==OP_IdxInsert );
assert( pOp[1].opcode==OP_Insert || pOp->p3==0 );
assert( pOp[1].opcode==OP_IdxInsert || pOp->p3>0 );
assert( pOp[1].p5 & OPFLAG_PREFORMAT );
pDest = p->apCsr[pOp->p1];
pSrc = p->apCsr[pOp->p2];
iKey = pOp->p3 ? aMem[pOp->p3].u.i : 0;
rc = sqlite3BtreeTransferRow(pDest->uc.pCursor, pSrc->uc.pCursor, iKey);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
break;
};
/* Opcode: Delete P1 P2 P3 P4 P5
**
** Delete the record at which the P1 cursor is currently pointing.
**
** If the OPFLAG_SAVEPOSITION bit of the P5 parameter is set, then
** the cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op. As a result, in this case
** it is ok to delete a record from within a Next loop. If
** OPFLAG_SAVEPOSITION bit of P5 is clear, then the cursor will be
** left in an undefined state.
**
** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this
** delete is one of several associated with deleting a table row and
** all its associated index entries. Exactly one of those deletes is
** the "primary" delete. The others are all on OPFLAG_FORDELETE
** cursors or else are marked with the AUXDELETE flag.
**
** If the OPFLAG_NCHANGE (0x01) flag of P2 (NB: P2 not P5) is set, then
** the row change count is incremented (otherwise not).
**
** If the OPFLAG_ISNOOP (0x40) flag of P2 (not P5!) is set, then the
** pre-update-hook for deletes is run, but the btree is otherwise unchanged.
** This happens when the OP_Delete is to be shortly followed by an OP_Insert
** with the same key, causing the btree entry to be overwritten.
**
** P1 must not be pseudo-table. It has to be a real table with
** multiple rows.
**
** If P4 is not NULL then it points to a Table object. In this case either
** the update or pre-update hook, or both, may be invoked. The P1 cursor must
** have been positioned using OP_NotFound prior to invoking this opcode in
** this case. Specifically, if one is configured, the pre-update hook is
** invoked if P4 is not NULL. The update-hook is invoked if one is configured,
** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2.
**
** If the OPFLAG_ISUPDATE flag is set in P2, then P3 contains the address
** of the memory cell that contains the value that the rowid of the row will
** be set to by the update.
*/
case OP_Delete: {
VdbeCursor *pC;
const char *zDb;
Table *pTab;
int opflags;
opflags = pOp->p2;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( pC->deferredMoveto==0 );
sqlite3VdbeIncrWriteCounter(p, pC);
#ifdef SQLITE_DEBUG
if( pOp->p4type==P4_TABLE
&& HasRowid(pOp->p4.pTab)
&& pOp->p5==0
&& sqlite3BtreeCursorIsValidNN(pC->uc.pCursor)
){
/* If p5 is zero, the seek operation that positioned the cursor prior to
** OP_Delete will have also set the pC->movetoTarget field to the rowid of
** the row that is being deleted */
i64 iKey = sqlite3BtreeIntegerKey(pC->uc.pCursor);
assert( CORRUPT_DB || pC->movetoTarget==iKey );
}
#endif
/* If the update-hook or pre-update-hook will be invoked, set zDb to
** the name of the db to pass as to it. Also set local pTab to a copy
** of p4.pTab. Finally, if p5 is true, indicating that this cursor was
** last moved with OP_Next or OP_Prev, not Seek or NotFound, set
** VdbeCursor.movetoTarget to the current rowid. */
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
assert( pC->iDb>=0 );
assert( pOp->p4.pTab!=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){
pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor);
}
}else{
zDb = 0;
pTab = 0;
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update-hook if required. */
assert( db->xPreUpdateCallback==0 || pTab==pOp->p4.pTab );
if( db->xPreUpdateCallback && pTab ){
assert( !(opflags & OPFLAG_ISUPDATE)
|| HasRowid(pTab)==0
|| (aMem[pOp->p3].flags & MEM_Int)
);
sqlite3VdbePreUpdateHook(p, pC,
(opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
zDb, pTab, pC->movetoTarget,
pOp->p3, -1
);
}
if( opflags & OPFLAG_ISNOOP ) break;
#endif
/* Only flags that can be set are SAVEPOISTION and AUXDELETE */
assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 );
assert( OPFLAG_SAVEPOSITION==BTREE_SAVEPOSITION );
assert( OPFLAG_AUXDELETE==BTREE_AUXDELETE );
#ifdef SQLITE_DEBUG
if( p->pFrame==0 ){
if( pC->isEphemeral==0
&& (pOp->p5 & OPFLAG_AUXDELETE)==0
&& (pC->wrFlag & OPFLAG_FORDELETE)==0
){
nExtraDelete++;
}
if( pOp->p2 & OPFLAG_NCHANGE ){
nExtraDelete--;
}
}
#endif
rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5);
pC->cacheStatus = CACHE_STALE;
colCacheCtr++;
pC->seekResult = 0;
if( rc ) goto abort_due_to_error;
/* Invoke the update-hook if required. */
if( opflags & OPFLAG_NCHANGE ){
p->nChange++;
if( db->xUpdateCallback && ALWAYS(pTab!=0) && HasRowid(pTab) ){
db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,
pC->movetoTarget);
assert( pC->iDb>=0 );
}
}
break;
}
/* Opcode: ResetCount * * * * *
**
** The value of the change counter is copied to the database handle
** change counter (returned by subsequent calls to sqlite3_changes()).
** Then the VMs internal change counter resets to 0.
** This is used by trigger programs.
*/
case OP_ResetCount: {
sqlite3VdbeSetChanges(db, p->nChange);
p->nChange = 0;
break;
}
/* Opcode: SorterCompare P1 P2 P3 P4
** Synopsis: if key(P1)!=trim(r[P3],P4) goto P2
**
** P1 is a sorter cursor. This instruction compares a prefix of the
** record blob in register P3 against a prefix of the entry that
** the sorter cursor currently points to. Only the first P4 fields
** of r[P3] and the sorter record are compared.
**
** If either P3 or the sorter contains a NULL in one of their significant
** fields (not counting the P4 fields at the end which are ignored) then
** the comparison is assumed to be equal.
**
** Fall through to next instruction if the two records compare equal to
** each other. Jump to P2 if they are different.
*/
case OP_SorterCompare: {
VdbeCursor *pC;
int res;
int nKeyCol;
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
assert( pOp->p4type==P4_INT32 );
pIn3 = &aMem[pOp->p3];
nKeyCol = pOp->p4.i;
res = 0;
rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res);
VdbeBranchTaken(res!=0,2);
if( rc ) goto abort_due_to_error;
if( res ) goto jump_to_p2;
break;
};
/* Opcode: SorterData P1 P2 P3 * *
** Synopsis: r[P2]=data
**
** Write into register P2 the current sorter data for sorter cursor P1.
** Then clear the column header cache on cursor P3.
**
** This opcode is normally used to move a record out of the sorter and into
** a register that is the source for a pseudo-table cursor created using
** OpenPseudo. That pseudo-table cursor is the one that is identified by
** parameter P3. Clearing the P3 column cache as part of this opcode saves
** us from having to issue a separate NullRow instruction to clear that cache.
*/
case OP_SorterData: { /* ncycle */
VdbeCursor *pC;
pOut = &aMem[pOp->p2];
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
rc = sqlite3VdbeSorterRowkey(pC, pOut);
assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
if( rc ) goto abort_due_to_error;
p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE;
break;
}
/* Opcode: RowData P1 P2 P3 * *
** Synopsis: r[P2]=data
**
** Write into register P2 the complete row content for the row at
** which cursor P1 is currently pointing.
** There is no interpretation of the data.
** It is just copied onto the P2 register exactly as
** it is found in the database file.
**
** If cursor P1 is an index, then the content is the key of the row.
** If cursor P2 is a table, then the content extracted is the data.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
**
** If P3!=0 then this opcode is allowed to make an ephemeral pointer
** into the database page. That means that the content of the output
** register will be invalidated as soon as the cursor moves - including
** moves caused by other cursors that "save" the current cursors
** position in order that they can write to the same table. If P3==0
** then a copy of the data is made into memory. P3!=0 is faster, but
** P3==0 is safer.
**
** If P3!=0 then the content of the P2 register is unsuitable for use
** in OP_Result and any OP_Result will invalidate the P2 register content.
** The P2 register content is invalidated by opcodes like OP_Function or
** by any use of another cursor pointing to the same table.
*/
case OP_RowData: {
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( isSorter(pC)==0 );
assert( pC->nullRow==0 );
assert( pC->uc.pCursor!=0 );
pCrsr = pC->uc.pCursor;
/* The OP_RowData opcodes always follow OP_NotExists or
** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
** that might invalidate the cursor.
** If this were not the case, one of the following assert()s
** would fail. Should this ever change (because of changes in the code
** generator) then the fix would be to insert a call to
** sqlite3VdbeCursorMoveto().
*/
assert( pC->deferredMoveto==0 );
assert( sqlite3BtreeCursorIsValid(pCrsr) );
n = sqlite3BtreePayloadSize(pCrsr);
if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
testcase( n==0 );
rc = sqlite3VdbeMemFromBtreeZeroOffset(pCrsr, n, pOut);
if( rc ) goto abort_due_to_error;
if( !pOp->p3 ) Deephemeralize(pOut);
UPDATE_MAX_BLOBSIZE(pOut);
REGISTER_TRACE(pOp->p2, pOut);
break;
}
/* Opcode: Rowid P1 P2 * * *
** Synopsis: r[P2]=PX rowid of P1
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
**
** P1 can be either an ordinary table or a virtual table. There used to
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
case OP_Rowid: { /* out2, ncycle */
VdbeCursor *pC;
i64 v;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
if( pC->nullRow ){
pOut->flags = MEM_Null;
break;
}else if( pC->deferredMoveto ){
v = pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
}else if( pC->eCurType==CURTYPE_VTAB ){
assert( pC->uc.pVCur!=0 );
pVtab = pC->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xRowid );
rc = pModule->xRowid(pC->uc.pVCur, &v);
sqlite3VtabImportErrmsg(p, pVtab);
if( rc ) goto abort_due_to_error;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
rc = sqlite3VdbeCursorRestore(pC);
if( rc ) goto abort_due_to_error;
if( pC->nullRow ){
pOut->flags = MEM_Null;
break;
}
v = sqlite3BtreeIntegerKey(pC->uc.pCursor);
}
pOut->u.i = v;
break;
}
/* Opcode: NullRow P1 * * * *
**
** Move the cursor P1 to a null row. Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
**
** If cursor P1 is not previously opened, open it now to a special
** pseudo-cursor that always returns NULL for every column.
*/
case OP_NullRow: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
if( pC==0 ){
/* If the cursor is not already open, create a special kind of
** pseudo-cursor that always gives null rows. */
pC = allocateCursor(p, pOp->p1, 1, CURTYPE_PSEUDO);
if( pC==0 ) goto no_mem;
pC->seekResult = 0;
pC->isTable = 1;
pC->noReuse = 1;
pC->uc.pCursor = sqlite3BtreeFakeValidCursor();
}
pC->nullRow = 1;
pC->cacheStatus = CACHE_STALE;
if( pC->eCurType==CURTYPE_BTREE ){
assert( pC->uc.pCursor!=0 );
sqlite3BtreeClearCursor(pC->uc.pCursor);
}
#ifdef SQLITE_DEBUG
if( pC->seekOp==0 ) pC->seekOp = OP_NullRow;
#endif
break;
}
/* Opcode: SeekEnd P1 * * * *
**
** Position cursor P1 at the end of the btree for the purpose of
** appending a new entry onto the btree.
**
** It is assumed that the cursor is used only for appending and so
** if the cursor is valid, then the cursor must already be pointing
** at the end of the btree and so no changes are made to
** the cursor.
*/
/* Opcode: Last P1 P2 * * *
**
** The next use of the Rowid or Column or Prev instruction for P1
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
**
** This opcode leaves the cursor configured to move in reverse order,
** from the end toward the beginning. In other words, the cursor is
** configured to use Prev, not Next.
*/
case OP_SeekEnd: /* ncycle */
case OP_Last: { /* jump0, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
pCrsr = pC->uc.pCursor;
res = 0;
assert( pCrsr!=0 );
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
if( pOp->opcode==OP_SeekEnd ){
assert( pOp->p2==0 );
pC->seekResult = -1;
if( sqlite3BtreeCursorIsValidNN(pCrsr) ){
break;
}
}
rc = sqlite3BtreeLast(pCrsr, &res);
pC->nullRow = (u8)res;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
if( rc ) goto abort_due_to_error;
if( pOp->p2>0 ){
VdbeBranchTaken(res!=0,2);
if( res ) goto jump_to_p2;
}
break;
}
/* Opcode: IfSizeBetween P1 P2 P3 P4 *
**
** Let N be the approximate number of rows in the table or index
** with cursor P1 and let X be 10*log2(N) if N is positive or -1
** if N is zero.
**
** Jump to P2 if X is in between P3 and P4, inclusive.
*/
case OP_IfSizeBetween: { /* jump */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
i64 sz;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p4type==P4_INT32 );
assert( pOp->p3>=-1 && pOp->p3<=640*2 );
assert( pOp->p4.i>=-1 && pOp->p4.i<=640*2 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pCrsr = pC->uc.pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
if( rc ) goto abort_due_to_error;
if( res!=0 ){
sz = -1; /* -Infinity encoding */
}else{
sz = sqlite3BtreeRowCountEst(pCrsr);
assert( sz>0 );
sz = sqlite3LogEst((u64)sz);
}
res = sz>=pOp->p3 && sz<=pOp->p4.i;
VdbeBranchTaken(res!=0,2);
if( res ) goto jump_to_p2;
break;
}
/* Opcode: SorterSort P1 P2 * * *
**
** After all records have been inserted into the Sorter object
** identified by P1, invoke this opcode to actually do the sorting.
** Jump to P2 if there are no records to be sorted.
**
** This opcode is an alias for OP_Sort and OP_Rewind that is used
** for Sorter objects.
*/
/* Opcode: Sort P1 P2 * * *
**
** This opcode does exactly the same thing as OP_Rewind except that
** it increments an undocumented global variable used for testing.
**
** Sorting is accomplished by writing records into a sorting index,
** then rewinding that index and playing it back from beginning to
** end. We use the OP_Sort opcode instead of OP_Rewind to do the
** rewinding so that the global variable will be incremented and
** regression tests can determine whether or not the optimizer is
** correctly optimizing out sorts.
*/
case OP_SorterSort: /* jump ncycle */
case OP_Sort: { /* jump ncycle */
#ifdef SQLITE_TEST
sqlite3_sort_count++;
sqlite3_search_count--;
#endif
p->aCounter[SQLITE_STMTSTATUS_SORT]++;
/* Fall through into OP_Rewind */
/* no break */ deliberate_fall_through
}
/* Opcode: Rewind P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1
** will refer to the first entry in the database table or index.
** If the table or index is empty, jump immediately to P2.
** If the table or index is not empty, fall through to the following
** instruction.
**
** If P2 is zero, that is an assertion that the P1 table is never
** empty and hence the jump will never be taken.
**
** This opcode leaves the cursor configured to move in forward order,
** from the beginning toward the end. In other words, the cursor is
** configured to use Next, not Prev.
*/
case OP_Rewind: { /* jump0, ncycle */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5==0 );
assert( pOp->p2>=0 && pOp->p2<p->nOp );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
res = 1;
#ifdef SQLITE_DEBUG
pC->seekOp = OP_Rewind;
#endif
if( isSorter(pC) ){
rc = sqlite3VdbeSorterRewind(pC, &res);
}else{
assert( pC->eCurType==CURTYPE_BTREE );
pCrsr = pC->uc.pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
if( rc ) goto abort_due_to_error;
pC->nullRow = (u8)res;
if( pOp->p2>0 ){
VdbeBranchTaken(res!=0,2);
if( res ) goto jump_to_p2;
}
break;
}
/* Opcode: IfEmpty P1 P2 * * *
** Synopsis: if( empty(P1) ) goto P2
**
** Check to see if the b-tree table that cursor P1 references is empty
** and jump to P2 if it is.
*/
case OP_IfEmpty: { /* jump */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p2>=0 && pOp->p2<p->nOp );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
pCrsr = pC->uc.pCursor;
assert( pCrsr );
rc = sqlite3BtreeIsEmpty(pCrsr, &res);
if( rc ) goto abort_due_to_error;
VdbeBranchTaken(res!=0,2);
if( res ) goto jump_to_p2;
break;
}
/* Opcode: Next P1 P2 P3 * P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
** to the following instruction. But if the cursor advance was successful,
** jump immediately to P2.
**
** The Next opcode is only valid following an SeekGT, SeekGE, or
** OP_Rewind opcode used to position the cursor. Next is not allowed
** to follow SeekLT, SeekLE, or OP_Last.
**
** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
** been opened prior to this opcode or the program will segfault.
**
** The P3 value is a hint to the btree implementation. If P3==1, that
** means P1 is an SQL index and that this instruction could have been
** omitted if that index had been unique. P3 is usually 0. P3 is
** always either 0 or 1.
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
** See also: Prev
*/
/* Opcode: Prev P1 P2 P3 * P5
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index. If there is no previous key/value pairs then fall through
** to the following instruction. But if the cursor backup was successful,
** jump immediately to P2.
**
**
** The Prev opcode is only valid following an SeekLT, SeekLE, or
** OP_Last opcode used to position the cursor. Prev is not allowed
** to follow SeekGT, SeekGE, or OP_Rewind.
**
** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
** not open then the behavior is undefined.
**
** The P3 value is a hint to the btree implementation. If P3==1, that
** means P1 is an SQL index and that this instruction could have been
** omitted if that index had been unique. P3 is usually 0. P3 is
** always either 0 or 1.
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
/* Opcode: SorterNext P1 P2 * * P5
**
** This opcode works just like OP_Next except that P1 must be a
** sorter object for which the OP_SorterSort opcode has been
** invoked. This opcode advances the cursor to the next sorted
** record, or jumps to P2 if there are no more sorted records.
*/
case OP_SorterNext: { /* jump */
VdbeCursor *pC;
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
rc = sqlite3VdbeSorterNext(db, pC);
goto next_tail;
case OP_Prev: /* jump, ncycle */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5==0
|| pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
|| pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX);
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->deferredMoveto==0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|| pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope
|| pC->seekOp==OP_NullRow);
rc = sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3);
goto next_tail;
case OP_Next: /* jump, ncycle */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5==0
|| pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
|| pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX);
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->deferredMoveto==0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
|| pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid
|| pC->seekOp==OP_IfNoHope);
rc = sqlite3BtreeNext(pC->uc.pCursor, pOp->p3);
next_tail:
pC->cacheStatus = CACHE_STALE;
VdbeBranchTaken(rc==SQLITE_OK,2);
if( rc==SQLITE_OK ){
pC->nullRow = 0;
p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
goto jump_to_p2_and_check_for_interrupt;
}
if( rc!=SQLITE_DONE ) goto abort_due_to_error;
rc = SQLITE_OK;
pC->nullRow = 1;
goto check_for_interrupt;
}
/* Opcode: IdxInsert P1 P2 P3 P4 P5
** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions. This opcode writes that key
** into the index P1. Data for the entry is nil.
**
** If P4 is not zero, then it is the number of values in the unpacked
** key of reg(P2). In that case, P3 is the index of the first register
** for the unpacked key. The availability of the unpacked key can sometimes
** be an optimization.
**
** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer
** that this insert is likely to be an append.
**
** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear,
** then the change counter is unchanged.
**
** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
** run faster by avoiding an unnecessary seek on cursor P1. However,
** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
** seeks on the cursor or if the most recent seek used a key equivalent
** to P2.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
case OP_IdxInsert: { /* in2 */
VdbeCursor *pC;
BtreePayload x;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
sqlite3VdbeIncrWriteCounter(p, pC);
assert( pC!=0 );
assert( !isSorter(pC) );
pIn2 = &aMem[pOp->p2];
assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) );
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->isTable==0 );
rc = ExpandBlob(pIn2);
if( rc ) goto abort_due_to_error;
x.nKey = pIn2->n;
x.pKey = pIn2->z;
x.aMem = aMem + pOp->p3;
x.nMem = (u16)pOp->p4.i;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
if( rc) goto abort_due_to_error;
break;
}
/* Opcode: SorterInsert P1 P2 * * *
** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions. This opcode writes that key
** into the sorter P1. Data for the entry is nil.
*/
case OP_SorterInsert: { /* in2 */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
sqlite3VdbeIncrWriteCounter(p, pC);
assert( pC!=0 );
assert( isSorter(pC) );
pIn2 = &aMem[pOp->p2];
assert( pIn2->flags & MEM_Blob );
assert( pC->isTable==0 );
rc = ExpandBlob(pIn2);
if( rc ) goto abort_due_to_error;
rc = sqlite3VdbeSorterWrite(pC, pIn2);
if( rc) goto abort_due_to_error;
break;
}
/* Opcode: IdxDelete P1 P2 P3 * P5
** Synopsis: key=r[P2@P3]
**
** The content of P3 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the
** index opened by cursor P1.
**
** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error
** if no matching index entry is found. This happens when running
** an UPDATE or DELETE statement and the index entry to be updated
** or deleted is not found. For some uses of IdxDelete
** (example: the EXCEPT operator) it does not matter that no matching
** entry is found. For those cases, P5 is zero. Also, do not raise
** this (self-correcting and non-critical) error if in writable_schema mode.
*/
case OP_IdxDelete: {
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
UnpackedRecord r;
assert( pOp->p3>0 );
assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
sqlite3VdbeIncrWriteCounter(p, pC);
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p3;
r.default_rc = 0;
r.aMem = &aMem[pOp->p2];
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
if( rc ) goto abort_due_to_error;
if( res==0 ){
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
if( rc ) goto abort_due_to_error;
}else if( pOp->p5 && !sqlite3WritableSchema(db) ){
rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
goto abort_due_to_error;
}
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
pC->seekResult = 0;
break;
}
/* Opcode: DeferredSeek P1 * P3 P4 *
** Synopsis: Move P3 to P1.rowid if needed
**
** P1 is an open index cursor and P3 is a cursor on the corresponding
** table. This opcode does a deferred seek of the P3 table cursor
** to the row that corresponds to the current row of P1.
**
** This is a deferred seek. Nothing actually happens until
** the cursor is used to read a record. That way, if no reads
** occur, no unnecessary I/O happens.
**
** P4 may be an array of integers (type P4_INTARRAY) containing
** one entry for each column in the P3 table. If array entry a(i)
** is non-zero, then reading column a(i)-1 from cursor P3 is
** equivalent to performing the deferred seek and then reading column i
** from P1. This information is stored in P3 and used to redirect
** reads against P3 over to P1, thus possibly avoiding the need to
** seek and read cursor P3.
*/
/* Opcode: IdxRowid P1 P2 * * *
** Synopsis: r[P2]=rowid
**
** Write into register P2 an integer which is the last entry in the record at
** the end of the index key pointed to by cursor P1. This integer should be
** the rowid of the table entry to which this index entry points.
**
** See also: Rowid, MakeRecord.
*/
case OP_DeferredSeek: /* ncycle */
case OP_IdxRowid: { /* out2, ncycle */
VdbeCursor *pC; /* The P1 index cursor */
VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */
i64 rowid; /* Rowid that P1 current points to */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE || IsNullCursor(pC) );
assert( pC->uc.pCursor!=0 );
assert( pC->isTable==0 || IsNullCursor(pC) );
assert( pC->deferredMoveto==0 );
assert( !pC->nullRow || pOp->opcode==OP_IdxRowid );
/* The IdxRowid and Seek opcodes are combined because of the commonality
** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */
rc = sqlite3VdbeCursorRestore(pC);
/* sqlite3VdbeCursorRestore() may fail if the cursor has been disturbed
** since it was last positioned and an error (e.g. OOM or an IO error)
** occurs while trying to reposition it. */
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( !pC->nullRow ){
rowid = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3VdbeIdxRowid(db, pC->uc.pCursor, &rowid);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( pOp->opcode==OP_DeferredSeek ){
assert( pOp->p3>=0 && pOp->p3<p->nCursor );
pTabCur = p->apCsr[pOp->p3];
assert( pTabCur!=0 );
assert( pTabCur->eCurType==CURTYPE_BTREE );
assert( pTabCur->uc.pCursor!=0 );
assert( pTabCur->isTable );
pTabCur->nullRow = 0;
pTabCur->movetoTarget = rowid;
pTabCur->deferredMoveto = 1;
pTabCur->cacheStatus = CACHE_STALE;
assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
assert( !pTabCur->isEphemeral );
pTabCur->ub.aAltMap = pOp->p4.ai;
assert( !pC->isEphemeral );
pTabCur->pAltCursor = pC;
}else{
pOut = out2Prerelease(p, pOp);
pOut->u.i = rowid;
}
}else{
assert( pOp->opcode==OP_IdxRowid );
sqlite3VdbeMemSetNull(&aMem[pOp->p2]);
}
break;
}
/* Opcode: FinishSeek P1 * * * *
**
** If cursor P1 was previously moved via OP_DeferredSeek, complete that
** seek operation now, without further delay. If the cursor seek has
** already occurred, this instruction is a no-op.
*/
case OP_FinishSeek: { /* ncycle */
VdbeCursor *pC; /* The P1 index cursor */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
if( pC->deferredMoveto ){
rc = sqlite3VdbeFinishMoveto(pC);
if( rc ) goto abort_due_to_error;
}
break;
}
/* Opcode: IdxGE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
** key that omits the PRIMARY KEY. Compare this key value against the index
** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID
** fields at the end.
**
** 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.
*/
/* Opcode: IdxGT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
** key that omits the PRIMARY KEY. Compare this key value against the index
** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID
** fields at the end.
**
** If the P1 index entry is greater than the key value
** then jump to P2. Otherwise fall through to the next instruction.
*/
/* Opcode: IdxLT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
** key that omits the PRIMARY KEY or ROWID. Compare this key value against
** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
** ROWID on the P1 index.
**
** If the P1 index entry is less than the key value then jump to P2.
** Otherwise fall through to the next instruction.
*/
/* Opcode: IdxLE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
** key that omits the PRIMARY KEY or ROWID. Compare this key value against
** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
** ROWID on the P1 index.
**
** If the P1 index entry is less than or equal to the key value then jump
** to P2. Otherwise fall through to the next instruction.
*/
case OP_IdxLE: /* jump, ncycle */
case OP_IdxGT: /* jump, ncycle */
case OP_IdxLT: /* jump, ncycle */
case OP_IdxGE: { /* jump, ncycle */
VdbeCursor *pC;
int res;
#endif
/* Inlined version of sqlite3VdbeIdxKeyCompare() */
{
i64 nCellKey = 0;
BtCursor *pCur;
Mem m;
assert( pC->eCurType==CURTYPE_BTREE );
pCur = pC->uc.pCursor;
assert( sqlite3BtreeCursorIsValid(pCur) );
nCellKey = sqlite3BtreePayloadSize(pCur);
/* nCellKey will always be between 0 and 0xffffffff because of the way
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
if( nCellKey<=0 || nCellKey>0x7fffffff ){
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
sqlite3VdbeMemInit(&m, db, 0);
rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
if( rc ) goto abort_due_to_error;
res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0);
sqlite3VdbeMemReleaseMalloc(&m);
}
/* End of inlined sqlite3VdbeIdxKeyCompare() */
assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
if( (pOp->opcode&1)==(OP_IdxLT&1) ){
assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
res = -res;
}else{
assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT );
res++;
}
VdbeBranchTaken(res>0,2);
assert( rc==SQLITE_OK );
if( res>0 ) goto jump_to_p2;
break;
}
/* Opcode: Destroy P1 P2 P3 * *
**
** Delete an entire database table or index whose root page in the database
** file is given by P1.
**
** The table being destroyed is in the main database file if P3==0. If
** P3==1 then the table to be destroyed is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** If AUTOVACUUM is enabled then it is possible that another root page
** might be moved into the newly deleted root page in order to keep all
** root pages contiguous at the beginning of the database. The former
** value of the root page that moved - its value before the move occurred -
** is stored in register P2. If no page movement was required (because the
** table being dropped was already the last one in the database) then a
** zero is stored in register P2. If AUTOVACUUM is disabled then a zero
** is stored in register P2.
**
** This opcode throws an error if there are any active reader VMs when
** it is invoked. This is done to avoid the difficulty associated with
** updating existing cursors when a root page is moved in an AUTOVACUUM
** database. This error is thrown even if the database is not an AUTOVACUUM
** db in order to avoid introducing an incompatibility between autovacuum
** and non-autovacuum modes.
**
** See also: Clear
*/
case OP_Destroy: { /* out2 */
int iMoved;
int iDb;
sqlite3VdbeIncrWriteCounter(p, 0);
assert( p->readOnly==0 );
assert( pOp->p1>1 );
pOut = out2Prerelease(p, pOp);
pOut->flags = MEM_Null;
if( db->nVdbeRead > db->nVDestroy+1 ){
rc = SQLITE_LOCKED;
p->errorAction = OE_Abort;
goto abort_due_to_error;
}else{
iDb = pOp->p3;
assert( DbMaskTest(p->btreeMask, iDb) );
iMoved = 0; /* Not needed. Only to silence a warning. */
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
pOut->flags = MEM_Int;
pOut->u.i = iMoved;
if( rc ) goto abort_due_to_error;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( iMoved!=0 ){
sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1);
/* All OP_Destroy operations occur on the same btree */
assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 );
resetSchemaOnFault = iDb+1;
}
#endif
}
break;
}
/* Opcode: Clear P1 P2 P3
**
** Delete all contents of the database table or index whose root page
** in the database file is given by P1. But, unlike Destroy, do not
** remove the table or index from the database file.
**
** The table being cleared is in the main database file if P2==0. If
** P2==1 then the table to be cleared is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** If the P3 value is non-zero, then the row change count is incremented
** by the number of rows in the table being cleared. If P3 is greater
** than zero, then the value stored in register P3 is also incremented
** by the number of rows in the table being cleared.
**
** See also: Destroy
*/
case OP_Clear: {
i64 nChange;
sqlite3VdbeIncrWriteCounter(p, 0);
nChange = 0;
assert( p->readOnly==0 );
assert( DbMaskTest(p->btreeMask, pOp->p2) );
rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange);
if( pOp->p3 ){
p->nChange += nChange;
if( pOp->p3>0 ){
assert( memIsValid(&aMem[pOp->p3]) );
memAboutToChange(p, &aMem[pOp->p3]);
aMem[pOp->p3].u.i += nChange;
}
}
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: ResetSorter P1 * * * *
**
** Delete all contents from the ephemeral table or sorter
** that is open on cursor P1.
**
** This opcode only works for cursors used for sorting and
** opened with OP_OpenEphemeral or OP_SorterOpen.
*/
case OP_ResetSorter: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
if( isSorter(pC) ){
sqlite3VdbeSorterReset(db, pC->uc.pSorter);
}else{
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->isEphemeral );
rc = sqlite3BtreeClearTableOfCursor(pC->uc.pCursor);
if( rc ) goto abort_due_to_error;
}
break;
}
/* Opcode: CreateBtree P1 P2 P3 * *
** Synopsis: r[P2]=root iDb=P1 flags=P3
**
** Allocate a new b-tree in the main database file if P1==0 or in the
** TEMP database file if P1==1 or in an attached database if
** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table
** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table.
** The root page number of the new b-tree is stored in register P2.
*/
case OP_CreateBtree: { /* out2 */
Pgno pgno;
Db *pDb;
sqlite3VdbeIncrWriteCounter(p, 0);
pOut = out2Prerelease(p, pOp);
pgno = 0;
assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( p->readOnly==0 );
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, pOp->p3);
if( rc ) goto abort_due_to_error;
pOut->u.i = pgno;
break;
}
/* Opcode: SqlExec P1 P2 * P4 *
**
** Run the SQL statement or statements specified in the P4 string.
**
** The P1 parameter is a bitmask of options:
**
** 0x0001 Disable Auth and Trace callbacks while the statements
** in P4 are running.
**
** 0x0002 Set db->nAnalysisLimit to P2 while the statements in
** P4 are running.
**
*/
**
** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
**
** P1 contains the address of the memory cell that contains the first memory
** cell in an array of values used as arguments to the sub-program. P2
** contains the address to jump to if the sub-program throws an IGNORE
** exception using the RAISE() function. P2 might be zero, if there is
** no possibility that an IGNORE exception will be raised.
** Register P3 contains the address
** of a memory cell in this (the parent) VM that is used to allocate the
** memory required by the sub-vdbe at runtime.
**
** P4 is a pointer to the VM containing the trigger program.
**
** If P5 is non-zero, then recursive program invocation is enabled.
*/
case OP_Program: { /* jump0 */
int nMem; /* Number of memory registers for sub-program */
i64 nByte; /* Bytes of runtime space required for sub-program */
Mem *pRt; /* Register to allocate runtime space */
Mem *pMem; /* Used to iterate through memory cells */
Mem *pEnd; /* Last memory cell in new array */
VdbeFrame *pFrame; /* New vdbe frame to execute in */
SubProgram *pProgram; /* Sub-program to execute */
void *t; /* Token identifying trigger */
pProgram = pOp->p4.pProgram;
pRt = &aMem[pOp->p3];
assert( pProgram->nOp>0 );
/* If the p5 flag is clear, then recursive invocation of triggers is
** disabled for backwards compatibility (p5 is set if this sub-program
** is really a trigger, not a foreign key action, and the flag set
** and cleared by the "PRAGMA recursive_triggers" command is clear).
**
** It is recursive invocation of triggers, at the SQL level, that is
** disabled. In some cases a single trigger may generate more than one
** SubProgram (if the trigger may be executed with more than one different
** ON CONFLICT algorithm). SubProgram structures associated with a
** single trigger all have the same value for the SubProgram.token
** variable. */
if( pOp->p5 ){
t = pProgram->token;
for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
if( pFrame ) break;
}
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
rc = SQLITE_ERROR;
sqlite3VdbeError(p, "too many levels of trigger recursion");
goto abort_due_to_error;
}
/* Register pRt is used to store the memory required to save the state
** of the current program, and the memory required at runtime to execute
** the trigger program. If this trigger has been fired before, then pRt
** is already allocated. Otherwise, it must be initialized. */
if( (pRt->flags&MEM_Blob)==0 ){
/* SubProgram.nMem is set to the number of memory cells used by the
** program stored in SubProgram.aOp. As well as these, one memory
** cell is required for each cursor used by the program. Set local
** variable nMem (and later, VdbeFrame.nChildMem) to this value.
*/
nMem = pProgram->nMem + pProgram->nCsr;
assert( nMem>0 );
if( pProgram->nCsr==0 ) nMem++;
nByte = ROUND8(sizeof(VdbeFrame))
+ nMem * sizeof(Mem)
+ pProgram->nCsr * sizeof(VdbeCursor*)
+ (7 + (i64)pProgram->nOp)/8;
pFrame = sqlite3DbMallocZero(db, nByte);
if( !pFrame ){
goto no_mem;
}
sqlite3VdbeMemRelease(pRt);
pRt->flags = MEM_Blob|MEM_Dyn;
pRt->z = (char*)pFrame;
pRt->n = (int)nByte;
pRt->xDel = sqlite3VdbeFrameMemDel;
pFrame->v = p;
pFrame->nChildMem = nMem;
pFrame->nChildCsr = pProgram->nCsr;
pFrame->pc = (int)(pOp - aOp);
pFrame->aMem = p->aMem;
pFrame->nMem = p->nMem;
pFrame->apCsr = p->apCsr;
pFrame->nCursor = p->nCursor;
pFrame->aOp = p->aOp;
pFrame->nOp = p->nOp;
pFrame->token = pProgram->token;
#ifdef SQLITE_DEBUG
pFrame->iFrameMagic = SQLITE_FRAME_MAGIC;
#endif
pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
pMem->flags = MEM_Undefined;
pMem->db = db;
}
}else{
pFrame = (VdbeFrame*)pRt->z;
assert( pRt->xDel==sqlite3VdbeFrameMemDel );
assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem
|| (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) );
assert( pProgram->nCsr==pFrame->nChildCsr );
assert( (int)(pOp - aOp)==pFrame->pc );
}
p->nFrame++;
pFrame->pParent = p->pFrame;
pFrame->lastRowid = db->lastRowid;
pFrame->nChange = p->nChange;
pFrame->nDbChange = p->db->nChange;
assert( pFrame->pAuxData==0 );
pFrame->pAuxData = p->pAuxData;
p->pAuxData = 0;
p->nChange = 0;
p->pFrame = pFrame;
p->aMem = aMem = VdbeFrameMem(pFrame);
p->nMem = pFrame->nChildMem;
rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1,
pOp->p2 ? &aMem[pOp->p2] : 0);
if( rc ) goto abort_due_to_error;
break;
}
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
/* Opcode: IncrVacuum P1 P2 * * *
**
** Perform a single step of the incremental vacuum procedure on
** the P1 database. If the vacuum has finished, jump to instruction
** P2. Otherwise, fall through to the next instruction.
*/
case OP_IncrVacuum: { /* jump */
Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( p->readOnly==0 );
pBt = db->aDb[pOp->p1].pBt;
rc = sqlite3BtreeIncrVacuum(pBt);
VdbeBranchTaken(rc==SQLITE_DONE,2);
if( rc ){
if( rc!=SQLITE_DONE ) goto abort_due_to_error;
rc = SQLITE_OK;
goto jump_to_p2;
}
break;
}
#endif
/* Opcode: Expire P1 P2 * * *
**
** Cause precompiled statements to expire. When an expired statement
** is executed using sqlite3_step() it will either automatically
** reprepare itself (if it was originally created using sqlite3_prepare_v2())
** or it will fail with SQLITE_SCHEMA.
**
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
** then only the currently executing statement is expired.
**
** If P2 is 0, then SQL statements are expired immediately. If P2 is 1,
** then running SQL statements are allowed to continue to run to completion.
** The P2==1 case occurs when a CREATE INDEX or similar schema change happens
** that might help the statement run faster but which does not affect the
** correctness of operation.
*/
case OP_Expire: {
assert( pOp->p2==0 || pOp->p2==1 );
if( !pOp->p1 ){
sqlite3ExpirePreparedStatements(db, pOp->p2);
}else{
p->expired = pOp->p2+1;
}
break;
}
/* Opcode: CursorLock P1 * * * *
**
** Lock the btree to which cursor P1 is pointing so that the btree cannot be
** written by an other cursor.
*/
case OP_CursorLock: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
sqlite3BtreeCursorPin(pC->uc.pCursor);
break;
}
/* Opcode: CursorUnlock P1 * * * *
**
** Unlock the btree to which cursor P1 is pointing so that it can be
** written by other cursors.
*/
case OP_CursorUnlock: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
sqlite3BtreeCursorUnpin(pC->uc.pCursor);
break;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
/* Opcode: TableLock P1 P2 P3 P4 *
** Synopsis: iDb=P1 root=P2 write=P3
**
** Obtain a lock on a particular table. This instruction is only used when
** the shared-cache feature is enabled.
**
** 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.
**
** P4 contains a pointer to the name of the table being locked. This is only
** used to generate an error message if the lock cannot be obtained.
*/
case OP_TableLock: {
u8 isWriteLock = (u8)pOp->p3;
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){
int p1 = pOp->p1;
assert( p1>=0 && p1<db->nDb );
assert( DbMaskTest(p->btreeMask, p1) );
assert( isWriteLock==0 || isWriteLock==1 );
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
if( rc ){
if( (rc&0xFF)==SQLITE_LOCKED ){
const char *z = pOp->p4.z;
sqlite3VdbeError(p, "database table is locked: %s", z);
}
goto abort_due_to_error;
}
}
break;
}
#endif /* SQLITE_OMIT_SHARED_CACHE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VBegin * * * P4 *
**
** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
** xBegin method for that table.
**
** Also, whether or not P4 is set, check that this is not being called from
** within a callback to a virtual table xSync() method. If it is, the error
** code will be set to SQLITE_LOCKED.
*/
case OP_VBegin: {
VTable *pVTab;
pVTab = pOp->p4.pVtab;
rc = sqlite3VtabBegin(db, pVTab);
if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab);
if( rc ) goto abort_due_to_error;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCreate P1 P2 * * *
**
** P2 is a register that holds the name of a virtual table in database
** P1. Call the xCreate method for that table.
*/
case OP_VCreate: {
Mem sMem; /* For storing the record being decoded */
const char *zTab; /* Name of the virtual table */
memset(&sMem, 0, sizeof(sMem));
sMem.db = db;
/* Because P2 is always a static string, it is impossible for the
** sqlite3VdbeMemCopy() to fail */
assert( (aMem[pOp->p2].flags & MEM_Str)!=0 );
assert( (aMem[pOp->p2].flags & MEM_Static)!=0 );
rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]);
assert( rc==SQLITE_OK );
zTab = (const char*)sqlite3_value_text(&sMem);
assert( zTab || db->mallocFailed );
if( zTab ){
rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg);
}
sqlite3VdbeMemRelease(&sMem);
if( rc ) goto abort_due_to_error;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VDestroy P1 * * P4 *
**
** P4 is the name of a virtual table in database P1. Call the xDestroy method
** of that table.
*/
case OP_VDestroy: {
db->nVDestroy++;
rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
db->nVDestroy--;
assert( p->errorAction==OE_Abort && p->usesStmtJournal );
if( rc ) goto abort_due_to_error;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VOpen P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** P1 is a cursor number. This opcode opens a cursor to the virtual
** table and stores that cursor in P1.
*/
case OP_VOpen: { /* ncycle */
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVCur;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
assert( p->bIsReader );
pCur = p->apCsr[pOp->p1];
if( pCur!=0
&& ALWAYS( pCur->eCurType==CURTYPE_VTAB )
&& ALWAYS( pCur->uc.pVCur->pVtab==pOp->p4.pVtab->pVtab )
){
/* This opcode is a no-op if the cursor is already open */
break;
}
pVCur = 0;
pVtab = pOp->p4.pVtab->pVtab;
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
rc = SQLITE_LOCKED;
goto abort_due_to_error;
}
pModule = pVtab->pModule;
rc = pModule->xOpen(pVtab, &pVCur);
sqlite3VtabImportErrmsg(p, pVtab);
if( rc ) goto abort_due_to_error;
/* Initialize sqlite3_vtab_cursor base class */
pVCur->pVtab = pVtab;
/* Initialize vdbe cursor object */
pCur = allocateCursor(p, pOp->p1, 0, CURTYPE_VTAB);
if( pCur ){
pCur->uc.pVCur = pVCur;
pVtab->nRef++;
}else{
assert( db->mallocFailed );
pModule->xClose(pVCur);
goto no_mem;
}
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCheck P1 P2 P3 P4 *
**
** P4 is a pointer to a Table object that is a virtual table in schema P1
** that supports the xIntegrity() method. This opcode runs the xIntegrity()
** method for that virtual table, using P3 as the integer argument. If
** an error is reported back, the table name is prepended to the error
** message and that message is stored in P2. If no errors are seen,
** register P2 is set to NULL.
*/
case OP_VCheck: { /* out2 */
Table *pTab;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
char *zErr = 0;
pOut = &aMem[pOp->p2];
sqlite3VdbeMemSetNull(pOut); /* Innocent until proven guilty */
assert( pOp->p4type==P4_TABLEREF );
pTab = pOp->p4.pTab;
assert( pTab!=0 );
assert( pTab->nTabRef>0 );
assert( IsVirtual(pTab) );
if( pTab->u.vtab.p==0 ) break;
pVtab = pTab->u.vtab.p->pVtab;
assert( pVtab!=0 );
pModule = pVtab->pModule;
assert( pModule!=0 );
assert( pModule->iVersion>=4 );
assert( pModule->xIntegrity!=0 );
sqlite3VtabLock(pTab->u.vtab.p);
assert( pOp->p1>=0 && pOp->p1<db->nDb );
rc = pModule->xIntegrity(pVtab, db->aDb[pOp->p1].zDbSName, pTab->zName,
pOp->p3, &zErr);
sqlite3VtabUnlock(pTab->u.vtab.p);
if( rc ){
sqlite3_free(zErr);
goto abort_due_to_error;
}
if( zErr ){
sqlite3VdbeMemSetStr(pOut, zErr, -1, SQLITE_UTF8, sqlite3_free);
}
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VInitIn P1 P2 P3 * *
** Synopsis: r[P2]=ValueList(P1,P3)
**
** Set register P2 to be a pointer to a ValueList object for cursor P1
** with cache register P3 and output register P3+1. This ValueList object
** can be used as the first argument to sqlite3_vtab_in_first() and
** sqlite3_vtab_in_next() to extract all of the values stored in the P1
** cursor. Register P3 is used to hold the values returned by
** sqlite3_vtab_in_first() and sqlite3_vtab_in_next().
*/
case OP_VInitIn: { /* out2, ncycle */
VdbeCursor *pC; /* The cursor containing the RHS values */
ValueList *pRhs; /* New ValueList object to put in reg[P2] */
pC = p->apCsr[pOp->p1];
pRhs = sqlite3_malloc64( sizeof(*pRhs) );
if( pRhs==0 ) goto no_mem;
pRhs->pCsr = pC->uc.pCursor;
pRhs->pOut = &aMem[pOp->p3];
pOut = out2Prerelease(p, pOp);
pOut->flags = MEM_Null;
sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3VdbeValueListFree);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
** Synopsis: iplan=r[P3] zplan='P4'
**
** P1 is a cursor opened using VOpen. P2 is an address to jump to if
** the filtered result set is empty.
**
** P4 is either NULL or a string that was generated by the xBestIndex
** method of the module. The interpretation of the P4 string is left
** to the module implementation.
**
** This opcode invokes the xFilter method on the virtual table specified
** by P1. The integer query plan parameter to xFilter is stored in register
** P3. Register P3+1 stores the argc parameter to be passed to the
** xFilter method. Registers P3+2..P3+1+argc are the argc
** additional parameters which are passed to
** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
**
** A jump is made to P2 if the result set after filtering would be empty.
*/
case OP_VFilter: { /* jump, ncycle */
int nArg;
int iQuery;
const sqlite3_module *pModule;
Mem *pQuery;
Mem *pArgc;
sqlite3_vtab_cursor *pVCur;
sqlite3_vtab *pVtab;
VdbeCursor *pCur;
int res;
int i;
Mem **apArg;
pQuery = &aMem[pOp->p3];
pArgc = &pQuery[1];
pCur = p->apCsr[pOp->p1];
assert( memIsValid(pQuery) );
REGISTER_TRACE(pOp->p3, pQuery);
assert( pCur!=0 );
assert( pCur->eCurType==CURTYPE_VTAB );
pVCur = pCur->uc.pVCur;
pVtab = pVCur->pVtab;
pModule = pVtab->pModule;
/* Grab the index number and argc parameters */
assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
nArg = (int)pArgc->u.i;
iQuery = (int)pQuery->u.i;
/* Invoke the xFilter method */
apArg = p->apArg;
assert( nArg<=p->napArg );
for(i = 0; i<nArg; i++){
apArg[i] = &pArgc[i+1];
}
rc = pModule->xFilter(pVCur, iQuery, pOp->p4.z, nArg, apArg);
sqlite3VtabImportErrmsg(p, pVtab);
if( rc ) goto abort_due_to_error;
res = pModule->xEof(pVCur);
pCur->nullRow = 0;
VdbeBranchTaken(res!=0,2);
if( res ) goto jump_to_p2;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VColumn P1 P2 P3 * P5
** Synopsis: r[P3]=vcolumn(P2)
**
** Store in register P3 the value of the P2-th column of
** the current row of the virtual-table of cursor P1.
**
** If the VColumn opcode is being used to fetch the value of
** an unchanging column during an UPDATE operation, then the P5
** value is OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange()
** function to return true inside the xColumn method of the virtual
** table implementation. The P5 column might also contain other
** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are
** unused by OP_VColumn.
*/
case OP_VColumn: { /* ncycle */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
FuncDef nullFunc;
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur!=0 );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
}
assert( pCur->eCurType==CURTYPE_VTAB );
pVtab = pCur->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
sContext.enc = encoding;
nullFunc.pUserData = 0;
nullFunc.funcFlags = SQLITE_RESULT_SUBTYPE;
sContext.pFunc = &nullFunc;
assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
pDest->flags = MEM_Null|MEM_Zero;
pDest->u.nZero = 0;
}else{
MemSetTypeFlag(pDest, MEM_Null);
}
rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
sqlite3VtabImportErrmsg(p, pVtab);
if( sContext.isError>0 ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest));
rc = sContext.isError;
}
sqlite3VdbeChangeEncoding(pDest, encoding);
REGISTER_TRACE(pOp->p3, pDest);
UPDATE_MAX_BLOBSIZE(pDest);
if( rc ) goto abort_due_to_error;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VNext P1 P2 * * *
**
** Advance virtual table P1 to the next row in its result set and
** jump to instruction P2. Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: { /* jump, ncycle */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
pCur = p->apCsr[pOp->p1];
assert( pCur!=0 );
assert( pCur->eCurType==CURTYPE_VTAB );
if( pCur->nullRow ){
break;
}
pVtab = pCur->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xNext );
/* Invoke the xNext() method of the module. There is no way for the
** underlying implementation to return an error if one occurs during
** xNext(). Instead, if an error occurs, true is returned (indicating that
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
rc = pModule->xNext(pCur->uc.pVCur);
sqlite3VtabImportErrmsg(p, pVtab);
if( rc ) goto abort_due_to_error;
res = pModule->xEof(pCur->uc.pVCur);
VdbeBranchTaken(!res,2);
if( !res ){
/* If there is data, jump to P2 */
goto jump_to_p2_and_check_for_interrupt;
}
goto check_for_interrupt;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VRename P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** This opcode invokes the corresponding xRename method. The value
** in register P1 is passed as the zName argument to the xRename method.
*/
case OP_VRename: {
sqlite3_vtab *pVtab;
Mem *pName;
int isLegacy;
isLegacy = (db->flags & SQLITE_LegacyAlter);
db->flags |= SQLITE_LegacyAlter;
pVtab = pOp->p4.pVtab->pVtab;
pName = &aMem[pOp->p1];
assert( pVtab->pModule->xRename );
assert( memIsValid(pName) );
assert( p->readOnly==0 );
REGISTER_TRACE(pOp->p1, pName);
assert( pName->flags & MEM_Str );
testcase( pName->enc==SQLITE_UTF8 );
testcase( pName->enc==SQLITE_UTF16BE );
testcase( pName->enc==SQLITE_UTF16LE );
rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
if( rc ) goto abort_due_to_error;
rc = pVtab->pModule->xRename(pVtab, pName->z);
if( isLegacy==0 ) db->flags &= ~(u64)SQLITE_LegacyAlter;
sqlite3VtabImportErrmsg(p, pVtab);
p->expired = 0;
if( rc ) goto abort_due_to_error;
break;
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VUpdate P1 P2 P3 P4 P5
** Synopsis: data=r[P3@P2]
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** This opcode invokes the corresponding xUpdate method. P2 values
** are contiguous memory cells starting at P3 to pass to the xUpdate
** invocation. The value in register (P3+P2-1) corresponds to the
** p2th element of the argv array passed to xUpdate.
**
** The xUpdate method will do a DELETE or an INSERT or both.
*/
assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 );
/* OP_Init is always instruction 0 */
assert( pOp==p->aOp || pOp->opcode==OP_Trace );
#ifndef SQLITE_OMIT_TRACE
if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
&& p->minWriteFileFormat!=254 /* tag-20220401a */
&& (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
){
#ifndef SQLITE_OMIT_DEPRECATED
if( db->mTrace & SQLITE_TRACE_LEGACY ){
char *z = sqlite3VdbeExpandSql(p, zTrace);
db->trace.xLegacy(db->pTraceArg, z);
sqlite3_free(z);
}else
#endif
if( db->nVdbeExec>1 ){
char *z = sqlite3MPrintf(db, "-- %s", zTrace);
(void)db->trace.xV2(SQLITE_TRACE_STMT, db->pTraceArg, p, z);
sqlite3DbFree(db, z);
}else{
(void)db->trace.xV2(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
}
}
#ifdef SQLITE_USE_FCNTL_TRACE
zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
if( zTrace ){
int j;
for(j=0; j<db->nDb; j++){
if( DbMaskTest(p->btreeMask, j)==0 ) continue;
sqlite3_file_control(db, db->aDb[j].zDbSName, SQLITE_FCNTL_TRACE, zTrace);
}
}
#endif /* SQLITE_USE_FCNTL_TRACE */
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0
&& (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
){
sqlite3DebugPrintf("SQL-trace: %s\n", zTrace);
}
#endif /* SQLITE_DEBUG */
#endif /* SQLITE_OMIT_TRACE */
assert( pOp->p2>0 );
if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){
if( pOp->opcode==OP_Trace ) break;
for(i=1; i<p->nOp; i++){
if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0;
}
pOp->p1 = 0;
}
pOp->p1++;
p->aCounter[SQLITE_STMTSTATUS_RUN]++;
goto jump_to_p2;
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
/* Opcode: CursorHint P1 * * P4 *
**
** Provide a hint to cursor P1 that it only needs to return rows that
** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer
** to values currently held in registers. TK_COLUMN terms in the P4
** expression refer to columns in the b-tree to which cursor P1 is pointing.
*/
case OP_CursorHint: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p4type==P4_EXPR );
pC = p->apCsr[pOp->p1];
if( pC ){
assert( pC->eCurType==CURTYPE_BTREE );
sqlite3BtreeCursorHint(pC->uc.pCursor, BTREE_HINT_RANGE,
pOp->p4.pExpr, aMem);
}
break;
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
#ifdef SQLITE_DEBUG
/* Opcode: Abortable * * * * *
**
** Verify that an Abort can happen. Assert if an Abort at this point
** might cause database corruption. This opcode only appears in debugging
** builds.
**
** An Abort is safe if either there have been no writes, or if there is
** an active statement journal.
*/
case OP_Abortable: {
sqlite3VdbeAssertAbortable(p);
break;
}
#endif
#ifdef SQLITE_DEBUG
/* Opcode: ReleaseReg P1 P2 P3 * P5
** Synopsis: release r[P1@P2] mask P3
**
** Release registers from service. Any content that was in the
** the registers is unreliable after this opcode completes.
**
** The registers released will be the P2 registers starting at P1,
** except if bit ii of P3 set, then do not release register P1+ii.
** In other words, P3 is a mask of registers to preserve.
**
** Releasing a register clears the Mem.pScopyFrom pointer. That means
** that if the content of the released register was set using OP_SCopy,
** a change to the value of the source register for the OP_SCopy will no longer
** generate an assertion fault in sqlite3VdbeMemAboutToChange().
**
** If P5 is set, then all released registers have their type set
** to MEM_Undefined so that any subsequent attempt to read the released
** register (before it is reinitialized) will generate an assertion fault.
**
** P5 ought to be set on every call to this opcode.
** However, there are places in the code generator will release registers
** before their are used, under the (valid) assumption that the registers
** will not be reallocated for some other purpose before they are used and
** hence are safe to release.
**
** This opcode is only available in testing and debugging builds. It is
** not generated for release builds. The purpose of this opcode is to help
}
assert( rc!=SQLITE_OK || nExtraDelete==0
|| sqlite3_strlike("DELETE%",p->zSql,0)!=0
);
return rc;
/* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH
** is encountered.
*/
too_big:
sqlite3VdbeError(p, "string or blob too big");
rc = SQLITE_TOOBIG;
goto abort_due_to_error;
/* Jump to here if a malloc() fails.
*/
no_mem:
sqlite3OomFault(db);
sqlite3VdbeError(p, "out of memory");
rc = SQLITE_NOMEM_BKPT;
goto abort_due_to_error;
/* Jump to here if the sqlite3_interrupt() API sets the interrupt
** flag.
*/
abort_due_to_interrupt:
assert( AtomicLoad(&db->u1.isInterrupted) );
rc = SQLITE_INTERRUPT;
goto abort_due_to_error;
}
/************** End of vdbe.c ************************************************/
/************** Begin file vdbeblob.c ****************************************/
/*
** 2007 May 1
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement incremental BLOB I/O.
*/
/* #include "sqliteInt.h" */
/* #include "vdbeInt.h" */
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Valid sqlite3_blob* handles point to Incrblob structures.
*/
typedef struct Incrblob Incrblob;
struct Incrblob {
int nByte; /* Size of open blob, in bytes */
int iOffset; /* Byte offset of blob in cursor data */
u16 iCol; /* Table column this handle is open on */
BtCursor *pCsr; /* Cursor pointing at blob row */
sqlite3_stmt *pStmt; /* Statement holding cursor open */
sqlite3 *db; /* The associated database */
char *zDb; /* Database name */
Table *pTab; /* Table object */
};
/*
** This function is used by both blob_open() and blob_reopen(). It seeks
** the b-tree cursor associated with blob handle p to point to row iRow.
** If successful, SQLITE_OK is returned and subsequent calls to
** sqlite3_blob_read() or sqlite3_blob_write() access the specified row.
**
** If an error occurs, or if the specified row does not exist or does not
** contain a value of type TEXT or BLOB in the column nominated when the
** blob handle was opened, then an error code is returned and *pzErr may
** be set to point to a buffer containing an error message. It is the
** responsibility of the caller to free the error message buffer using
** sqlite3DbFree().
**
** If an error does occur, then the b-tree cursor is closed. All subsequent
** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will
** immediately return SQLITE_ABORT.
*/
static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
int rc; /* Error code */
char *zErr = 0; /* Error message */
Vdbe *v = (Vdbe *)p->pStmt;
/* Set the value of register r[1] in the SQL statement to integer iRow.
** This is done directly as a performance optimization
*/
sqlite3VdbeMemSetInt64(&v->aMem[1], iRow);
/* If the statement has been run before (and is paused at the OP_ResultRow)
** then back it up to the point where it does the OP_NotExists. This could
** have been down with an extra OP_Goto, but simply setting the program
** counter is faster. */
if( v->pc>4 ){
v->pc = 4;
assert( v->aOp[v->pc].opcode==OP_NotExists );
rc = sqlite3VdbeExec(v);
}else{
rc = sqlite3_step(p->pStmt);
}
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
u32 type;
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
testcase( pC->nHdrParsed==p->iCol );
testcase( pC->nHdrParsed==p->iCol+1 );
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
);
rc = SQLITE_ERROR;
sqlite3_finalize(p->pStmt);
p->pStmt = 0;
}else{
p->iOffset = pC->aType[p->iCol + pC->nField];
p->nByte = sqlite3VdbeSerialTypeLen(type);
p->pCsr = pC->uc.pCursor;
sqlite3BtreeIncrblobCursor(p->pCsr);
}
}
if( rc==SQLITE_ROW ){
rc = SQLITE_OK;
}else if( p->pStmt ){
rc = sqlite3_finalize(p->pStmt);
p->pStmt = 0;
if( rc==SQLITE_OK ){
zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow);
rc = SQLITE_ERROR;
}else{
zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db));
}
}
}
pBlob->pTab = pTab;
pBlob->zDb = db->aDb[iDb].zDbSName;
/* Now search pTab for the exact column. */
iCol = sqlite3ColumnIndex(pTab, zColumn);
if( iCol<0 ){
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
/* If the value is being opened for writing, check that the
** column is not indexed, and that it is not part of a foreign key.
*/
if( wrFlag ){
const char *zFault = 0;
Index *pIdx;
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( db->flags&SQLITE_ForeignKeys ){
/* Check that the column is not part of an FK child key definition. It
** is not necessary to check if it is part of a parent key, as parent
** key columns must be indexed. The check below will pick up this
** case. */
FKey *pFKey;
assert( IsOrdinaryTable(pTab) );
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
int j;
for(j=0; j<pFKey->nCol; j++){
if( pFKey->aCol[j].iFrom==iCol ){
zFault = "foreign key";
}
}
}
}
#endif
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int j;
for(j=0; j<pIdx->nKeyCol; j++){
/* FIXME: Be smarter about indexes that use expressions */
if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){
zFault = "indexed";
}
}
}
if( zFault ){
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
}
pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(&sParse);
assert( pBlob->pStmt || db->mallocFailed );
if( pBlob->pStmt ){
/* This VDBE program seeks a btree cursor to the identified
** db/table/row entry. The reason for using a vdbe program instead
** of writing code to use the b-tree layer directly is that the
** vdbe program will take advantage of the various transaction,
** locking and error handling infrastructure built into the vdbe.
**
** After seeking the cursor, the vdbe executes an OP_ResultRow.
** Code external to the Vdbe then "borrows" the b-tree cursor and
** uses it to implement the blob_read(), blob_write() and
** blob_bytes() functions.
**
** The sqlite3_blob_close() function finalizes the vdbe program,
** which closes the b-tree cursor and (possibly) commits the
** transaction.
*/
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList openBlob[] = {
{OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */
{OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */
/* blobSeekToRow() will initialize r[1] to the desired rowid */
{OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */
{OP_Column, 0, 0, 1}, /* 3 */
{OP_ResultRow, 1, 0, 0}, /* 4 */
{OP_Halt, 0, 0, 0}, /* 5 */
};
Vdbe *v = (Vdbe *)pBlob->pStmt;
VdbeOp *aOp;
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
pTab->pSchema->schema_cookie,
pTab->pSchema->iGeneration);
sqlite3VdbeChangeP5(v, 1);
assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed );
aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
/* Make sure a mutex is held on the table to be accessed */
sqlite3VdbeUsesBtree(v, iDb);
if( db->mallocFailed==0 ){
assert( aOp!=0 );
/* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
aOp[0].opcode = OP_Noop;
#else
aOp[0].p1 = iDb;
aOp[0].p2 = pTab->tnum;
aOp[0].p3 = wrFlag;
sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
}
if( db->mallocFailed==0 ){
#endif
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
if( wrFlag ) aOp[1].opcode = OP_OpenWrite;
aOp[1].p2 = pTab->tnum;
aOp[1].p3 = iDb;
/* Configure the number of columns. Configure the cursor to
** think that the table has one more column than it really
** does. An OP_Column to retrieve this imaginary column will
** always return an SQL NULL. This is useful because it means
** we can invoke OP_Column to fill in the vdbe cursors type
** and offset cache without causing any IO.
*/
aOp[1].p4type = P4_INT32;
aOp[1].p4.i = pTab->nCol+1;
aOp[3].p2 = pTab->nCol;
sParse.nVar = 0;
sParse.nMem = 1;
sParse.nTab = 1;
sqlite3VdbeMakeReady(v, &sParse);
}
}
pBlob->iCol = iCol;
pBlob->db = db;
sqlite3BtreeLeaveAll(db);
if( db->mallocFailed ){
goto blob_open_out;
}
rc = blobSeekToRow(pBlob, iRow, &zErr);
if( (++nAttempt)>=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break;
sqlite3ParseObjectReset(&sParse);
}
blob_open_out:
if( rc==SQLITE_OK && db->mallocFailed==0 ){
*ppBlob = (sqlite3_blob *)pBlob;
}else{
if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
sqlite3DbFree(db, pBlob);
}
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr);
sqlite3DbFree(db, zErr);
sqlite3ParseObjectReset(&sParse);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** Close a blob handle that was previously created using
** sqlite3_blob_open().
*/
SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){
Incrblob *p = (Incrblob *)pBlob;
int rc;
sqlite3 *db;
if( p ){
sqlite3_stmt *pStmt = p->pStmt;
db = p->db;
sqlite3_mutex_enter(db->mutex);
sqlite3DbFree(db, p);
sqlite3_mutex_leave(db->mutex);
rc = sqlite3_finalize(pStmt);
}else{
rc = SQLITE_OK;
}
return rc;
}
/*
** Perform a read or write operation on a blob
*/
static int blobReadWrite(
sqlite3_blob *pBlob,
void *z,
int n,
int iOffset,
int (*xCall)(BtCursor*, u32, u32, void*)
){
int rc = SQLITE_OK;
Incrblob *p = (Incrblob *)pBlob;
Vdbe *v;
sqlite3 *db;
if( p==0 ) return SQLITE_MISUSE_BKPT;
db = p->db;
sqlite3_mutex_enter(db->mutex);
v = (Vdbe*)p->pStmt;
if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){
/* Request is out of range. Return a transient error. */
rc = SQLITE_ERROR;
}else if( v==0 ){
/* If there is no statement handle, then the blob-handle has
** already been invalidated. Return SQLITE_ABORT in this case.
*/
rc = SQLITE_ABORT;
}else{
/* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
** returned, clean-up the statement handle.
*/
assert( db == v->db );
sqlite3BtreeEnterCursor(p->pCsr);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
if( xCall==sqlite3BtreePutData && db->xPreUpdateCallback ){
/* If a pre-update hook is registered and this is a write cursor,
** invoke it here.
**
** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this
** operation should really be an SQLITE_UPDATE. This is probably
** incorrect, but is convenient because at this point the new.* values
** are not easily obtainable. And for the sessions module, an
** SQLITE_UPDATE where the PK columns do not change is handled in the
** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually
** slightly more efficient). Since you cannot write to a PK column
** using the incremental-blob API, this works. For the sessions module
** anyhow.
*/
if( sqlite3BtreeCursorIsValidNN(p->pCsr)==0 ){
/* If the cursor is not currently valid, try to reseek it. This
** always either fails or finds the correct row - the cursor will
** have been marked permanently CURSOR_INVALID if the open row has
** been deleted. */
int bDiff = 0;
rc = sqlite3BtreeCursorRestore(p->pCsr, &bDiff);
assert( bDiff==0 || sqlite3BtreeCursorIsValidNN(p->pCsr)==0 );
}
if( sqlite3BtreeCursorIsValidNN(p->pCsr) ){
sqlite3_int64 iKey;
iKey = sqlite3BtreeIntegerKey(p->pCsr);
assert( v->apCsr[0]!=0 );
assert( v->apCsr[0]->eCurType==CURTYPE_BTREE );
sqlite3VdbePreUpdateHook(
v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
);
}
}
if( rc==SQLITE_OK ){
rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
}
#else
rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
#endif
sqlite3BtreeLeaveCursor(p->pCsr);
if( rc==SQLITE_ABORT ){
sqlite3VdbeFinalize(v);
p->pStmt = 0;
}else{
v->rc = rc;
}
}
sqlite3Error(db, rc);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** Read data from a blob handle.
*/
SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreePayloadChecked);
}
/*
** Write data to a blob handle.
*/
SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
}
/*
** Query a blob handle for the size of the data.
**
** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
** so no mutex is required for access.
*/
SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){
Incrblob *p = (Incrblob *)pBlob;
return (p && p->pStmt) ? p->nByte : 0;
if( p->pStmt==0 ){
/* If there is no statement handle, then the blob-handle has
** already been invalidated. Return SQLITE_ABORT in this case.
*/
rc = SQLITE_ABORT;
}else{
char *zErr;
((Vdbe*)p->pStmt)->rc = SQLITE_OK;
rc = blobSeekToRow(p, iRow, &zErr);
if( rc!=SQLITE_OK ){
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr);
sqlite3DbFree(db, zErr);
}
assert( rc!=SQLITE_SCHEMA );
}
rc = sqlite3ApiExit(db, rc);
assert( rc==SQLITE_OK || p->pStmt==0 );
sqlite3_mutex_leave(db->mutex);
return rc;
}
#endif /* #ifndef SQLITE_OMIT_INCRBLOB */
/************** End of vdbeblob.c ********************************************/
/************** Begin file vdbesort.c ****************************************/
/*
** 2011-07-09
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code for the VdbeSorter object, used in concert with
** a VdbeCursor to sort large numbers of keys for CREATE INDEX statements
** or by SELECT statements with ORDER BY clauses that cannot be satisfied
** using indexes and without LIMIT clauses.
**
** The VdbeSorter object implements a multi-threaded external merge sort
** algorithm that is efficient even if the number of elements being sorted
** exceeds the available memory.
**
** Here is the (internal, non-API) interface between this module and the
** rest of the SQLite system:
**
** sqlite3VdbeSorterInit() Create a new VdbeSorter object.
**
** sqlite3VdbeSorterWrite() Add a single new row to the VdbeSorter
** object. The row is a binary blob in the
** OP_MakeRecord format that contains both
** the ORDER BY key columns and result columns
** in the case of a SELECT w/ ORDER BY, or
** the complete record for an index entry
** in the case of a CREATE INDEX.
**
** sqlite3VdbeSorterRewind() Sort all content previously added.
** Position the read cursor on the
** first sorted element.
**
** sqlite3VdbeSorterNext() Advance the read cursor to the next sorted
** element.
**
** sqlite3VdbeSorterRowkey() Return the complete binary blob for the
** row currently under the read cursor.
**
** sqlite3VdbeSorterCompare() Compare the binary blob for the row
** currently under the read cursor against
** another binary blob X and report if
** X is strictly less than the read cursor.
** Used to enforce uniqueness in a
** CREATE UNIQUE INDEX statement.
**
** sqlite3VdbeSorterClose() Close the VdbeSorter object and reclaim
** all resources.
**
** sqlite3VdbeSorterReset() Refurbish the VdbeSorter for reuse. This
** is like Close() followed by Init() only
** much faster.
**
** The interfaces above must be called in a particular order. Write() can
** only occur in between Init()/Reset() and Rewind(). Next(), Rowkey(), and
** Compare() can only occur in between Rewind() and Close()/Reset(). i.e.
**
** Init()
** for each record: Write()
** Rewind()
** Rowkey()/Compare()
** Next()
** Close()
**
** Algorithm:
**
** Records passed to the sorter via calls to Write() are initially held
** unsorted in main memory. Assuming the amount of memory used never exceeds
** a threshold, when Rewind() is called the set of records is sorted using
** an in-memory merge sort. In this case, no temporary files are required
** and subsequent calls to Rowkey(), Next() and Compare() read records
** directly from main memory.
**
** If the amount of space used to store records in main memory exceeds the
** threshold, then the set of records currently in memory are sorted and
** written to a temporary file in "Packed Memory Array" (PMA) format.
** A PMA created at this point is known as a "level-0 PMA". Higher levels
** of PMAs may be created by merging existing PMAs together - for example
** merging two or more level-0 PMAs together creates a level-1 PMA.
**
** The threshold for the amount of main memory to use before flushing
** records to a PMA is roughly the same as the limit configured for the
** page-cache of the main database. Specifically, the threshold is set to
** the value returned by "PRAGMA main.page_size" multiplied by
** that returned by "PRAGMA main.cache_size", in bytes.
**
** If the sorter is running in single-threaded mode, then all PMAs generated
** are appended to a single temporary file. Or, if the sorter is running in
** multi-threaded mode then up to (N+1) temporary files may be opened, where
** N is the configured number of worker threads. In this case, instead of
** sorting the records and writing the PMA to a temporary file itself, the
** calling thread usually launches a worker thread to do so. Except, if
** there are already N worker threads running, the main thread does the work
** itself.
**
** The sorter is running in multi-threaded mode if (a) the library was built
** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater
** than zero, and (b) worker threads have been enabled at runtime by calling
** "PRAGMA threads=N" with some value of N greater than 0.
**
** When Rewind() is called, any data remaining in memory is flushed to a
** final PMA. So at this point the data is stored in some number of sorted
** PMAs within temporary files on disk.
**
** In other words, each time we advance to the next sorter element, log2(N)
** key comparison operations are required, where N is the number of segments
** being merged (rounded up to the next power of 2).
*/
struct MergeEngine {
int nTree; /* Used size of aTree/aReadr (power of 2) */
SortSubtask *pTask; /* Used by this thread only */
int *aTree; /* Current state of incremental merge */
PmaReader *aReadr; /* Array of PmaReaders to merge data from */
};
/*
** This object represents a single thread of control in a sort operation.
** Exactly VdbeSorter.nTask instances of this object are allocated
** as part of each VdbeSorter object. Instances are never allocated any
** other way. VdbeSorter.nTask is set to the number of worker threads allowed
** (see SQLITE_CONFIG_WORKER_THREADS) plus one (the main thread). Thus for
** single-threaded operation, there is exactly one instance of this object
** and for multi-threaded operation there are two or more instances.
**
** Essentially, this structure contains all those fields of the VdbeSorter
** structure for which each thread requires a separate instance. For example,
** each thread requeries its own UnpackedRecord object to unpack records in
** as part of comparison operations.
**
** Before a background thread is launched, variable bDone is set to 0. Then,
** right before it exits, the thread itself sets bDone to 1. This is used for
** two purposes:
**
** 1. When flushing the contents of memory to a level-0 PMA on disk, to
** attempt to select a SortSubtask for which there is not already an
** active background thread (since doing so causes the main thread
** to block until it finishes).
**
** 2. If SQLITE_DEBUG_SORTER_THREADS is defined, to determine if a call
** to sqlite3ThreadJoin() is likely to block. Cases that are likely to
** block provoke debugging output.
**
** In both cases, the effects of the main thread seeing (bDone==0) even
** after the thread has finished are not dire. So we don't worry about
** memory barriers and such here.
*/
typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int);
struct SortSubtask {
SQLiteThread *pThread; /* Background thread, if any */
int bDone; /* Set if thread is finished but not joined */
int nPMA; /* Number of PMAs currently in file */
VdbeSorter *pSorter; /* Sorter that owns this sub-task */
UnpackedRecord *pUnpacked; /* Space to unpack a record */
SorterList list; /* List for thread to write to a PMA */
SorterCompare xCompare; /* Compare function to use */
SorterFile file; /* Temp file for level-0 PMAs */
SorterFile file2; /* Space for other PMAs */
u64 nSpill; /* Total bytes written by this task */
};
/*
** Main sorter structure. A single instance of this is allocated for each
** sorter cursor created by the VDBE.
**
** mxKeysize:
** As records are added to the sorter by calls to sqlite3VdbeSorterWrite(),
** this variable is updated so as to be set to the size on disk of the
** largest record in the sorter.
*/
struct VdbeSorter {
int mnPmaSize; /* Minimum PMA size, in bytes */
int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */
int mxKeysize; /* Largest serialized key seen so far */
int pgsz; /* Main database page size */
PmaReader *pReader; /* Readr data from here after Rewind() */
MergeEngine *pMerger; /* Or here, if bUseThreads==0 */
sqlite3 *db; /* Database connection */
KeyInfo *pKeyInfo; /* How to compare records */
UnpackedRecord *pUnpacked; /* Used by VdbeSorterCompare() */
SorterList list; /* List of in-memory records */
int iMemory; /* Offset of free space in list.aMemory */
int nMemory; /* Size of list.aMemory allocation in bytes */
u8 bUsePMA; /* True if one or more PMAs created */
u8 bUseThreads; /* True to use background threads */
u8 iPrev; /* Previous thread used to flush PMA */
u8 nTask; /* Size of aTask[] array */
u8 typeMask;
SortSubtask aTask[FLEXARRAY]; /* One or more subtasks */
};
/* Size (in bytes) of a VdbeSorter object that works with N or fewer subtasks */
#define SZ_VDBESORTER(N) (offsetof(VdbeSorter,aTask)+(N)*sizeof(SortSubtask))
#define SORTER_TYPE_INTEGER 0x01
#define SORTER_TYPE_TEXT 0x02
/*
** An instance of the following object is used to read records out of a
** PMA, in sorted order. The next key to be read is cached in nKey/aKey.
** aKey might point into aMap or into aBuffer. If neither of those locations
** contain a contiguous representation of the key, then aAlloc is allocated
** and the key is copied into aAlloc and aKey is made to point to aAlloc.
**
** pFd==0 at EOF.
*/
struct PmaReader {
i64 iReadOff; /* Current read offset */
i64 iEof; /* 1 byte past EOF for this PmaReader */
int nAlloc; /* Bytes of space at aAlloc */
int nKey; /* Number of bytes in key */
sqlite3_file *pFd; /* File handle we are reading from */
u8 *aAlloc; /* Space for aKey if aBuffer and pMap wont work */
u8 *aKey; /* Pointer to current key */
u8 *aBuffer; /* Current read buffer */
int nBuffer; /* Size of read buffer in bytes */
u8 *aMap; /* Pointer to mapping of entire file */
IncrMerger *pIncr; /* Incremental merger */
};
/*
** Normally, a PmaReader object iterates through an existing PMA stored
** within a temp file. However, if the PmaReader.pIncr variable points to
** an object of the following type, it may be used to iterate/merge through
return SQLITE_OK;
}
/*
** Read a varint from the stream of data accessed by p. Set *pnOut to
** the value read.
*/
static int vdbePmaReadVarint(PmaReader *p, u64 *pnOut){
int iBuf;
if( p->aMap ){
p->iReadOff += sqlite3GetVarint(&p->aMap[p->iReadOff], pnOut);
}else{
iBuf = p->iReadOff % p->nBuffer;
if( iBuf && (p->nBuffer-iBuf)>=9 ){
p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut);
}else{
u8 aVarint[16], *a;
int i = 0, rc;
do{
rc = vdbePmaReadBlob(p, 1, &a);
if( rc ) return rc;
aVarint[(i++)&0xf] = a[0];
}while( (a[0]&0x80)!=0 );
sqlite3GetVarint(aVarint, pnOut);
}
}
return SQLITE_OK;
}
/*
** Attempt to memory map file pFile. If successful, set *pp to point to the
** new mapping and return SQLITE_OK. If the mapping is not attempted
** (because the file is too large or the VFS layer is configured not to use
** mmap), return SQLITE_OK and set *pp to NULL.
**
** Or, if an error occurs, return an SQLite error code. The final value of
** *pp is undefined in this case.
*/
static int vdbeSorterMapFile(SortSubtask *pTask, SorterFile *pFile, u8 **pp){
int rc = SQLITE_OK;
if( pFile->iEof<=(i64)(pTask->pSorter->db->nMaxSorterMmap) ){
sqlite3_file *pFd = pFile->pFd;
if( pFd->pMethods->iVersion>=3 ){
rc = sqlite3OsFetch(pFd, 0, (int)pFile->iEof, (void**)pp);
testcase( rc!=SQLITE_OK );
}
}
return rc;
}
/*
** Attach PmaReader pReadr to file pFile (if it is not already attached to
** that file) and seek it to offset iOff within the file. Return SQLITE_OK
** if successful, or an SQLite error code if an error occurs.
*/
static int vdbePmaReaderSeek(
SortSubtask *pTask, /* Task context */
PmaReader *pReadr, /* Reader whose cursor is to be moved */
SorterFile *pFile, /* Sorter file to read from */
i64 iOff /* Offset in pFile */
){
int rc = SQLITE_OK;
assert( pReadr->pIncr==0 || pReadr->pIncr->bEof==0 );
if( sqlite3FaultSim(201) ) return SQLITE_IOERR_READ;
if( pReadr->aMap ){
sqlite3OsUnfetch(pReadr->pFd, 0, pReadr->aMap);
pReadr->aMap = 0;
}
pReadr->iReadOff = iOff;
pReadr->iEof = pFile->iEof;
pReadr->pFd = pFile->pFd;
rc = vdbeSorterMapFile(pTask, pFile, &pReadr->aMap);
if( rc==SQLITE_OK && pReadr->aMap==0 ){
int pgsz = pTask->pSorter->pgsz;
int iBuf = pReadr->iReadOff % pgsz;
if( pReadr->aBuffer==0 ){
pReadr->aBuffer = (u8*)sqlite3Malloc(pgsz);
if( pReadr->aBuffer==0 ) rc = SQLITE_NOMEM_BKPT;
pReadr->nBuffer = pgsz;
}
if( rc==SQLITE_OK && iBuf ){
int nRead = pgsz - iBuf;
if( (pReadr->iReadOff + nRead) > pReadr->iEof ){
nRead = (int)(pReadr->iEof - pReadr->iReadOff);
}
rc = sqlite3OsRead(
pReadr->pFd, &pReadr->aBuffer[iBuf], nRead, pReadr->iReadOff
);
testcase( rc!=SQLITE_OK );
}
}
return rc;
}
/*
** Advance PmaReader pReadr to the next key in its PMA. Return SQLITE_OK if
** no error occurs, or an SQLite error code if one does.
*/
static int vdbePmaReaderNext(PmaReader *pReadr){
int rc = SQLITE_OK; /* Return Code */
u64 nRec = 0; /* Size of record in bytes */
if( pReadr->iReadOff>=pReadr->iEof ){
IncrMerger *pIncr = pReadr->pIncr;
int bEof = 1;
if( pIncr ){
rc = vdbeIncrSwap(pIncr);
if( rc==SQLITE_OK && pIncr->bEof==0 ){
rc = vdbePmaReaderSeek(
pIncr->pTask, pReadr, &pIncr->aFile[0], pIncr->iStartOff
);
bEof = 0;
}
const u8 * const p1 = (const u8 * const)pKey1;
const u8 * const p2 = (const u8 * const)pKey2;
const int s1 = p1[1]; /* Left hand serial type */
const int s2 = p2[1]; /* Right hand serial type */
const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
int res; /* Return value */
assert( (s1>0 && s1<7) || s1==8 || s1==9 );
assert( (s2>0 && s2<7) || s2==8 || s2==9 );
if( s1==s2 ){
/* The two values have the same sign. Compare using memcmp(). */
static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8, 0, 0, 0 };
const u8 n = aLen[s1];
int i;
res = 0;
for(i=0; i<n; i++){
if( (res = v1[i] - v2[i])!=0 ){
if( ((v1[0] ^ v2[0]) & 0x80)!=0 ){
res = v1[0] & 0x80 ? -1 : +1;
}
break;
}
}
}else if( s1>7 && s2>7 ){
res = s1 - s2;
}else{
if( s2>7 ){
res = +1;
}else if( s1>7 ){
res = -1;
}else{
res = s1 - s2;
}
assert( res!=0 );
if( res>0 ){
if( *v1 & 0x80 ) res = -1;
}else{
if( *v2 & 0x80 ) res = +1;
}
}
assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
if( res==0 ){
if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
);
}
}else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
res = res * -1;
}
return res;
}
/*
** Initialize the temporary index cursor just opened as a sorter cursor.
**
** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField)
** to determine the number of fields that should be compared from the
** records being sorted. However, if the value passed as argument nField
** is non-zero and the sorter is able to guarantee a stable sort, nField
** is used instead. This is used when sorting records for a CREATE INDEX
** statement. In this case, keys are always delivered to the sorter in
** order of the primary key, which happens to be make up the final part
** of the records being sorted. So if the sort is stable, there is never
** any reason to compare PK fields and they can be ignored for a small
** performance boost.
**
** The sorter can guarantee a stable sort when running in single-threaded
** mode, but not in multi-threaded mode.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterInit(
sqlite3 *db, /* Database connection (for malloc()) */
int nField, /* Number of key fields in each record */
VdbeCursor *pCsr /* Cursor that holds the new sorter */
){
int pgsz; /* Page size of main database */
int i; /* Used to iterate through aTask[] */
VdbeSorter *pSorter; /* The new sorter */
KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
i64 sz; /* Size of pSorter in bytes */
int rc = SQLITE_OK;
#if SQLITE_MAX_WORKER_THREADS==0
# define nWorker 0
#else
int nWorker;
#endif
/* Initialize the upper limit on the number of worker threads */
#if SQLITE_MAX_WORKER_THREADS>0
if( sqlite3TempInMemory(db) || sqlite3GlobalConfig.bCoreMutex==0 ){
nWorker = 0;
}else{
nWorker = db->aLimit[SQLITE_LIMIT_WORKER_THREADS];
}
#endif
/* Do not allow the total number of threads (main thread + all workers)
** to exceed the maximum merge count */
#if SQLITE_MAX_WORKER_THREADS>=SORTER_MAX_MERGE_COUNT
if( nWorker>=SORTER_MAX_MERGE_COUNT ){
nWorker = SORTER_MAX_MERGE_COUNT-1;
}
#endif
assert( pCsr->pKeyInfo );
assert( !pCsr->isEphemeral );
assert( pCsr->eCurType==CURTYPE_SORTER );
assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
< 0x7fffffff );
assert( pCsr->pKeyInfo->nKeyField<=pCsr->pKeyInfo->nAllField );
szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nAllField);
sz = SZ_VDBESORTER(nWorker+1);
/*
** Allocate a new MergeEngine object capable of handling up to
** nReader PmaReader inputs.
**
** nReader is automatically rounded up to the next power of two.
** nReader may not exceed SORTER_MAX_MERGE_COUNT even after rounding up.
*/
static MergeEngine *vdbeMergeEngineNew(int nReader){
int N = 2; /* Smallest power of two >= nReader */
i64 nByte; /* Total bytes of space to allocate */
MergeEngine *pNew; /* Pointer to allocated object to return */
assert( nReader<=SORTER_MAX_MERGE_COUNT );
while( N<nReader ) N += N;
nByte = sizeof(MergeEngine) + N * (sizeof(int) + sizeof(PmaReader));
pNew = sqlite3FaultSim(100) ? 0 : (MergeEngine*)sqlite3MallocZero(nByte);
if( pNew ){
pNew->nTree = N;
pNew->pTask = 0;
pNew->aReadr = (PmaReader*)&pNew[1];
pNew->aTree = (int*)&pNew->aReadr[N];
}
return pNew;
}
/*
** Free the MergeEngine object passed as the only argument.
*/
static void vdbeMergeEngineFree(MergeEngine *pMerger){
int i;
if( pMerger ){
for(i=0; i<pMerger->nTree; i++){
vdbePmaReaderClear(&pMerger->aReadr[i]);
}
}
sqlite3_free(pMerger);
}
/*
** Free all resources associated with the IncrMerger object indicated by
** the first argument.
*/
static void vdbeIncrFree(IncrMerger *pIncr){
if( pIncr ){
#if SQLITE_MAX_WORKER_THREADS>0
if( pIncr->bUseThread ){
vdbeSorterJoinThread(pIncr->pTask);
if( pIncr->aFile[0].pFd ) sqlite3OsCloseFree(pIncr->aFile[0].pFd);
if( pIncr->aFile[1].pFd ) sqlite3OsCloseFree(pIncr->aFile[1].pFd);
}
#endif
vdbeMergeEngineFree(pIncr->pMerger);
sqlite3_free(pIncr);
}
}
/*
** Reset a sorting cursor back to its original empty state.
*/
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
int i;
(void)vdbeSorterJoinAll(pSorter, SQLITE_OK);
assert( pSorter->bUseThreads || pSorter->pReader==0 );
#if SQLITE_MAX_WORKER_THREADS>0
if( pSorter->pReader ){
vdbePmaReaderClear(pSorter->pReader);
sqlite3DbFree(db, pSorter->pReader);
pSorter->pReader = 0;
}
#endif
vdbeMergeEngineFree(pSorter->pMerger);
pSorter->pMerger = 0;
for(i=0; i<pSorter->nTask; i++){
SortSubtask *pTask = &pSorter->aTask[i];
vdbeSortSubtaskCleanup(db, pTask);
pTask->pSorter = pSorter;
}
if( pSorter->list.aMemory==0 ){
vdbeSorterRecordFree(0, pSorter->list.pList);
}
pSorter->list.pList = 0;
pSorter->list.szPMA = 0;
pSorter->bUsePMA = 0;
pSorter->iMemory = 0;
pSorter->mxKeysize = 0;
sqlite3DbFree(db, pSorter->pUnpacked);
pSorter->pUnpacked = 0;
}
/*
** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
*/
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
VdbeSorter *pSorter;
assert( pCsr->eCurType==CURTYPE_SORTER );
pSorter = pCsr->uc.pSorter;
if( pSorter ){
/* Increment db->nSpill by the total number of bytes of data written
** to temp files by this sort operation. */
int ii;
for(ii=0; ii<pSorter->nTask; ii++){
db->nSpill += pSorter->aTask[ii].nSpill;
}
sqlite3VdbeSorterReset(db, pSorter);
sqlite3_free(pSorter->list.aMemory);
sqlite3DbFree(db, pSorter);
pCsr->uc.pSorter = 0;
}
}
#if SQLITE_MAX_MMAP_SIZE>0
/*
** The first argument is a file-handle open on a temporary file. The file
** is guaranteed to be nByte bytes or smaller in size. This function
** attempts to extend the file to nByte bytes in size and to ensure that
** the VFS has memory mapped it.
**
** Whether or not the file does end up memory mapped of course depends on
** the specific VFS implementation.
*/
static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
void *p = 0;
int chunksize = 4*1024;
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
sqlite3OsFetch(pFd, 0, (int)nByte, &p);
if( p ) sqlite3OsUnfetch(pFd, 0, p);
}
}
#else
# define vdbeSorterExtendFile(x,y,z)
#endif
/*
** Allocate space for a file-handle and open a temporary file. If successful,
** set *ppFd to point to the malloc'd file-handle and return SQLITE_OK.
** Otherwise, set *ppFd to 0 and return an SQLite error code.
*/
static int vdbeSorterOpenTempFile(
sqlite3 *db, /* Database handle doing sort */
i64 nExtend, /* Attempt to extend file to this size */
sqlite3_file **ppFd
){
int rc;
if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS;
rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd,
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &rc
);
** Or will be, anyhow. */
pSorter->bUsePMA = 1;
/* Select a sub-task to sort and flush the current list of in-memory
** records to disk. If the sorter is running in multi-threaded mode,
** round-robin between the first (pSorter->nTask-1) tasks. Except, if
** the background thread from a sub-tasks previous turn is still running,
** skip it. If the first (pSorter->nTask-1) sub-tasks are all still busy,
** fall back to using the final sub-task. The first (pSorter->nTask-1)
** sub-tasks are preferred as they use background threads - the final
** sub-task uses the main thread. */
for(i=0; i<nWorker; i++){
int iTest = (pSorter->iPrev + i + 1) % nWorker;
pTask = &pSorter->aTask[iTest];
if( pTask->bDone ){
rc = vdbeSorterJoinThread(pTask);
}
if( rc!=SQLITE_OK || pTask->pThread==0 ) break;
}
if( rc==SQLITE_OK ){
if( i==nWorker ){
/* Use the foreground thread for this operation */
rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list);
}else{
/* Launch a background thread for this operation */
u8 *aMem;
void *pCtx;
assert( pTask!=0 );
assert( pTask->pThread==0 && pTask->bDone==0 );
assert( pTask->list.pList==0 );
assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 );
aMem = pTask->list.aMemory;
pCtx = (void*)pTask;
pSorter->iPrev = (u8)(pTask - pSorter->aTask);
pTask->list = pSorter->list;
pSorter->list.pList = 0;
pSorter->list.szPMA = 0;
if( aMem ){
pSorter->list.aMemory = aMem;
pSorter->nMemory = sqlite3MallocSize(aMem);
}else if( pSorter->list.aMemory ){
pSorter->list.aMemory = sqlite3Malloc(pSorter->nMemory);
if( !pSorter->list.aMemory ) return SQLITE_NOMEM_BKPT;
}
rc = vdbeSorterCreateThread(pTask, vdbeSorterFlushThread, pCtx);
}
}
return rc;
#endif /* SQLITE_MAX_WORKER_THREADS!=0 */
}
/*
** Add a record to the sorter.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
const VdbeCursor *pCsr, /* Sorter cursor */
Mem *pVal /* Memory cell containing record */
){
VdbeSorter *pSorter;
int rc = SQLITE_OK; /* Return Code */
SorterRecord *pNew; /* New list element */
int bFlush; /* True to flush contents of memory to PMA */
i64 nReq; /* Bytes of memory required */
i64 nPMA; /* Bytes of PMA space required */
int t; /* serial type of first record field */
assert( pCsr->eCurType==CURTYPE_SORTER );
pSorter = pCsr->uc.pSorter;
getVarint32NR((const u8*)&pVal->z[1], t);
if( t>0 && t<10 && t!=7 ){
pSorter->typeMask &= SORTER_TYPE_INTEGER;
}else if( t>10 && (t & 0x01) ){
pSorter->typeMask &= SORTER_TYPE_TEXT;
}else{
pSorter->typeMask = 0;
}
assert( pSorter );
/* Figure out whether or not the current contents of memory should be
** flushed to a PMA before continuing. If so, do so.
**
** If using the single large allocation mode (pSorter->aMemory!=0), then
** flush the contents of memory to a new PMA if (a) at least one value is
** already in memory and (b) the new value will not fit in memory.
**
** Or, if using separate allocations for each record, flush the contents
** of memory to a PMA if either of the following are true:
**
** * The total memory allocated for the in-memory list is greater
** than (page-size * cache-size), or
**
** * The total memory allocated for the in-memory list is greater
** than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
*/
nReq = pVal->n + sizeof(SorterRecord);
nPMA = pVal->n + sqlite3VarintLen(pVal->n);
if( pSorter->mxPmaSize ){
if( pSorter->list.aMemory ){
bFlush = pSorter->iMemory && (pSorter->iMemory+nReq) > pSorter->mxPmaSize;
}else{
bFlush = (
(pSorter->list.szPMA > pSorter->mxPmaSize)
|| (pSorter->list.szPMA > pSorter->mnPmaSize && sqlite3HeapNearlyFull())
);
}
if( bFlush ){
rc = vdbeSorterFlushPMA(pSorter);
pSorter->list.szPMA = 0;
pSorter->iMemory = 0;
assert( rc!=SQLITE_OK || pSorter->list.pList==0 );
}
}
pSorter->list.szPMA += nPMA;
if( nPMA>pSorter->mxKeysize ){
** If successful, SQLITE_OK is returned. If an error occurs, an SQLite error
** code is returned and pLeaf is freed.
*/
static int vdbeSorterAddToTree(
SortSubtask *pTask, /* Task context */
int nDepth, /* Depth of tree according to TreeDepth() */
int iSeq, /* Sequence number of leaf within tree */
MergeEngine *pRoot, /* Root of tree */
MergeEngine *pLeaf /* Leaf to add to tree */
){
int rc = SQLITE_OK;
int nDiv = 1;
int i;
MergeEngine *p = pRoot;
IncrMerger *pIncr;
rc = vdbeIncrMergerNew(pTask, pLeaf, &pIncr);
for(i=1; i<nDepth; i++){
nDiv = nDiv * SORTER_MAX_MERGE_COUNT;
}
for(i=1; i<nDepth && rc==SQLITE_OK; i++){
int iIter = (iSeq / nDiv) % SORTER_MAX_MERGE_COUNT;
PmaReader *pReadr = &p->aReadr[iIter];
if( pReadr->pIncr==0 ){
MergeEngine *pNew = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT);
if( pNew==0 ){
rc = SQLITE_NOMEM_BKPT;
}else{
rc = vdbeIncrMergerNew(pTask, pNew, &pReadr->pIncr);
}
}
if( rc==SQLITE_OK ){
p = pReadr->pIncr->pMerger;
nDiv = nDiv / SORTER_MAX_MERGE_COUNT;
}
}
if( rc==SQLITE_OK ){
p->aReadr[iSeq % SORTER_MAX_MERGE_COUNT].pIncr = pIncr;
}else{
vdbeIncrFree(pIncr);
}
return rc;
}
/*
** This function is called as part of a SorterRewind() operation on a sorter
** that has already written two or more level-0 PMAs to one or more temp
** files. It builds a tree of MergeEngine/IncrMerger/PmaReader objects that
** can be used to incrementally merge all PMAs on disk.
**
** If successful, SQLITE_OK is returned and *ppOut set to point to the
** MergeEngine object at the root of the tree before returning. Or, if an
** error occurs, an SQLite error code is returned and the final value
** of *ppOut is undefined.
*/
static int vdbeSorterMergeTreeBuild(
VdbeSorter *pSorter, /* The VDBE cursor that implements the sort */
MergeEngine **ppOut /* Write the MergeEngine here */
){
MergeEngine *pMain = 0;
int rc = SQLITE_OK;
int iTask;
#if SQLITE_MAX_WORKER_THREADS>0
/* If the sorter uses more than one task, then create the top-level
** MergeEngine here. This MergeEngine will read data from exactly
** one PmaReader per sub-task. */
assert( pSorter->bUseThreads || pSorter->nTask==1 );
if( pSorter->nTask>1 ){
pMain = vdbeMergeEngineNew(pSorter->nTask);
if( pMain==0 ) rc = SQLITE_NOMEM_BKPT;
}
#endif
for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
SortSubtask *pTask = &pSorter->aTask[iTask];
assert( pTask->nPMA>0 || SQLITE_MAX_WORKER_THREADS>0 );
if( SQLITE_MAX_WORKER_THREADS==0 || pTask->nPMA ){
MergeEngine *pRoot = 0; /* Root node of tree for this task */
int nDepth = vdbeSorterTreeDepth(pTask->nPMA);
i64 iReadOff = 0;
if( pTask->nPMA<=SORTER_MAX_MERGE_COUNT ){
rc = vdbeMergeEngineLevel0(pTask, pTask->nPMA, &iReadOff, &pRoot);
}else{
int i;
int iSeq = 0;
pRoot = vdbeMergeEngineNew(SORTER_MAX_MERGE_COUNT);
if( pRoot==0 ) rc = SQLITE_NOMEM_BKPT;
for(i=0; i<pTask->nPMA && rc==SQLITE_OK; i += SORTER_MAX_MERGE_COUNT){
MergeEngine *pMerger = 0; /* New level-0 PMA merger */
int nReader; /* Number of level-0 PMAs to merge */
nReader = MIN(pTask->nPMA - i, SORTER_MAX_MERGE_COUNT);
rc = vdbeMergeEngineLevel0(pTask, nReader, &iReadOff, &pMerger);
if( rc==SQLITE_OK ){
rc = vdbeSorterAddToTree(pTask, nDepth, iSeq++, pRoot, pMerger);
}
}
}
if( rc==SQLITE_OK ){
#if SQLITE_MAX_WORKER_THREADS>0
if( pMain!=0 ){
rc = vdbeIncrMergerNew(pTask, pRoot, &pMain->aReadr[iTask].pIncr);
}else
#endif
{
assert( pMain==0 );
pMain = pRoot;
}
}else{
vdbeMergeEngineFree(pRoot);
}
}
}
}
}else{
SorterRecord *pFree = pSorter->list.pList;
pSorter->list.pList = pFree->u.pNext;
pFree->u.pNext = 0;
if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree);
rc = pSorter->list.pList ? SQLITE_OK : SQLITE_DONE;
}
return rc;
}
/*
** Return a pointer to a buffer owned by the sorter that contains the
** current key.
*/
static void *vdbeSorterRowkey(
const VdbeSorter *pSorter, /* Sorter object */
int *pnKey /* OUT: Size of current key in bytes */
){
void *pKey;
if( pSorter->bUsePMA ){
PmaReader *pReader;
#if SQLITE_MAX_WORKER_THREADS>0
if( pSorter->bUseThreads ){
pReader = pSorter->pReader;
}else
#endif
/*if( !pSorter->bUseThreads )*/{
pReader = &pSorter->pMerger->aReadr[pSorter->pMerger->aTree[1]];
}
*pnKey = pReader->nKey;
pKey = pReader->aKey;
}else{
*pnKey = pSorter->list.pList->nVal;
pKey = SRVAL(pSorter->list.pList);
}
return pKey;
}
/*
** Copy the current sorter key into the memory cell pOut.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
VdbeSorter *pSorter;
void *pKey; int nKey; /* Sorter key to copy into pOut */
assert( pCsr->eCurType==CURTYPE_SORTER );
pSorter = pCsr->uc.pSorter;
pKey = vdbeSorterRowkey(pSorter, &nKey);
if( sqlite3VdbeMemClearAndResize(pOut, nKey) ){
return SQLITE_NOMEM_BKPT;
}
pOut->n = nKey;
MemSetTypeFlag(pOut, MEM_Blob);
memcpy(pOut->z, pKey, nKey);
return SQLITE_OK;
}
/*
** Compare the key in memory cell pVal with the key that the sorter cursor
** passed as the first argument currently points to. For the purposes of
** the comparison, ignore the rowid field at the end of each record.
**
** If the sorter cursor key contains any NULL values, consider it to be
** less than pVal. Even if pVal also contains NULL values.
**
** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM).
** Otherwise, set *pRes to a negative, zero or positive value if the
** key in pVal is smaller than, equal to or larger than the current sorter
** key.
**
** This routine forms the core of the OP_SorterCompare opcode, which in
** turn is used to verify uniqueness when constructing a UNIQUE INDEX.
*/
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
const VdbeCursor *pCsr, /* Sorter cursor */
Mem *pVal, /* Value to compare to current sorter key */
int nKeyCol, /* Compare this many columns */
int *pRes /* OUT: Result of comparison */
){
VdbeSorter *pSorter;
UnpackedRecord *r2;
KeyInfo *pKeyInfo;
int i;
void *pKey; int nKey; /* Sorter key to compare pVal with */
assert( pCsr->eCurType==CURTYPE_SORTER );
pSorter = pCsr->uc.pSorter;
r2 = pSorter->pUnpacked;
pKeyInfo = pCsr->pKeyInfo;
if( r2==0 ){
r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( r2==0 ) return SQLITE_NOMEM_BKPT;
r2->nField = nKeyCol;
}
assert( r2->nField==nKeyCol );
pKey = vdbeSorterRowkey(pSorter, &nKey);
sqlite3VdbeRecordUnpack(nKey, pKey, r2);
for(i=0; i<nKeyCol; i++){
if( r2->aMem[i].flags & MEM_Null ){
*pRes = -1;
return SQLITE_OK;
}
}
*pRes = sqlite3VdbeRecordCompare(pVal->n, pVal->z, r2);
return SQLITE_OK;
}
/************** End of vdbesort.c ********************************************/
/************** Begin file vdbevtab.c ****************************************/
/*
** 2020-03-23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements virtual-tables for examining the bytecode content
** of a prepared statement.
*/
/* #include "sqliteInt.h" */
#if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
/* #include "vdbeInt.h" */
/* An instance of the bytecode() table-valued function.
*/
typedef struct bytecodevtab bytecodevtab;
struct bytecodevtab {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection */
int bTablesUsed; /* 2 for tables_used(). 0 for bytecode(). */
};
/* A cursor for scanning through the bytecode
*/
typedef struct bytecodevtab_cursor bytecodevtab_cursor;
struct bytecodevtab_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3_stmt *pStmt; /* The statement whose bytecode is displayed */
int iRowid; /* The rowid of the output table */
int iAddr; /* Address */
int needFinalize; /* Cursors owns pStmt and must finalize it */
int showSubprograms; /* Provide a listing of subprograms */
Op *aOp; /* Operand array */
char *zP4; /* Rendered P4 value */
const char *zType; /* tables_used.type */
const char *zSchema; /* tables_used.schema */
const char *zName; /* tables_used.name */
Mem sub; /* Subprograms */
};
/*
** Create a new bytecode() table-valued function.
*/
static int bytecodevtabConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
bytecodevtab *pNew;
int rc;
int isTabUsed = pAux!=0;
const char *azSchema[2] = {
/* bytecode() schema */
"CREATE TABLE x("
"addr INT,"
"opcode TEXT,"
"p1 INT,"
"p2 INT,"
"p3 INT,"
"p4 TEXT,"
"p5 INT,"
"comment TEXT,"
"subprog TEXT,"
"nexec INT,"
"ncycle INT,"
"stmt HIDDEN"
");",
/* Tables_used() schema */
"CREATE TABLE x("
"type TEXT,"
"schema TEXT,"
"name TEXT,"
"wr INT,"
"subprog TEXT,"
"stmt HIDDEN"
");"
};
(void)argc;
(void)argv;
(void)pzErr;
rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]);
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
pNew->db = db;
pNew->bTablesUsed = isTabUsed*2;
}
return rc;
}
/*
** This method is the destructor for bytecodevtab objects.
*/
static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
bytecodevtab *p = (bytecodevtab*)pVtab;
sqlite3_free(p);
return SQLITE_OK;
}
/*
** Constructor for a new bytecodevtab_cursor object.
*/
static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
bytecodevtab *pVTab = (bytecodevtab*)p;
bytecodevtab_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1);
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Clear all internal content from a bytecodevtab cursor.
*/
static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){
sqlite3_free(pCur->zP4);
pCur->zP4 = 0;
sqlite3VdbeMemRelease(&pCur->sub);
sqlite3VdbeMemSetNull(&pCur->sub);
if( pCur->needFinalize ){
sqlite3_finalize(pCur->pStmt);
}
pCur->pStmt = 0;
pCur->needFinalize = 0;
pCur->zType = 0;
pCur->zSchema = 0;
pCur->zName = 0;
}
/*
** Destructor for a bytecodevtab_cursor.
*/
static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
bytecodevtabCursorClear(pCur);
sqlite3_free(pCur);
return SQLITE_OK;
}
/*
** Advance a bytecodevtab_cursor to its next row of output.
*/
static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
bytecodevtab *pTab = (bytecodevtab*)cur->pVtab;
int rc;
if( pCur->zP4 ){
sqlite3_free(pCur->zP4);
pCur->zP4 = 0;
}
if( pCur->zName ){
pCur->zName = 0;
pCur->zType = 0;
pCur->zSchema = 0;
}
rc = sqlite3VdbeNextOpcode(
(Vdbe*)pCur->pStmt,
pCur->showSubprograms ? &pCur->sub : 0,
pTab->bTablesUsed,
&pCur->iRowid,
&pCur->iAddr,
&pCur->aOp);
if( rc!=SQLITE_OK ){
sqlite3VdbeMemSetNull(&pCur->sub);
pCur->aOp = 0;
}
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
return pCur->aOp==0;
}
/*
** Return values of columns for the row at which the bytecodevtab_cursor
** is currently pointing.
*/
static int bytecodevtabColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab;
Op *pOp = pCur->aOp + pCur->iAddr;
if( pVTab->bTablesUsed ){
if( i==4 ){
i = 8;
}else{
if( i<=2 && pCur->zType==0 ){
Schema *pSchema;
HashElem *k;
int iDb = pOp->p3;
Pgno iRoot = (Pgno)pOp->p2;
sqlite3 *db = pVTab->db;
pSchema = db->aDb[iDb].pSchema;
pCur->zSchema = db->aDb[iDb].zDbSName;
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
Table *pTab = (Table*)sqliteHashData(k);
if( !IsVirtual(pTab) && pTab->tnum==iRoot ){
pCur->zName = pTab->zName;
pCur->zType = "table";
break;
}
}
if( pCur->zName==0 ){
for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
Index *pIdx = (Index*)sqliteHashData(k);
if( pIdx->tnum==iRoot ){
pCur->zName = pIdx->zName;
pCur->zType = "index";
}
}
}
}
i += 20;
}
}
switch( i ){
case 0: /* addr */
sqlite3_result_int(ctx, pCur->iAddr);
break;
case 1: /* opcode */
sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode),
-1, SQLITE_STATIC);
break;
case 2: /* p1 */
sqlite3_result_int(ctx, pOp->p1);
break;
case 3: /* p2 */
sqlite3_result_int(ctx, pOp->p2);
break;
case 4: /* p3 */
sqlite3_result_int(ctx, pOp->p3);
break;
case 5: /* p4 */
case 7: /* comment */
if( pCur->zP4==0 ){
pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp);
}
if( i==5 ){
sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC);
}else{
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4);
sqlite3_result_text(ctx, zCom, -1, sqlite3_free);
#endif
}
break;
case 6: /* p5 */
sqlite3_result_int(ctx, pOp->p5);
break;
case 8: { /* subprog */
Op *aOp = pCur->aOp;
assert( aOp[0].opcode==OP_Init );
assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 );
if( pCur->iRowid==pCur->iAddr+1 ){
break; /* Result is NULL for the main program */
}else if( aOp[0].p4.z!=0 ){
sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC);
}else{
sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC);
}
break;
}
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
case 9: /* nexec */
sqlite3_result_int64(ctx, pOp->nExec);
break;
case 10: /* ncycle */
sqlite3_result_int64(ctx, pOp->nCycle);
break;
#else
case 9: /* nexec */
case 10: /* ncycle */
sqlite3_result_int(ctx, 0);
break;
#endif
case 20: /* tables_used.type */
sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
break;
case 21: /* tables_used.schema */
sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC);
break;
case 22: /* tables_used.name */
sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC);
break;
case 23: /* tables_used.wr */
sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite);
break;
}
return SQLITE_OK;
}
/*
** Return the rowid for the current row. In this implementation, the
** rowid is the same as the output value.
*/
static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
/*
** Initialize a cursor.
**
** idxNum==0 means show all subprograms
** idxNum==1 means show only the main bytecode and omit subprograms.
*/
static int bytecodevtabFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab;
int rc = SQLITE_OK;
(void)idxStr;
bytecodevtabCursorClear(pCur);
pCur->iRowid = 0;
pCur->iAddr = 0;
pCur->showSubprograms = idxNum==0;
assert( argc==1 );
if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
const char *zSql = (const char*)sqlite3_value_text(argv[0]);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0);
pCur->needFinalize = 1;
}
}else{
pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer");
}
if( pCur->pStmt==0 ){
pVTab->base.zErrMsg = sqlite3_mprintf(
"argument to %s() is not a valid SQL statement",
pVTab->bTablesUsed ? "tables_used" : "bytecode"
);
rc = SQLITE_ERROR;
}else{
bytecodevtabNext(pVtabCursor);
}
return rc;
}
/*
** We must have a single stmt=? constraint that will be passed through
** into the xFilter method. If there is no valid stmt=? constraint,
** then return an SQLITE_CONSTRAINT error.
*/
static int bytecodevtabBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i;
int rc = SQLITE_CONSTRAINT;
struct sqlite3_index_constraint *p;
bytecodevtab *pVTab = (bytecodevtab*)tab;
int iBaseCol = pVTab->bTablesUsed ? 4 : 10;
pIdxInfo->estimatedCost = (double)100;
pIdxInfo->estimatedRows = 100;
pIdxInfo->idxNum = 0;
for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
if( p->usable==0 ) continue;
if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){
rc = SQLITE_OK;
pIdxInfo->aConstraintUsage[i].omit = 1;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
}
if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){
pIdxInfo->aConstraintUsage[i].omit = 1;
pIdxInfo->idxNum = 1;
}
SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; }
#endif /* SQLITE_ENABLE_BYTECODE_VTAB */
/************** End of vdbevtab.c ********************************************/
/************** Begin file memjournal.c **************************************/
/*
** 2008 October 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code use to implement an in-memory rollback journal.
** The in-memory rollback journal is used to journal transactions for
** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
**
** Update: The in-memory journal is also used to temporarily cache
** smaller journals that are not critical for power-loss recovery.
** For example, statement journals that are not too big will be held
** entirely in memory, thus reducing the number of file I/O calls, and
** more importantly, reducing temporary file creation events. If these
** journals become too large for memory, they are spilled to disk. But
** in the common case, they are usually small and no file I/O needs to
** occur.
*/
/* #include "sqliteInt.h" */
/* Forward references to internal structures */
typedef struct MemJournal MemJournal;
typedef struct FilePoint FilePoint;
typedef struct FileChunk FileChunk;
/*
** The rollback journal is composed of a linked list of these structures.
**
** The zChunk array is always at least 8 bytes in size - usually much more.
** Its actual size is stored in the MemJournal.nChunkSize variable.
*/
struct FileChunk {
FileChunk *pNext; /* Next chunk in the journal */
u8 zChunk[8]; /* Content of this chunk */
};
/*
** By default, allocate this many bytes of memory for each FileChunk object.
*/
#define MEMJOURNAL_DFLT_FILECHUNKSIZE 1024
/*
** For chunk size nChunkSize, return the number of bytes that should
** be allocated for each FileChunk structure.
*/
#define fileChunkSize(nChunkSize) (sizeof(FileChunk) + ((nChunkSize)-8))
/*
** An instance of this object serves as a cursor into the rollback journal.
** The cursor can be either for reading or writing.
*/
struct FilePoint {
sqlite3_int64 iOffset; /* Offset from the beginning of the file */
FileChunk *pChunk; /* Specific chunk into which cursor points */
};
/*
** This structure is a subclass of sqlite3_file. Each open memory-journal
** is an instance of this class.
*/
struct MemJournal {
const sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */
int nChunkSize; /* In-memory chunk-size */
int nSpill; /* Bytes of data before flushing */
FileChunk *pFirst; /* Head of in-memory chunk-list */
FilePoint endpoint; /* Pointer to the end of the file */
FilePoint readpoint; /* Pointer to the end of the last xRead() */
int flags; /* xOpen flags */
sqlite3_vfs *pVfs; /* The "real" underlying VFS */
const char *zJournal; /* Name of the journal file */
};
/*
** Read data from the in-memory journal file. This is the implementation
** of the sqlite3_vfs.xRead method.
*/
static int memjrnlRead(
sqlite3_file *pJfd, /* The journal file from which to read */
void *zBuf, /* Put the results here */
int iAmt, /* Number of bytes to read */
sqlite_int64 iOfst /* Begin reading at this offset */
){
MemJournal *p = (MemJournal *)pJfd;
u8 *zOut = zBuf;
int nRead = iAmt;
int iChunkOffset;
FileChunk *pChunk;
if( (iAmt+iOfst)>p->endpoint.iOffset ){
return SQLITE_IOERR_SHORT_READ;
}
assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 );
if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
sqlite3_int64 iOff = 0;
for(pChunk=p->pFirst;
ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst;
pChunk=pChunk->pNext
){
iOff += p->nChunkSize;
}
}else{
pChunk = p->readpoint.pChunk;
assert( pChunk!=0 );
}
iChunkOffset = (int)(iOfst%p->nChunkSize);
do {
int iSpace = p->nChunkSize - iChunkOffset;
int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset));
memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy);
zOut += nCopy;
nRead -= iSpace;
}
}
/*
** Create a new expression term for the column specified by pMatch and
** iColumn. Append this new expression term to the FULL JOIN Match set
** in *ppList. Create a new *ppList if this is the first term in the
** set.
*/
static void extendFJMatch(
Parse *pParse, /* Parsing context */
ExprList **ppList, /* ExprList to extend */
SrcItem *pMatch, /* Source table containing the column */
i16 iColumn /* The column number */
){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pMatch->iCursor;
pNew->iColumn = iColumn;
pNew->y.pTab = pMatch->pSTab;
assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 );
ExprSetProperty(pNew, EP_CanBeNull);
*ppList = sqlite3ExprListAppend(pParse, *ppList, pNew);
}
}
/*
** Return TRUE (non-zero) if zTab is a valid name for the schema table pTab.
*/
static SQLITE_NOINLINE int isValidSchemaTableName(
const char *zTab, /* Name as it appears in the SQL */
Table *pTab, /* The schema table we are trying to match */
const char *zDb /* non-NULL if a database qualifier is present */
){
const char *zLegacy;
assert( pTab!=0 );
assert( pTab->tnum==1 );
if( sqlite3StrNICmp(zTab, "sqlite_", 7)!=0 ) return 0;
zLegacy = pTab->zName;
if( strcmp(zLegacy+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){
if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
return 1;
}
if( zDb==0 ) return 0;
if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
}else{
if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
}
return 0;
}
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
** are made to pExpr:
**
** pExpr->iDb Set the index in db->aDb[] of the database X
** (even if X is implied).
** pExpr->iTable Set to the cursor number for the table obtained
** from pSrcList.
** pExpr->y.pTab Points to the Table structure of X.Y (even if
** X and/or Y are implied.)
** pExpr->iColumn Set to the column number within the table.
** pExpr->op Set to TK_COLUMN.
** pExpr->pLeft Any expression this points to is deleted
** pExpr->pRight Any expression this points to is deleted.
**
** The zDb variable is the name of the database (the "X"). This value may be
** NULL meaning that name is of the form Y.Z or Z. Any available database
** can be used. The zTable variable is the name of the table (the "Y"). This
** value can be NULL if zDb is also NULL. If zTable is NULL it
** means that the form of the name is Z and that columns from any table
** can be used.
**
** If the name cannot be resolved unambiguously, leave an error message
** in pParse and return WRC_Abort. Return WRC_Prune on success.
*/
static int lookupName(
Parse *pParse, /* The parsing context */
const char *zDb, /* Name of the database containing table, or NULL */
const char *zTab, /* Name of table containing column, or NULL */
const Expr *pRight, /* Name of the column. */
NameContext *pNC, /* The name context used to resolve the name */
Expr *pExpr /* Make this EXPR node point to the selected column */
){
int i, j; /* Loop counters */
int cnt = 0; /* Number of matching column names */
int cntTab = 0; /* Number of potential "rowid" matches */
int nSubquery = 0; /* How many levels of subquery */
sqlite3 *db = pParse->db; /* The database connection */
SrcItem *pItem; /* Use for looping over pSrcList items */
SrcItem *pMatch = 0; /* The matching pSrcList item */
NameContext *pTopNC = pNC; /* First namecontext in the list */
Schema *pSchema = 0; /* Schema of the expression */
int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
Table *pTab = 0; /* Table holding the row */
ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */
const char *zCol = pRight->u.zToken;
assert( pNC ); /* the name context cannot be NULL. */
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
assert( zDb==0 || zTab!=0 );
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
/* Initialize the node to no-match */
pExpr->iTable = -1;
ExprSetVVAProperty(pExpr, EP_NoReduce);
/* Translate the schema name in zDb into a pointer to the corresponding
** schema. If not found, pSchema will remain NULL and nothing will match
** resulting in an appropriate error message toward the end of this routine
*/
if( zDb ){
testcase( pNC->ncFlags & NC_PartIdx );
testcase( pNC->ncFlags & NC_IsCheck );
if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){
/* Silently ignore database qualifiers inside CHECK constraints and
** partial indices. Do not raise errors because that might break
** legacy and because it does not hurt anything to just ignore the
if( pGroupBy ){
struct ExprList_item *pItem;
if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
return WRC_Abort;
}
for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
"the GROUP BY clause");
return WRC_Abort;
}
}
}
/* If this is part of a compound SELECT, check that it has the right
** number of expressions in the select list. */
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
sqlite3SelectWrongNumTermsError(pParse, p->pNext);
return WRC_Abort;
}
/* Advance to the next term of the compound
*/
p = p->pPrior;
nCompound++;
}
/* Resolve the ORDER BY on a compound SELECT after all terms of
** the compound have been resolved.
*/
if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
return WRC_Abort;
}
return WRC_Prune;
}
/*
** This routine walks an expression tree and resolves references to
** table columns and result-set columns. At the same time, do error
** checking on function usage and set a flag if any aggregate functions
** are seen.
**
** To resolve table columns references we look for nodes (or subtrees) of the
** form X.Y.Z or Y.Z or just Z where
**
** X: The name of a database. Ex: "main" or "temp" or
** the symbolic name assigned to an ATTACH-ed database.
**
** Y: The name of a table in a FROM clause. Or in a trigger
** one of the special names "old" or "new".
**
** Z: The name of a column in table Y.
**
** The node at the root of the subtree is modified as follows:
**
** Expr.op Changed to TK_COLUMN
** Expr.pTab Points to the Table object for X.Y
** Expr.iColumn The column index in X.Y. -1 for the rowid.
** Expr.iTable The VDBE cursor number for X.Y
**
**
** To resolve result-set references, look for expression nodes of the
** form Z (with no X and Y prefix) where the Z matches the right-hand
** size of an AS clause in the result-set of a SELECT. The Z expression
** is replaced by a copy of the left-hand side of the result-set expression.
** Table-name and function resolution occurs on the substituted expression
** tree. For example, in:
**
** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
**
** The "x" term of the order by is replaced by "a+b" to render:
**
** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
**
** Function calls are checked to make sure that the function is
** defined and that the correct number of arguments are specified.
** If the function is an aggregate function, then the NC_HasAgg flag is
** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
** If an expression contains aggregate functions then the EP_Agg
** property on the expression is set.
**
** An error message is left in pParse if anything is amiss. The number
** if errors is returned.
*/
SQLITE_PRIVATE int sqlite3ResolveExprNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
Expr *pExpr /* The expression to be analyzed. */
){
int savedHasAgg;
Walker w;
if( pExpr==0 ) return SQLITE_OK;
savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
w.xSelectCallback2 = 0;
w.u.pNC = pNC;
#if SQLITE_MAX_EXPR_DEPTH>0
w.pParse->nHeight += pExpr->nHeight;
if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
return SQLITE_ERROR;
}
#endif
assert( pExpr!=0 );
sqlite3WalkExprNN(&w, pExpr);
#if SQLITE_MAX_EXPR_DEPTH>0
w.pParse->nHeight -= pExpr->nHeight;
#endif
assert( EP_Agg==NC_HasAgg );
assert( EP_Win==NC_HasWin );
testcase( pNC->ncFlags & NC_HasAgg );
testcase( pNC->ncFlags & NC_HasWin );
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
pNC->ncFlags |= savedHasAgg;
return pNC->nNcErr>0 || w.pParse->nErr>0;
}
CollSeq *p4;
if( pParse->nErr ) return 0;
if( isCommuted ){
p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft);
}else{
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
}
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
sqlite3VdbeChangeP5(pParse->pVdbe, (u16)p5);
return addr;
}
/*
** Return true if expression pExpr is a vector, or false otherwise.
**
** A vector is defined as any expression that results in two or more
** columns of result. Every TK_VECTOR node is an vector because the
** parser will not generate a TK_VECTOR with fewer than two entries.
** But a TK_SELECT might be either a vector or a scalar. It is only
** considered a vector if it has two or more result columns.
*/
SQLITE_PRIVATE int sqlite3ExprIsVector(const Expr *pExpr){
return sqlite3ExprVectorSize(pExpr)>1;
}
/*
** If the expression passed as the only argument is of type TK_VECTOR
** return the number of expressions in the vector. Or, if the expression
** is a sub-select, return the number of columns in the sub-select. For
** any other type of expression, return 1.
*/
SQLITE_PRIVATE int sqlite3ExprVectorSize(const Expr *pExpr){
u8 op = pExpr->op;
if( op==TK_REGISTER ) op = pExpr->op2;
if( op==TK_VECTOR ){
assert( ExprUseXList(pExpr) );
return pExpr->x.pList->nExpr;
}else if( op==TK_SELECT ){
assert( ExprUseXSelect(pExpr) );
return pExpr->x.pSelect->pEList->nExpr;
}else{
return 1;
}
}
/*
** Return a pointer to a subexpression of pVector that is the i-th
** column of the vector (numbered starting with 0). The caller must
** ensure that i is within range.
**
** If pVector is really a scalar (and "scalar" here includes subqueries
** that return a single column!) then return pVector unmodified.
**
** pVector retains ownership of the returned subexpression.
**
** If the vector is a (SELECT ...) then the expression returned is
** just the expression for the i-th term of the result set, and may
** not be ready for evaluation because the table cursor has not yet
** been positioned.
*/
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
assert( i<sqlite3ExprVectorSize(pVector) || pVector->op==TK_ERROR );
if( sqlite3ExprIsVector(pVector) ){
assert( pVector->op2==0 || pVector->op==TK_REGISTER );
if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){
assert( ExprUseXSelect(pVector) );
return pVector->x.pSelect->pEList->a[i].pExpr;
}else{
assert( ExprUseXList(pVector) );
return pVector->x.pList->a[i].pExpr;
}
}
return pVector;
}
/*
** Compute and return a new Expr object which when passed to
** sqlite3ExprCode() will generate all necessary code to compute
** the iField-th column of the vector expression pVector.
**
** It is ok for pVector to be a scalar (as long as iField==0).
** In that case, this routine works like sqlite3ExprDup().
**
** The caller owns the returned Expr object and is responsible for
** ensuring that the returned value eventually gets freed.
**
** The caller retains ownership of pVector. If pVector is a TK_SELECT,
** then the returned object will reference pVector and so pVector must remain
** valid for the life of the returned object. If pVector is a TK_VECTOR
** or a scalar expression, then it can be deleted as soon as this routine
** returns.
**
** A trick to cause a TK_SELECT pVector to be deleted together with
** the returned Expr object is to attach the pVector to the pRight field
** of the returned TK_SELECT_COLUMN Expr object.
*/
SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
Parse *pParse, /* Parsing context */
Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
int iField, /* Which column of the vector to return */
int nField /* Total number of columns in the vector */
){
Expr *pRet;
if( pVector->op==TK_SELECT ){
assert( ExprUseXSelect(pVector) );
/* The TK_SELECT_COLUMN Expr node:
**
** pLeft: pVector containing TK_SELECT. Not deleted.
** pRight: not used. But recursively deleted.
** iColumn: Index of a column in pVector
** iTable: 0 or the number of columns on the LHS of an assignment
** pLeft->iTable: First in an array of register holding result, or 0
** if the result is not yet computed.
**
** sqlite3ExprDelete() specifically skips the recursive delete of
** pLeft on TK_SELECT_COLUMN nodes. But pRight is followed, so pVector
** can be attached to pRight to cause this node to take ownership of
** pVector. Typically there will be multiple TK_SELECT_COLUMN nodes
**
** The expression list, ID, and source lists return by sqlite3ExprListDup(),
** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
** by subsequent calls to sqlite*ListAppend() routines.
**
** Any tables that the SrcList might point to are not duplicated.
**
** The flags parameter contains a combination of the EXPRDUP_XXX flags.
** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
** truncated version of the usual Expr structure that will be stored as
** part of the in-memory representation of the database schema.
*/
SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, const Expr *p, int flags){
assert( flags==0 || flags==EXPRDUP_REDUCE );
return p ? exprDup(db, p, flags, 0) : 0;
}
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int flags){
ExprList *pNew;
struct ExprList_item *pItem;
const struct ExprList_item *pOldItem;
int i;
Expr *pPriorSelectColOld = 0;
Expr *pPriorSelectColNew = 0;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
if( pNew==0 ) return 0;
pNew->nExpr = p->nExpr;
pNew->nAlloc = p->nAlloc;
pItem = pNew->a;
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
Expr *pNewExpr;
pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
if( pOldExpr
&& pOldExpr->op==TK_SELECT_COLUMN
&& (pNewExpr = pItem->pExpr)!=0
){
if( pNewExpr->pRight ){
pPriorSelectColOld = pOldExpr->pRight;
pPriorSelectColNew = pNewExpr->pRight;
pNewExpr->pLeft = pNewExpr->pRight;
}else{
if( pOldExpr->pLeft!=pPriorSelectColOld ){
pPriorSelectColOld = pOldExpr->pLeft;
pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags);
pNewExpr->pRight = pPriorSelectColNew;
}
pNewExpr->pLeft = pPriorSelectColNew;
}
}
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
pItem->fg = pOldItem->fg;
pItem->u = pOldItem->u;
}
return pNew;
}
/*
** If cursors, triggers, views and subqueries are all omitted from
** the build, then none of the following routines, except for
** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
** called with a NULL argument.
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
|| !defined(SQLITE_OMIT_SUBQUERY)
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
SrcList *pNew;
int i;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, SZ_SRCLIST(p->nSrc) );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; i<p->nSrc; i++){
SrcItem *pNewItem = &pNew->a[i];
const SrcItem *pOldItem = &p->a[i];
Table *pTab;
pNewItem->fg = pOldItem->fg;
if( pOldItem->fg.isSubquery ){
Subquery *pNewSubq = sqlite3DbMallocRaw(db, sizeof(Subquery));
if( pNewSubq==0 ){
assert( db->mallocFailed );
pNewItem->fg.isSubquery = 0;
}else{
memcpy(pNewSubq, pOldItem->u4.pSubq, sizeof(*pNewSubq));
pNewSubq->pSelect = sqlite3SelectDup(db, pNewSubq->pSelect, flags);
if( pNewSubq->pSelect==0 ){
sqlite3DbFree(db, pNewSubq);
pNewSubq = 0;
pNewItem->fg.isSubquery = 0;
}
}
pNewItem->u4.pSubq = pNewSubq;
}else if( pOldItem->fg.fixedSchema ){
pNewItem->u4.pSchema = pOldItem->u4.pSchema;
}else{
pNewItem->u4.zDatabase = sqlite3DbStrDup(db, pOldItem->u4.zDatabase);
}
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
pNewItem->iCursor = pOldItem->iCursor;
if( pNewItem->fg.isIndexedBy ){
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
}else if( pNewItem->fg.isTabFunc ){
pNewItem->u1.pFuncArg =
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
}else{
pNewItem->u1.nRow = pOldItem->u1.nRow;
}
pNewItem->u2 = pOldItem->u2;
if( pNewItem->fg.isCte ){
pNewItem->u2.pCteUse->nUse++;
}
pTab = pNewItem->pSTab = pOldItem->pSTab;
if( pTab ){
pTab->nTabRef++;
}
if( pOldItem->fg.isUsing ){
assert( pNewItem->fg.isUsing );
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
sqlite3WalkExpr(&w, p);
return w.eCode;
}
/*
** Walk an expression tree. Return non-zero if the expression is constant
** and 0 if it involves variables or function calls.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
**
** The pParse parameter may be NULL. But if it is NULL, there is no way
** to determine if function calls are constant or not, and hence all
** function calls will be considered to be non-constant. If pParse is
** not NULL, then a function call might be constant, depending on the
** function and on its parameters.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstant(Parse *pParse, Expr *p){
return exprIsConst(pParse, p, 1);
}
/*
** Walk an expression tree. Return non-zero if
**
** (1) the expression is constant, and
** (2) the expression does originate in the ON or USING clause
** of a LEFT JOIN, and
** (3) the expression does not contain any EP_FixedCol TK_COLUMN
** operands created by the constant propagation optimization.
**
** When this routine returns true, it indicates that the expression
** can be added to the pParse->pConstExpr list and evaluated once when
** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
*/
static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){
return exprIsConst(pParse, p, 2);
}
/*
** This routine examines sub-SELECT statements as an expression is being
** walked as part of sqlite3ExprIsTableConstant(). Sub-SELECTs are considered
** constant as long as they are uncorrelated - meaning that they do not
** contain any terms from outer contexts.
*/
static int exprSelectWalkTableConstant(Walker *pWalker, Select *pSelect){
assert( pSelect!=0 );
assert( pWalker->eCode==3 || pWalker->eCode==0 );
if( (pSelect->selFlags & SF_Correlated)!=0 ){
pWalker->eCode = 0;
return WRC_Abort;
}
return WRC_Prune;
}
/*
** Walk an expression tree. Return non-zero if the expression is constant
** for any single row of the table with cursor iCur. In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
**
** Consider uncorrelated subqueries to be constants if the bAllowSubq
** parameter is true.
*/
static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
Walker w;
w.eCode = 3;
w.pParse = 0;
w.xExprCallback = exprNodeIsConstant;
if( bAllowSubq ){
w.xSelectCallback = exprSelectWalkTableConstant;
}else{
w.xSelectCallback = sqlite3SelectWalkFail;
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
}
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
}
/*
** Check pExpr to see if it is an constraint on the single data source
** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr
** constrains pSrc but does not depend on any other tables or data
** sources anywhere else in the query. Return true (non-zero) if pExpr
** is a constraint on pSrc only.
**
** This is an optimization. False negatives will perhaps cause slower
** queries, but false positives will yield incorrect answers. So when in
** doubt, return 0.
**
** To be an single-source constraint, the following must be true:
**
** (1) pExpr cannot refer to any table other than pSrc->iCursor.
**
** (2a) pExpr cannot use subqueries unless the bAllowSubq parameter is
** true and the subquery is non-correlated
**
** (2b) pExpr cannot use non-deterministic functions.
**
** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
** (Is there some way to relax this constraint?)
**
** (4) If pSrc is the right operand of a LEFT JOIN, then...
** (4a) pExpr must come from an ON clause..
** (4b) and specifically the ON clause associated with the LEFT JOIN.
**
** (5) If pSrc is the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
**
** (6) Either:
**
** (6a) pExpr does not originate in an ON or USING clause, or
**
** (6b) The ON or USING clause from which pExpr is derived is
assert( pTab!=0 );
assert( !IsView(pTab) ); /* FROM clause is not a view */
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
pEList = p->pEList;
assert( pEList!=0 );
/* All SELECT results must be columns. */
for(i=0; i<pEList->nExpr; i++){
Expr *pRes = pEList->a[i].pExpr;
if( pRes->op!=TK_COLUMN ) return 0;
assert( pRes->iTable==pSrc->a[0].iCursor ); /* Not a correlated subquery */
}
return p;
}
#endif /* SQLITE_OMIT_SUBQUERY */
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Generate code that checks the left-most column of index table iCur to see if
** it contains any NULL entries. Cause the register at regHasNull to be set
** to a non-NULL value if iCur contains no NULLs. Cause register regHasNull
** to be set to NULL if iCur contains one or more NULL values.
*/
static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){
int addr1;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull);
addr1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
VdbeComment((v, "first_entry_in(%d)", iCur));
sqlite3VdbeJumpHere(v, addr1);
}
#endif
#ifndef SQLITE_OMIT_SUBQUERY
/*
** The argument is an IN operator with a list (not a subquery) on the
** right-hand side. Return TRUE if that list is constant.
*/
static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){
Expr *pLHS;
int res;
assert( !ExprHasProperty(pIn, EP_xIsSelect) );
pLHS = pIn->pLeft;
pIn->pLeft = 0;
res = sqlite3ExprIsConstant(pParse, pIn);
pIn->pLeft = pLHS;
return res;
}
#endif
/*
** This function is used by the implementation of the IN (...) operator.
** The pX parameter is the expression on the RHS of the IN operator, which
** might be either a list of expressions or a subquery.
**
** The job of this routine is to find or create a b-tree object that can
** be used either to test for membership in the RHS set or to iterate through
** all members of the RHS set, skipping duplicates.
**
** A cursor is opened on the b-tree object that is the RHS of the IN operator
** and the *piTab parameter is set to the index of that cursor.
**
** The returned value of this function indicates the b-tree type, as follows:
**
** IN_INDEX_ROWID - The cursor was opened on a database table.
** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
** IN_INDEX_EPH - The cursor was opened on a specially created and
** populated ephemeral table.
** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be
** implemented as a sequence of comparisons.
**
** An existing b-tree might be used if the RHS expression pX is a simple
** subquery such as:
**
** SELECT <column1>, <column2>... FROM <table>
**
** If the RHS of the IN operator is a list or a more complex subquery, then
** an ephemeral table might need to be generated from the RHS and then
** pX->iTable made to point to the ephemeral table instead of an
** existing table. In this case, the creation and initialization of the
** ephemeral table might be put inside of a subroutine, the EP_Subrtn flag
** will be set on pX and the pX->y.sub fields will be set to show where
** the subroutine is coded.
**
** The inFlags parameter must contain, at a minimum, one of the bits
** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains
** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast
** membership test. When the IN_INDEX_LOOP bit is set, the IN index will
** be used to loop over all values of the RHS of the IN operator.
**
** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
** through the set members) then the b-tree must not contain duplicates.
** An ephemeral table will be created unless the selected columns are guaranteed
** to be unique - either because it is an INTEGER PRIMARY KEY or due to
** a UNIQUE constraint or index.
**
** When IN_INDEX_MEMBERSHIP is used (and the b-tree will be used
** for fast set membership tests) then an ephemeral table must
** be used unless <columns> is a single INTEGER PRIMARY KEY column or an
** index can be found with the specified <columns> as its left-most.
**
** If the IN_INDEX_NOOP_OK and IN_INDEX_MEMBERSHIP are both set and
** if the RHS of the IN operator is a list (not a subquery) then this
** routine might decide that creating an ephemeral b-tree for membership
** testing is too expensive and return IN_INDEX_NOOP. In that case, the
** calling routine should implement the IN operator using a sequence
** of Eq or Ne comparison operations.
**
** When the b-tree is being used for membership tests, the calling function
** might need to know whether or not the RHS side of the IN operator
** contains a NULL. If prRhsHasNull is not a NULL pointer and
** if there is any chance that the (...) might contain a NULL value at
** runtime, then a register is allocated and the register number written
** to *prRhsHasNull. If there is no chance that the (...) contains a
** NULL value, then *prRhsHasNull is left unchanged.
**
** If a register is allocated and its location stored in *prRhsHasNull, then
** the value in that register will be NULL if the b-tree contains one or more
** NULL values, and it will be some non-NULL value if the b-tree contains no
** NULL values.
**
** If the aiMap parameter is not NULL, it must point to an array containing
** one element for each column returned by the SELECT statement on the RHS
** of the IN(...) operator. The i'th entry of the array is populated with the
** offset of the index column that matches the i'th column returned by the
** SELECT. For example, if the expression and selected index are:
**
** (?,?,?) IN (SELECT a, b, c FROM t1)
** CREATE INDEX i1 ON t1(b, c, a);
int j;
for(j=0; j<nExpr; j++){
if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue;
assert( pIdx->azColl[j] );
if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){
continue;
}
break;
}
if( j==nExpr ) break;
mCol = MASKBIT(j);
if( mCol & colUsed ) break; /* Each column used only once */
colUsed |= mCol;
if( aiMap ) aiMap[i] = j;
}
assert( nExpr>0 && nExpr<BMS );
assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) );
if( colUsed==(MASKBIT(nExpr)-1) ){
/* If we reach this point, that means the index pIdx is usable */
int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
ExplainQueryPlan((pParse, 0,
"USING INDEX %s FOR IN-OPERATOR",pIdx->zName));
sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "%s", pIdx->zName));
assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
if( prRhsHasNull ){
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
i64 mask = (1<<nExpr)-1;
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed,
iTab, 0, 0, (u8*)&mask, P4_INT64);
#endif
*prRhsHasNull = ++pParse->nMem;
if( nExpr==1 ){
sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull);
}
}
sqlite3VdbeJumpHere(v, iAddr);
}
} /* End loop over indexes */
} /* End if( affinity_ok ) */
} /* End if not an rowid index */
} /* End attempt to optimize using an index */
/* If no preexisting index is available for the IN clause
** and IN_INDEX_NOOP is an allowed reply
** and the RHS of the IN operator is a list, not a subquery
** and the RHS is not constant or has two or fewer terms,
** then it is not worth creating an ephemeral table to evaluate
** the IN operator so return IN_INDEX_NOOP.
*/
if( eType==0
&& (inFlags & IN_INDEX_NOOP_OK)
&& ExprUseXList(pX)
&& (!sqlite3InRhsIsConstant(pParse,pX) || pX->x.pList->nExpr<=2)
){
pParse->nTab--; /* Back out the allocation of the unused cursor */
iTab = -1; /* Cursor is not allocated */
eType = IN_INDEX_NOOP;
}
if( eType==0 ){
/* Could not find an existing table or index to use as the RHS b-tree.
** We will have to generate an ephemeral table to do the job.
*/
u32 savedNQueryLoop = pParse->nQueryLoop;
int rMayHaveNull = 0;
eType = IN_INDEX_EPH;
if( inFlags & IN_INDEX_LOOP ){
pParse->nQueryLoop = 0;
}else if( prRhsHasNull ){
*prRhsHasNull = rMayHaveNull = ++pParse->nMem;
}
assert( pX->op==TK_IN );
sqlite3CodeRhsOfIN(pParse, pX, iTab);
if( rMayHaveNull ){
sqlite3SetHasNullFlag(v, iTab, rMayHaveNull);
}
pParse->nQueryLoop = savedNQueryLoop;
}
if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){
int i, n;
n = sqlite3ExprVectorSize(pX->pLeft);
for(i=0; i<n; i++) aiMap[i] = i;
}
*piTab = iTab;
return eType;
}
#endif
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Argument pExpr is an (?, ?...) IN(...) expression. This
** function allocates and returns a nul-terminated string containing
** the affinities to be used for each column of the comparison.
**
** It is the responsibility of the caller to ensure that the returned
** string is eventually freed using sqlite3DbFree().
*/
static char *exprINAffinity(Parse *pParse, const Expr *pExpr){
Expr *pLeft = pExpr->pLeft;
int nVal = sqlite3ExprVectorSize(pLeft);
Select *pSelect = ExprUseXSelect(pExpr) ? pExpr->x.pSelect : 0;
char *zRet;
assert( pExpr->op==TK_IN );
zRet = sqlite3DbMallocRaw(pParse->db, 1+(i64)nVal);
if( zRet ){
int i;
for(i=0; i<nVal; i++){
Expr *pA = sqlite3VectorFieldSubexpr(pLeft, i);
char a = sqlite3ExprAffinity(pA);
if( pSelect ){
zRet[i] = sqlite3CompareAffinity(pSelect->pEList->a[i].pExpr, a);
}else{
zRet[i] = a;
}else
#endif
{
sqlite3ErrorMsg(pParse, "row value misused");
}
}
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Scan all previously generated bytecode looking for an OP_BeginSubrtn
** that is compatible with pExpr. If found, add the y.sub values
** to pExpr and return true. If not found, return false.
*/
static int findCompatibleInRhsSubrtn(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* IN operator with RHS that we want to reuse */
SubrtnSig *pNewSig /* Signature for the IN operator */
){
VdbeOp *pOp, *pEnd;
SubrtnSig *pSig;
Vdbe *v;
if( pNewSig==0 ) return 0;
if( (pParse->mSubrtnSig & (1<<(pNewSig->selId&7)))==0 ) return 0;
assert( pExpr->op==TK_IN );
assert( !ExprUseYSub(pExpr) );
assert( ExprUseXSelect(pExpr) );
assert( pExpr->x.pSelect!=0 );
assert( (pExpr->x.pSelect->selFlags & SF_All)==0 );
v = pParse->pVdbe;
assert( v!=0 );
pOp = sqlite3VdbeGetOp(v, 1);
pEnd = sqlite3VdbeGetLastOp(v);
for(; pOp<pEnd; pOp++){
if( pOp->p4type!=P4_SUBRTNSIG ) continue;
assert( pOp->opcode==OP_BeginSubrtn );
pSig = pOp->p4.pSubrtnSig;
assert( pSig!=0 );
if( !pSig->bComplete ) continue;
if( pNewSig->selId!=pSig->selId ) continue;
if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue;
pExpr->y.sub.iAddr = pSig->iAddr;
pExpr->y.sub.regReturn = pSig->regReturn;
pExpr->iTable = pSig->iTable;
ExprSetProperty(pExpr, EP_Subrtn);
return 1;
}
return 0;
}
#endif /* SQLITE_OMIT_SUBQUERY */
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Generate code that will construct an ephemeral table containing all terms
** in the RHS of an IN operator. The IN operator can be in either of two
** forms:
**
** x IN (4,5,11) -- IN operator with list on right-hand side
** x IN (SELECT a FROM b) -- IN operator with subquery on the right
**
** The pExpr parameter is the IN operator. The cursor number for the
** constructed ephemeral table is returned. The first time the ephemeral
** table is computed, the cursor number is also stored in pExpr->iTable,
** however the cursor number returned might not be the same, as it might
** have been duplicated using OP_OpenDup.
**
** If the LHS expression ("x" in the examples) is a column value, or
** the SELECT statement returns a column value, then the affinity of that
** column is used to build the index keys. If both 'x' and the
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
** is used.
*/
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The IN operator */
int iTab /* Use this cursor number */
){
int addrOnce = 0; /* Address of the OP_Once instruction at top */
int addr; /* Address of OP_OpenEphemeral instruction */
Expr *pLeft; /* the LHS of the IN operator */
KeyInfo *pKeyInfo = 0; /* Key information */
int nVal; /* Size of vector pLeft */
Vdbe *v; /* The prepared statement under construction */
SubrtnSig *pSig = 0; /* Signature for this subroutine */
v = pParse->pVdbe;
assert( v!=0 );
/* The evaluation of the IN must be repeated every time it
** is encountered if any of the following is true:
**
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * We are inside a trigger
**
** If all of the above are false, then we can compute the RHS just once
** and reuse it many names.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
/* Reuse of the RHS is allowed
**
** Compute a signature for the RHS of the IN operator to facility
** finding and reusing prior instances of the same IN operator.
*/
assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 );
if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){
pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0]));
if( pSig ){
pSig->selId = pExpr->x.pSelect->selId;
pSig->zAff = exprINAffinity(pParse, pExpr);
}
}
/* Check to see if there is a prior materialization of the RHS of
** this IN operator. If there is, then make use of that prior
** materialization rather than recomputing it.
*/
if( ExprHasProperty(pExpr, EP_Subrtn)
|| findCompatibleInRhsSubrtn(pParse, pExpr, pSig)
){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
pExpr->x.pSelect->selId));
}
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr);
assert( iTab!=pExpr->iTable );
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
if( pSig ){
sqlite3DbFree(pParse->db, pSig->zAff);
sqlite3DbFree(pParse->db, pSig);
}
return;
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Generate code for an IN expression.
**
** x IN (SELECT ...)
** x IN (value, value, ...)
**
** The left-hand side (LHS) is a scalar or vector expression. The
** right-hand side (RHS) is an array of zero or more scalar values, or a
** subquery. If the RHS is a subquery, the number of result columns must
** match the number of columns in the vector on the LHS. If the RHS is
** a list of values, the LHS must be a scalar.
**
** The IN operator is true if the LHS value is contained within the RHS.
** The result is false if the LHS is definitely not in the RHS. The
** result is NULL if the presence of the LHS in the RHS cannot be
** determined due to NULLs.
**
** This routine generates code that jumps to destIfFalse if the LHS is not
** contained within the RHS. If due to NULLs we cannot determine if the LHS
** is contained in the RHS then jump to destIfNull. If the LHS is contained
** within the RHS then fall through.
**
** See the separate in-operator.md documentation file in the canonical
** SQLite source tree for additional information.
*/
static void sqlite3ExprCodeIN(
Parse *pParse, /* Parsing and code generating context */
Expr *pExpr, /* The IN expression */
int destIfFalse, /* Jump here if LHS is not contained in the RHS */
int destIfNull /* Jump here if the results are unknown due to NULLs */
){
int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
int eType; /* Type of the RHS */
int rLhs; /* Register(s) holding the LHS values */
Vdbe *v; /* Statement under construction */
int *aiMap = 0; /* Map from vector field to index column */
char *zAff = 0; /* Affinity string for comparisons */
int nVector; /* Size of vectors for this IN operator */
int iDummy; /* Dummy parameter to exprCodeVector() */
Expr *pLeft; /* The LHS of the IN operator */
int i; /* loop counter */
int destStep2; /* Where to jump when NULLs seen in step 2 */
int destStep6 = 0; /* Start of code for Step 6 */
int addrTruthOp; /* Address of opcode that determines the IN is true */
int destNotNull; /* Jump here if a comparison is not true in step 6 */
int addrTop; /* Top of the step-6 loop */
int iTab = 0; /* Index to use */
u8 okConstFactor = pParse->okConstFactor;
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
pLeft = pExpr->pLeft;
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
zAff = exprINAffinity(pParse, pExpr);
nVector = sqlite3ExprVectorSize(pExpr->pLeft);
aiMap = (int*)sqlite3DbMallocZero(pParse->db, nVector*sizeof(int));
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
/* Attempt to compute the RHS. After this step, if anything other than
** IN_INDEX_NOOP is returned, the table opened with cursor iTab
** contains the values that make up the RHS. If IN_INDEX_NOOP is returned,
** the RHS has not yet been coded. */
v = pParse->pVdbe;
assert( v!=0 ); /* OOM detected prior to this routine */
VdbeNoopComment((v, "begin IN expr"));
eType = sqlite3FindInIndex(pParse, pExpr,
IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
destIfFalse==destIfNull ? 0 : &rRhsHasNull,
aiMap, &iTab);
assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH
|| eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC
);
#ifdef SQLITE_DEBUG
/* Confirm that aiMap[] contains nVector integer values between 0 and
** nVector-1. */
for(i=0; i<nVector; i++){
int j, cnt;
for(cnt=j=0; j<nVector; j++) if( aiMap[j]==i ) cnt++;
assert( cnt==1 );
}
#endif
/* Code the LHS, the <expr> from "<expr> IN (...)". If the LHS is a
** vector, then it is stored in an array of nVector registers starting
** at r1.
**
** sqlite3FindInIndex() might have reordered the fields of the LHS vector
** so that the fields are in the same order as an existing index. The
** aiMap[] array contains a mapping from the original LHS field order to
** the field order that matches the RHS index.
**
** Avoid factoring the LHS of the IN(...) expression out of the loop,
** even if it is constant, as OP_Affinity may be used on the register
** by code generated below. */
assert( pParse->okConstFactor==okConstFactor );
pParse->okConstFactor = 0;
rLhs = exprCodeVector(pParse, pLeft, &iDummy);
pParse->okConstFactor = okConstFactor;
/* If sqlite3FindInIndex() did not find or create an index that is
** suitable for evaluating the IN operator, then evaluate using a
** sequence of comparisons.
**
** This is step (1) in the in-operator.md optimized algorithm.
*/
if( eType==IN_INDEX_NOOP ){
ExprList *pList;
CollSeq *pColl;
int labelOk = sqlite3VdbeMakeLabel(pParse);
int r2, regToFree;
int regCkNull = 0;
int ii;
assert( nVector==1 );
assert( ExprUseXList(pExpr) );
pList = pExpr->x.pList;
pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
if( destIfNull!=destIfFalse ){
regCkNull = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
Parse *pParse, /* The parsing context */
Index *pIdx, /* The index whose column is to be loaded */
int iTabCur, /* Cursor pointing to a table row */
int iIdxCol, /* The column of the index to be loaded */
int regOut /* Store the index column value in this register */
){
i16 iTabCol = pIdx->aiColumn[iIdxCol];
if( iTabCol==XN_EXPR ){
assert( pIdx->aColExpr );
assert( pIdx->aColExpr->nExpr>iIdxCol );
pParse->iSelfTab = iTabCur + 1;
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
pParse->iSelfTab = 0;
}else{
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
iTabCol, regOut);
}
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/*
** Generate code that will compute the value of generated column pCol
** and store the result in register regOut
*/
SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(
Parse *pParse, /* Parsing context */
Table *pTab, /* Table containing the generated column */
Column *pCol, /* The generated column */
int regOut /* Put the result in this register */
){
int iAddr;
Vdbe *v = pParse->pVdbe;
int nErr = pParse->nErr;
assert( v!=0 );
assert( pParse->iSelfTab!=0 );
if( pParse->iSelfTab>0 ){
iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut);
}else{
iAddr = 0;
}
sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut);
if( (pCol->colFlags & COLFLAG_VIRTUAL)!=0
&& (pTab->tabFlags & TF_Strict)!=0
){
int p3 = 2+(int)(pCol - pTab->aCol);
sqlite3VdbeAddOp4(v, OP_TypeCheck, regOut, 1, p3, (char*)pTab, P4_TABLE);
}else if( pCol->affinity>=SQLITE_AFF_TEXT ){
sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
}
if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
if( pParse->nErr>nErr ) pParse->db->errByteOffset = -1;
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
/*
** Generate code to extract the value of the iCol-th column of a table.
*/
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
Vdbe *v, /* Parsing context */
Table *pTab, /* The table containing the value */
int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */
int iCol, /* Index of the column to extract */
int regOut /* Extract the value into this register */
){
Column *pCol;
assert( v!=0 );
assert( pTab!=0 );
assert( iCol!=XN_EXPR );
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
VdbeComment((v, "%s.rowid", pTab->zName));
}else{
int op;
int x;
if( IsVirtual(pTab) ){
op = OP_VColumn;
x = iCol;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
Parse *pParse = sqlite3VdbeParser(v);
if( pCol->colFlags & COLFLAG_BUSY ){
sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
pCol->zCnName);
}else{
int savedSelfTab = pParse->iSelfTab;
pCol->colFlags |= COLFLAG_BUSY;
pParse->iSelfTab = iTabCur+1;
sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, regOut);
pParse->iSelfTab = savedSelfTab;
pCol->colFlags &= ~COLFLAG_BUSY;
}
return;
#endif
}else if( !HasRowid(pTab) ){
testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) );
x = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
op = OP_Column;
}else{
x = sqlite3TableColumnToStorage(pTab,iCol);
testcase( x!=iCol );
op = OP_Column;
}
sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
sqlite3ColumnDefault(v, pTab, iCol, regOut);
}
}
/*
** Generate code that will extract the iColumn-th column from
** table pTab and store the column value in register iReg.
**
** 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.
*/
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 */
u8 p5 /* P5 value for OP_Column + FLAGS */
){
assert( pParse->pVdbe!=0 );
assert( (p5 & (OPFLAG_NOCHNG|OPFLAG_TYPEOFARG|OPFLAG_LENGTHARG))==p5 );
assert( IsVirtual(pTab) || (p5 & OPFLAG_NOCHNG)==0 );
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg);
if( p5 ){
VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe);
if( pOp->opcode==OP_Column ) pOp->p5 = p5;
if( pOp->opcode==OP_VColumn ) pOp->p5 = (p5 & OPFLAG_NOCHNG);
}
return iReg;
}
/*
** Generate code to move content from registers iFrom...iFrom+nReg-1
** over to iTo..iTo+nReg-1.
*/
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
}
/*
** Convert a scalar expression node to a TK_REGISTER referencing
** register iReg. The caller must ensure that iReg already contains
** the correct value for the expression.
*/
SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
if( NEVER(p==0) ) return;
if( p->op==TK_REGISTER ){
assert( p->iTable==iReg );
}else{
p->op2 = p->op;
p->op = TK_REGISTER;
p->iTable = iReg;
ExprClearProperty(p, EP_Skip);
}
}
/*
** Evaluate an expression (either a vector or a scalar expression) and store
** the result in contiguous temporary registers. Return the index of
** the first register used to store the result.
**
** If the returned result register is a temporary scalar, then also write
** that register number into *piFreeable. If the returned result register
** is not a temporary or if the expression is a vector set *piFreeable
** to 0.
*/
static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
int iResult;
int nResult = sqlite3ExprVectorSize(p);
if( nResult==1 ){
iResult = sqlite3ExprCodeTemp(pParse, p, piFreeable);
}else{
*piFreeable = 0;
if( p->op==TK_SELECT ){
#if SQLITE_OMIT_SUBQUERY
&& IsVirtual(pRight->y.pTab))
){
return WRC_Prune;
}
/* no break */ deliberate_fall_through
}
default:
return WRC_Continue;
}
}
/*
** Return true (non-zero) if expression p can only be true if at least
** one column of table iTab is non-null. In other words, return true
** if expression p will always be NULL or false if every column of iTab
** is NULL.
**
** False negatives are acceptable. In other words, it is ok to return
** zero even if expression p will never be true of every column of iTab
** is NULL. A false negative is merely a missed optimization opportunity.
**
** False positives are not allowed, however. A false positive may result
** in an incorrect answer.
**
** Terms of p that are marked with EP_OuterON (and hence that come from
** the ON or USING clauses of OUTER JOINS) are excluded from the analysis.
**
** This routine is used to check if a LEFT JOIN can be converted into
** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE
** clause requires that some column of the right table of the LEFT JOIN
** be non-NULL, then the LEFT JOIN can be safely converted into an
** ordinary join.
*/
SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab, int isRJ){
Walker w;
p = sqlite3ExprSkipCollateAndLikely(p);
if( p==0 ) return 0;
if( p->op==TK_NOTNULL ){
p = p->pLeft;
}else{
while( p->op==TK_AND ){
if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab, isRJ) ) return 1;
p = p->pRight;
}
}
w.xExprCallback = impliesNotNullRow;
w.xSelectCallback = 0;
w.xSelectCallback2 = 0;
w.eCode = 0;
w.mWFlags = isRJ!=0;
w.u.iCur = iTab;
sqlite3WalkExpr(&w, p);
return w.eCode;
}
/*
** An instance of the following structure is used by the tree walker
** to determine if an expression can be evaluated by reference to the
** index only, without having to do a search for the corresponding
** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur
** is the cursor for the table.
*/
struct IdxCover {
Index *pIdx; /* The index to be tested for coverage */
int iCur; /* Cursor number for the table corresponding to the index */
};
/*
** Check to see if there are references to columns in table
** pWalker->u.pIdxCover->iCur can be satisfied using the index
** pWalker->u.pIdxCover->pIdx.
*/
static int exprIdxCover(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pWalker->u.pIdxCover->iCur
&& sqlite3TableColumnToIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
){
pWalker->eCode = 1;
return WRC_Abort;
}
return WRC_Continue;
}
/*
** Determine if an index pIdx on table with cursor iCur contains will
** the expression pExpr. Return true if the index does cover the
** expression and false if the pExpr expression references table columns
** that are not found in the index pIdx.
**
** An index covering an expression means that the expression can be
** evaluated using only the index and without having to lookup the
** corresponding table entry.
*/
SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(
Expr *pExpr, /* The index to be tested */
int iCur, /* The cursor number for the corresponding table */
Index *pIdx /* The index that might be used for coverage */
){
Walker w;
struct IdxCover xcov;
memset(&w, 0, sizeof(w));
xcov.iCur = iCur;
xcov.pIdx = pIdx;
w.xExprCallback = exprIdxCover;
w.u.pIdxCover = &xcov;
sqlite3WalkExpr(&w, pExpr);
return !w.eCode;
}
/* Structure used to pass information throughout the Walker in order to
** implement sqlite3ReferencesSrcList().
*/
struct RefSrcList {
sqlite3 *db; /* Database connection used for sqlite3DbRealloc() */
SrcList *pRef; /* Looking for references to these tables */
i64 nExclude; /* Number of tables to exclude from the search */
int *aiExclude; /* Cursor IDs for tables to exclude from the search */
};
/*
** Walker SELECT callbacks for sqlite3ReferencesSrcList().
**
** When entering a new subquery on the pExpr argument, add all FROM clause
** entries for that subquery to the exclude list.
**
** When leaving the subquery, remove those entries from the exclude list.
*/
static int selectRefEnter(Walker *pWalker, Select *pSelect){
struct RefSrcList *p = pWalker->u.pRefSrcList;
SrcList *pSrc = pSelect->pSrc;
i64 i, j;
int *piNew;
if( pSrc->nSrc==0 ) return WRC_Continue;
j = p->nExclude;
p->nExclude += pSrc->nSrc;
piNew = sqlite3DbRealloc(p->db, p->aiExclude, p->nExclude*sizeof(int));
if( piNew==0 ){
p->nExclude = 0;
return WRC_Abort;
}else{
p->aiExclude = piNew;
}
for(i=0; i<pSrc->nSrc; i++, j++){
p->aiExclude[j] = pSrc->a[i].iCursor;
}
return WRC_Continue;
}
static void selectRefLeave(Walker *pWalker, Select *pSelect){
struct RefSrcList *p = pWalker->u.pRefSrcList;
SrcList *pSrc = pSelect->pSrc;
if( p->nExclude ){
assert( p->nExclude>=pSrc->nSrc );
p->nExclude -= pSrc->nSrc;
}
}
** of the INTEGER PRIMARY KEY. The sample column is a blob which is the
** binary encoding of a key from the index. The nEq column is a
** list of integers. The first integer is the approximate number
** of entries in the index whose left-most column exactly matches
** the left-most column of the sample. The second integer in nEq
** is the approximate number of entries in the index where the
** first two columns match the first two columns of the sample.
** And so forth. nLt is another list of integers that show the approximate
** number of entries that are strictly less than the sample. The first
** integer in nLt contains the number of entries in the index where the
** left-most column is less than the left-most column of the sample.
** The K-th integer in the nLt entry is the number of index entries
** where the first K columns are less than the first K columns of the
** sample. The nDLt column is like nLt except that it contains the
** number of distinct entries in the index that are less than the
** sample.
**
** There can be an arbitrary number of sqlite_stat4 entries per index.
** The ANALYZE command will typically generate sqlite_stat4 tables
** that contain between 10 and 40 samples which are distributed across
** the key space, though not uniformly, and which include samples with
** large nEq values.
**
** Format for sqlite_stat3 redux:
**
** The sqlite_stat3 table is like sqlite_stat4 except that it only
** looks at the left-most column of the index. The sqlite_stat3.sample
** column contains the actual value of the left-most column instead
** of a blob encoding of the complete index key as is found in
** sqlite_stat4.sample. The nEq, nLt, and nDLt entries of sqlite_stat3
** all contain just a single integer which is the same as the first
** integer in the equivalent columns in sqlite_stat4.
*/
#ifndef SQLITE_OMIT_ANALYZE
/* #include "sqliteInt.h" */
#if defined(SQLITE_ENABLE_STAT4)
# define IsStat4 1
#else
# define IsStat4 0
# undef SQLITE_STAT4_SAMPLES
# define SQLITE_STAT4_SAMPLES 1
#endif
/*
** This routine generates code that opens the sqlite_statN tables.
** The sqlite_stat1 table is always relevant. sqlite_stat2 is now
** obsolete. sqlite_stat3 and sqlite_stat4 are only opened when
** appropriate compile-time options are provided.
**
** If the sqlite_statN tables do not previously exist, it is created.
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
** the sqlite_statN tables associated with the named table are deleted.
** If zWhere==0, then code is generated to delete all stat table entries.
*/
static void openStatTable(
Parse *pParse, /* Parsing context */
int iDb, /* The database we are looking in */
int iStatCur, /* Open the sqlite_stat1 table on this cursor */
const char *zWhere, /* Delete entries for this table or index */
const char *zWhereType /* Either "tbl" or "idx" */
){
static const struct {
const char *zName;
const char *zCols;
} aTable[] = {
{ "sqlite_stat1", "tbl,idx,stat" },
#if defined(SQLITE_ENABLE_STAT4)
{ "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
#else
{ "sqlite_stat4", 0 },
#endif
{ "sqlite_stat3", 0 },
};
int i;
sqlite3 *db = pParse->db;
Db *pDb;
Vdbe *v = sqlite3GetVdbe(pParse);
u32 aRoot[ArraySize(aTable)];
u8 aCreateTbl[ArraySize(aTable)];
#ifdef SQLITE_ENABLE_STAT4
const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1;
#else
const int nToOpen = 1;
#endif
if( v==0 ) return;
assert( sqlite3BtreeHoldsAllMutexes(db) );
assert( sqlite3VdbeDb(v)==db );
pDb = &db->aDb[iDb];
/* Create new statistic tables if they do not exist, or clear them
** if they do already exist.
*/
for(i=0; i<ArraySize(aTable); i++){
const char *zTab = aTable[i].zName;
Table *pStat;
aCreateTbl[i] = 0;
if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
if( i<nToOpen ){
/* The sqlite_statN table does not exist. Create it. Note that a
** side-effect of the CREATE TABLE statement is to leave the rootpage
** of the new table in register pParse->regRoot. This is important
** because the OpenWrite opcode below will be needing it. */
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
);
assert( pParse->isCreate || pParse->nErr );
aRoot[i] = (u32)pParse->u1.cr.regRoot;
aCreateTbl[i] = OPFLAG_P2ISREG;
}
}else{
/* The table already exists. If zWhere is not NULL, delete all entries
** associated with the table zWhere. If zWhere is NULL, delete the
** entire contents of the table. */
aRoot[i] = pStat->tnum;
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
if( zWhere ){
sqlite3NestedParse(pParse,
static const FuncDef statGetFuncdef = {
1+IsStat4, /* nArg */
SQLITE_UTF8, /* funcFlags */
0, /* pUserData */
0, /* pNext */
statGet, /* xSFunc */
0, /* xFinalize */
0, 0, /* xValue, xInverse */
"stat_get", /* zName */
{0}
};
static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){
#ifdef SQLITE_ENABLE_STAT4
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat+1);
#elif SQLITE_DEBUG
assert( iParam==STAT_GET_STAT1 );
#else
UNUSED_PARAMETER( iParam );
#endif
assert( regOut!=regStat && regOut!=regStat+1 );
sqlite3VdbeAddFunctionCall(pParse, 0, regStat, regOut, 1+IsStat4,
&statGetFuncdef, 0);
}
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
/* Add a comment to the most recent VDBE opcode that is the name
** of the k-th column of the pIdx index.
*/
static void analyzeVdbeCommentIndexWithColumnName(
Vdbe *v, /* Prepared statement under construction */
Index *pIdx, /* Index whose column is being loaded */
int k /* Which column index */
){
int i; /* Index of column in the table */
assert( k>=0 && k<pIdx->nColumn );
i = pIdx->aiColumn[k];
if( NEVER(i==XN_ROWID) ){
VdbeComment((v,"%s.rowid",pIdx->zName));
}else if( i==XN_EXPR ){
assert( pIdx->bHasExpr );
VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
}else{
VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName));
}
}
#else
# define analyzeVdbeCommentIndexWithColumnName(a,b,c)
#endif /* SQLITE_DEBUG */
/*
** Generate code to do an analysis of all indices associated with
** a single table.
*/
static void analyzeOneTable(
Parse *pParse, /* Parser context */
Table *pTab, /* Table whose indices are to be analyzed */
Index *pOnlyIdx, /* If not NULL, only analyze this one index */
int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */
int iMem, /* Available memory locations begin here */
int iTab /* Next available cursor */
){
sqlite3 *db = pParse->db; /* Database handle */
Index *pIdx; /* An index to being analyzed */
int iIdxCur; /* Cursor open on index being analyzed */
int iTabCur; /* Table cursor */
Vdbe *v; /* The virtual machine being built up */
int i; /* Loop counter */
int jZeroRows = -1; /* Jump from here if number of rows is zero */
int iDb; /* Index of database containing pTab */
u8 needTableCnt = 1; /* True to count the table */
int regNewRowid = iMem++; /* Rowid for the inserted record */
int regStat = iMem++; /* Register to hold StatAccum object */
int regChng = iMem++; /* Index of changed index field */
int regRowid = iMem++; /* Rowid argument passed to stat_push() */
int regTemp = iMem++; /* Temporary use register */
int regTemp2 = iMem++; /* Second temporary use register */
int regTabname = iMem++; /* Register containing table name */
int regIdxname = iMem++; /* Register containing index name */
int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
int regPrev = iMem; /* MUST BE LAST (see below) */
#ifdef SQLITE_ENABLE_STAT4
int doOnce = 1; /* Flag for a one-time computation */
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
Table *pStat1 = 0;
#endif
sqlite3TouchRegister(pParse, iMem);
assert( sqlite3NoTempsInRange(pParse, regNewRowid, iMem) );
v = sqlite3GetVdbe(pParse);
if( v==0 || NEVER(pTab==0) ){
return;
}
if( !IsOrdinaryTable(pTab) ){
/* Do not gather statistics on views or virtual tables */
return;
}
if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){
/* Do not gather statistics on system tables */
return;
}
assert( sqlite3BtreeHoldsAllMutexes(db) );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 );
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
db->aDb[iDb].zDbSName ) ){
return;
}
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
if( db->xPreUpdateCallback ){
pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13);
if( pStat1==0 ) return;
pStat1->zName = (char*)&pStat1[1];
memcpy(pStat1->zName, "sqlite_stat1", 13);
pStat1->nCol = 3;
pStat1->iPKey = -1;
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNAMIC);
}
#endif
/* Establish a read-lock on the table at the shared-cache level.
** Open a read-only cursor on the table. Also allocate a cursor number
** to use for scanning indexes (iIdxCur). No index cursor is opened at
** this time though. */
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
iTabCur = iTab++;
iIdxCur = iTab++;
pParse->nTab = MAX(pParse->nTab, iTab);
sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
sqlite3VdbeLoadString(v, regTabname, pTab->zName);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int nCol; /* Number of columns in pIdx. "N" */
int addrGotoEnd; /* Address of "OP_Rewind iIdxCur" */
int addrNextRow; /* Address of "next_row:" */
const char *zIdxName; /* Name of the index */
int nColTest; /* Number of columns to test for changes */
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIdx) ){
nCol = pIdx->nKeyCol;
zIdxName = pTab->zName;
nColTest = nCol - 1;
}else{
nCol = pIdx->nColumn;
zIdxName = pIdx->zName;
nColTest = pIdx->uniqNotNull ? pIdx->nKeyCol-1 : nCol-1;
}
/* Populate the register containing the index name. */
sqlite3VdbeLoadString(v, regIdxname, zIdxName);
VdbeComment((v, "Analysis for %s.%s", pTab->zName, zIdxName));
/*
** Pseudo-code for loop that calls stat_push():
**
** regChng = 0
** Rewind csr
** if eof(csr){
** stat_init() with count = 0;
** goto end_of_scan;
** }
** count()
** stat_init()
** goto chng_addr_0;
**
** next_row:
** regChng = 0
** if( idx(0) != regPrev(0) ) goto chng_addr_0
** regChng = 1
** if( idx(1) != regPrev(1) ) goto chng_addr_1
** ...
** regChng = N
** goto chng_addr_N
**
** chng_addr_0:
** regPrev(0) = idx(0)
** chng_addr_1:
** regPrev(1) = idx(1)
** ...
**
** endDistinctTest:
** regRowid = idx(rowid)
** stat_push(P, regChng, regRowid)
** Next csr
** if !eof(csr) goto next_row;
**
** end_of_scan:
*/
/* Make sure there are enough memory cells allocated to accommodate
** the regPrev array and a trailing rowid (the rowid slot is required
** when building a record to insert into the sample column of
** the sqlite_stat4 table. */
sqlite3TouchRegister(pParse, regPrev+nColTest);
/* Open a read-only cursor on the index being analyzed. */
assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "%s", pIdx->zName));
/* Implementation of the following:
**
** regChng = 0
** Rewind csr
** if eof(csr){
** stat_init() with count = 0;
** goto end_of_scan;
** }
** count()
** stat_init()
** goto chng_addr_0;
*/
assert( regTemp2==regStat+4 );
sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
/* Arguments to stat_init():
** (1) the number of columns in the index including the rowid
** (or for a WITHOUT ROWID table, the number of PK columns),
** (2) the number of columns in the key without the rowid/pk
** (3) estimated number of rows in the index. */
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1);
assert( regRowid==regStat+2 );
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid);
sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp,
OptimizationDisabled(db, SQLITE_Stat4));
sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4,
&statInitFuncdef, 0);
addrGotoEnd = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
addrNextRow = sqlite3VdbeCurrentAddr(v);
if( nColTest>0 ){
int endDistinctTest = sqlite3VdbeMakeLabel(pParse);
int *aGotoChng; /* Array of jump instruction addresses */
aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest);
if( aGotoChng==0 ) continue;
/*
** next_row:
** regChng = 0
** if( idx(0) != regPrev(0) ) goto chng_addr_0
** regChng = 1
** if( idx(1) != regPrev(1) ) goto chng_addr_1
** ...
** regChng = N
** goto endDistinctTest
*/
sqlite3VdbeAddOp0(v, OP_Goto);
addrNextRow = sqlite3VdbeCurrentAddr(v);
if( nColTest==1 && pIdx->nKeyCol==1 && IsUniqueIndex(pIdx) ){
/* For a single-column UNIQUE index, once we have found a non-NULL
** row, we know that all the rest will be distinct, so skip
** subsequent distinctness tests. */
sqlite3VdbeAddOp4Int(v,
OP_Transaction, /* Opcode */
iDb, /* P1 */
DbMaskTest(pParse->writeMask,iDb), /* P2 */
pSchema->schema_cookie, /* P3 */
pSchema->iGeneration /* P4 */
);
if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
VdbeComment((v,
"usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
}while( ++iDb<db->nDb );
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=0; i<pParse->nVtabLock; i++){
char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
}
pParse->nVtabLock = 0;
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
/* Once all the cookies have been verified and transactions opened,
** obtain the required table-locks. This is a no-op unless the
** shared-cache feature is enabled.
*/
if( pParse->nTableLock ) codeTableLocks(pParse);
#endif
/* Initialize any AUTOINCREMENT data structures required.
*/
if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse);
/* Code constant expressions that were factored out of inner loops.
*/
if( pParse->pConstExpr ){
ExprList *pEL = pParse->pConstExpr;
pParse->okConstFactor = 0;
for(i=0; i<pEL->nExpr; i++){
assert( pEL->a[i].u.iConstExprReg>0 );
sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
}
}
if( pParse->bReturning ){
Returning *pRet;
assert( !pParse->isCreate );
pRet = pParse->u1.d.pReturning;
if( pRet->nRetCol ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
}
}
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeGoto(v, 1);
}
/* Get the VDBE program ready for execution
*/
assert( v!=0 || pParse->nErr );
assert( db->mallocFailed==0 || pParse->nErr );
if( pParse->nErr==0 ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
assert( pParse->pAinc==0 || pParse->nTab>0 );
sqlite3VdbeMakeReady(v, pParse);
pParse->rc = SQLITE_DONE;
}else{
pParse->rc = SQLITE_ERROR;
}
}
/*
** Run the parser and code generator recursively in order to generate
** code for the SQL statement given onto the end of the pParse context
** currently under construction. Notes:
**
** * The final OP_Halt is not appended and other initialization
** and finalization steps are omitted because those are handling by the
** outermost parser.
**
** * Built-in SQL functions always take precedence over application-defined
** SQL functions. In other words, it is not possible to override a
** built-in function.
*/
SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
va_list ap;
char *zSql;
sqlite3 *db = pParse->db;
u32 savedDbFlags = db->mDbFlags;
char saveBuf[PARSE_TAIL_SZ];
if( pParse->nErr ) return;
if( pParse->eParseMode ) return;
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
va_start(ap, zFormat);
zSql = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
if( zSql==0 ){
/* This can result either from an OOM or because the formatted string
** exceeds SQLITE_LIMIT_LENGTH. In the latter case, we need to set
** an error */
if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG;
pParse->nErr++;
return;
}
pParse->nested++;
memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
db->mDbFlags |= DBFLAG_PreferBuiltin;
sqlite3RunParser(pParse, zSql);
db->mDbFlags = savedDbFlags;
sqlite3DbFree(db, zSql);
memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
pParse->nested--;
}
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table. Return NULL if not found.
**
** If zDatabase is 0, all databases are searched for the table and the
/* Verify that no lookaside memory was used by schema tables */
assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
}
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
/* Do not delete the table until the reference count reaches zero. */
assert( db!=0 );
if( !pTable ) return;
if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return;
deleteTable(db, pTable);
}
SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3 *db, void *pTable){
sqlite3DeleteTable(db, (Table*)pTable);
}
/*
** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys.
*/
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
Table *p;
Db *pDb;
assert( db!=0 );
assert( iDb>=0 && iDb<db->nDb );
assert( zTabName );
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */
pDb = &db->aDb[iDb];
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0);
sqlite3DeleteTable(db, p);
db->mDbFlags |= DBFLAG_SchemaChange;
}
/*
** Given a token, return a string that consists of the text of that
** token. Space to hold the returned string
** is obtained from sqliteMalloc() and must be freed by the calling
** function.
**
** Any quotation marks (ex: "name", 'name', [name], or `name`) that
** surround the body of the token are removed.
**
** Tokens are often just pointers into the original SQL text and so
** are not \000 terminated and are not persistent. The returned string
** is \000 terminated and is persistent.
*/
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, const Token *pName){
char *zName;
if( pName ){
zName = sqlite3DbStrNDup(db, (const char*)pName->z, pName->n);
sqlite3Dequote(zName);
}else{
zName = 0;
}
return zName;
}
/*
** Open the sqlite_schema table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, LEGACY_SCHEMA_TABLE);
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, SCHEMA_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
}
}
/*
** Parameter zName points to a nul-terminated buffer containing the name
** of a database ("main", "temp" or the name of an attached db). This
** function returns the index of the named database in db->aDb[], or
** -1 if the named db cannot be found.
*/
SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){
int i = -1; /* Database number */
if( zName ){
Db *pDb;
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
if( 0==sqlite3_stricmp(pDb->zDbSName, zName) ) break;
/* "main" is always an acceptable alias for the primary database
** even if it has been renamed using SQLITE_DBCONFIG_MAINDBNAME. */
if( i==0 && 0==sqlite3_stricmp("main", zName) ) break;
}
}
return i;
}
/*
** The token *pName contains the name of a database (either "main" or
** "temp" or the name of an attached db). This routine returns the
** index of the named database in db->aDb[], or -1 if the named db
** does not exist.
*/
SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){
int i; /* Database number */
char *zName; /* Name we are searching for */
zName = sqlite3NameFromToken(db, pName);
i = sqlite3FindDbName(db, zName);
sqlite3DbFree(db, zName);
return i;
}
/* The table or view or trigger name is passed to this routine via tokens
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
**
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
** CREATE TABLE yyy(...);
**
** Then pName1 is set to "yyy" and pName2 is "".
**
** This routine sets the *ppUnqual pointer to point at the token (pName1 or
** pName2) that stores the unqualified table name. The index of the
** database "xxx" is returned.
/* Estimate the average row size for the table and for all implied indices */
estimateTableWidth(p);
for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
estimateIndexWidth(pIdx);
}
/* If not initializing, then create a record for the new table
** in the schema table of the database.
**
** If this is a TEMPORARY table, write the entry into the auxiliary
** file instead of into the main database file.
*/
if( !db->init.busy ){
int n;
Vdbe *v;
char *zType; /* "view" or "table" */
char *zType2; /* "VIEW" or "TABLE" */
char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */
v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return;
sqlite3VdbeAddOp1(v, OP_Close, 0);
/*
** Initialize zType for the new view or table.
*/
if( IsOrdinaryTable(p) ){
/* A regular table */
zType = "table";
zType2 = "TABLE";
#ifndef SQLITE_OMIT_VIEW
}else{
/* A view */
zType = "view";
zType2 = "VIEW";
#endif
}
/* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
** statement to populate the new table. The root-page number for the
** new table is in register pParse->u1.cr.regRoot.
**
** Once the SELECT has been coded by sqlite3Select(), it is in a
** suitable state to query for the column names and types to be used
** by the new table.
**
** A shared-cache write-lock is not required to write to the new table,
** as a schema-lock must have already been obtained to create it. Since
** a schema-lock excludes all other database users, the write-lock would
** be redundant.
*/
if( pSelect ){
SelectDest dest; /* Where the SELECT should store results */
int regYield; /* Register holding co-routine entry-point */
int addrTop; /* Top of the co-routine */
int regRec; /* A record to be insert into the new table */
int regRowid; /* Rowid of the next row to insert */
int addrInsLoop; /* Top of the loop for inserting rows */
Table *pSelTab; /* A table that describes the SELECT results */
int iCsr; /* Write cursor on the new table */
if( IN_SPECIAL_PARSE ){
pParse->rc = SQLITE_ERROR;
pParse->nErr++;
return;
}
iCsr = pParse->nTab++;
regYield = ++pParse->nMem;
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
sqlite3MayAbort(pParse);
assert( pParse->isCreate );
sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->u1.cr.regRoot, iDb);
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
if( pParse->nErr ) return;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = p->nNVCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
sqlite3Select(pParse, pSelect, &dest);
if( pParse->nErr ) return;
sqlite3VdbeEndCoroutine(v, regYield);
sqlite3VdbeJumpHere(v, addrTop - 1);
addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec);
sqlite3TableAffinity(v, p, 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iCsr, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iCsr, regRec, regRowid);
sqlite3VdbeGoto(v, addrInsLoop);
sqlite3VdbeJumpHere(v, addrInsLoop);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
}
/* Compute the complete text of the CREATE statement */
if( pSelect ){
zStmt = createTableStmt(db, p);
}else{
Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd;
n = (int)(pEnd2->z - pParse->sNameToken.z);
if( pEnd2->z[0]!=';' ) n += pEnd2->n;
zStmt = sqlite3MPrintf(db,
"CREATE %s %.*s", zType2, n, pParse->sNameToken.z
);
}
/* A slot for the record has already been allocated in the
** schema table. We just need to update that slot with all
** the information we've collected.
*/
assert( pParse->isCreate );
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** The Table structure pTable is really a VIEW. Fill in the names of
** the columns of the view in the pTable structure. Return non-zero if
** there are errors. If an error is seen an error message is left
** in pParse->zErrMsg.
*/
static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
Table *pSelTab; /* A fake table from which we get the result set */
Select *pSel; /* Copy of the SELECT that implements the view */
int nErr = 0; /* Number of errors encountered */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
#ifndef SQLITE_OMIT_VIRTUALTABLE
int rc;
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth; /* Saved xAuth pointer */
#endif
assert( pTable );
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTable) ){
db->nSchemaLock++;
rc = sqlite3VtabCallConnect(pParse, pTable);
db->nSchemaLock--;
return rc;
}
#endif
#ifndef SQLITE_OMIT_VIEW
/* A positive nCol means the columns names for this view are
** already known. This routine is not called unless either the
** table is virtual or nCol is zero.
*/
assert( pTable->nCol<=0 );
/* A negative nCol is a special marker meaning that we are currently
** trying to compute the column names. If we enter this routine with
** a negative nCol, it means two or more views form a loop, like this:
**
** CREATE VIEW one AS SELECT * FROM two;
** CREATE VIEW two AS SELECT * FROM one;
**
** Actually, the error above is now caught prior to reaching this point.
** But the following test is still important as it does come up
** in the following:
**
** CREATE TABLE main.ex1(a);
** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
** SELECT * FROM temp.ex1;
*/
if( pTable->nCol<0 ){
sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
return 1;
}
assert( pTable->nCol>=0 );
/* If we get this far, it means we need to compute the table names.
** Note that the call to sqlite3ResultSetOfSelect() will expand any
** "*" elements in the results set of the view and will assign cursors
** to the elements of the FROM clause. But we do not want these changes
** to be permanent. So the computation is done on a copy of the SELECT
** statement that defines the view.
*/
assert( IsView(pTable) );
pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
if( pSel ){
u8 eParseMode = pParse->eParseMode;
int nTab = pParse->nTab;
int nSelect = pParse->nSelect;
pParse->eParseMode = PARSE_MODE_NORMAL;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
DisableLookaside;
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
db->xAuth = xAuth;
#else
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
pParse->nTab = nTab;
pParse->nSelect = nSelect;
if( pSelTab==0 ){
pTable->nCol = 0;
nErr++;
}else if( pTable->pCheck ){
/* CREATE VIEW name(arglist) AS ...
** The names of the columns in the table are taken from
** arglist which is stored in pTable->pCheck. The pCheck field
** normally holds CHECK constraints on an ordinary table, but for
** a VIEW it holds the list of column names.
*/
sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
if( pParse->nErr==0
&& pTable->nCol==pSel->pEList->nExpr
){
assert( db->mallocFailed==0 );
sqlite3SubqueryColumnTypes(pParse, pTable, pSel, SQLITE_AFF_NONE);
}
}else{
/* CREATE VIEW name AS... without an argument list. Construct
** the column names from the SELECT statement that defines the view.
*/
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
pTable->tabFlags |= (pSelTab->tabFlags & COLFLAG_NOINSERT);
pSelTab->nCol = 0;
pSelTab->aCol = 0;
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
}
pTable->nNVCol = pTable->nCol;
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
EnableLookaside;
pParse->eParseMode = eParseMode;
} else {
assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
pFKey->zTo, (void *)pFKey
);
if( pNextTo==pFKey ){
sqlite3OomFault(db);
goto fk_end;
}
if( pNextTo ){
assert( pNextTo->pPrevTo==0 );
pFKey->pNextTo = pNextTo;
pNextTo->pPrevTo = pFKey;
}
/* Link the foreign key to the table as the last step.
*/
assert( IsOrdinaryTable(p) );
p->u.tab.pFKey = pFKey;
pFKey = 0;
fk_end:
sqlite3DbFree(db, pFKey);
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
sqlite3ExprListDelete(db, pFromCol);
sqlite3ExprListDelete(db, pToCol);
}
/*
** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
** clause is seen as part of a foreign key definition. The isDeferred
** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
** The behavior of the most recently created foreign key is adjusted
** accordingly.
*/
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
#ifndef SQLITE_OMIT_FOREIGN_KEY
Table *pTab;
FKey *pFKey;
if( (pTab = pParse->pNewTable)==0 ) return;
if( NEVER(!IsOrdinaryTable(pTab)) ) return;
if( (pFKey = pTab->u.tab.pFKey)==0 ) return;
assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
pFKey->isDeferred = (u8)isDeferred;
#endif
}
/*
** Generate code that will erase and refill index *pIdx. This is
** used to initialize a newly created index or to recompute the
** content of an index in response to a REINDEX command.
**
** if memRootPage is not negative, it means that the index is newly
** created. The register specified by memRootPage contains the
** root page number of the index. If memRootPage is negative, then
** the index already exists and must be cleared before being refilled and
** the root page number of the index is taken from pIndex->tnum.
*/
static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
Table *pTab = pIndex->pTable; /* The table that is indexed */
int iTab = pParse->nTab++; /* Btree cursor used for pTab */
int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
int iSorter; /* Cursor opened by OpenSorter (if in use) */
int addr1; /* Address of top of loop */
int addr2; /* Address to jump to for next iteration */
Pgno tnum; /* Root page of index */
int iPartIdxLabel; /* Jump to this label to skip a row */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
int regRecord; /* Register holding assembled index record */
sqlite3 *db = pParse->db; /* The database connection */
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
db->aDb[iDb].zDbSName ) ){
return;
}
#endif
/* Require a write-lock on the table to perform this operation */
sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
if( memRootPage>=0 ){
tnum = (Pgno)memRootPage;
}else{
tnum = pIndex->tnum;
}
pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
assert( pKey!=0 || pParse->nErr );
/* Open the sorter cursor if we are to use one. */
iSorter = pParse->nTab++;
sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, pIndex->nKeyCol, (char*)
sqlite3KeyInfoRef(pKey), P4_KEYINFO);
/* Open the table. Loop through all rows of the table, inserting index
** records into the sorter. */
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
regRecord = sqlite3GetTempReg(pParse);
sqlite3MultiWrite(pParse);
sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, (int)tnum, iDb,
(char *)pKey, P4_KEYINFO);
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
if( IsUniqueIndex(pIndex) ){
int j2 = sqlite3VdbeGoto(v, 1);
addr2 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeVerifyAbortable(v, OE_Abort);
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
pIndex->nKeyCol); VdbeCoverage(v);
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
sqlite3VdbeJumpHere(v, j2);
}else{
/* Most CREATE INDEX and REINDEX statements that are not UNIQUE can not
** abort. The exception is if one of the indexed expressions contains a
** user function that throws an exception when it is evaluated. But the
** overhead of adding a statement journal to a CREATE INDEX statement is
** very small (since most of the pages written do not contain content that
** needs to be restored if the statement aborts), so we call
** sqlite3MayAbort() for all CREATE INDEX statements. */
sqlite3MayAbort(pParse);
addr2 = sqlite3VdbeCurrentAddr(v);
}
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
if( !pIndex->bAscKeyBug ){
/* This OP_SeekEnd opcode makes index insert for a REINDEX go much
** faster by avoiding unnecessary seeks. But the optimization does
** not work for UNIQUE constraint indexes on WITHOUT ROWID tables
** with DESC primary keys, since those indexes have there keys in
** a different order from the main table.
** See ticket: https://sqlite.org/src/info/bba7b69f9849b5bf
*/
sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
}
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp1(v, OP_Close, iTab);
sqlite3VdbeAddOp1(v, OP_Close, iIdx);
for(i=0; i<pPk->nKeyCol; i++){
Expr *p;
assert( pPk->aiColumn[i]>=0 && pPk->aiColumn[i]<pTab->nCol );
p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName);
pEList = sqlite3ExprListAppend(pParse, pEList, p);
}
pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
if( pLhs ){
pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
}
}
}
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
pSrc->a[0].pSTab = 0;
pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
pSrc->a[0].pSTab = pTab;
if( pSrc->a[0].fg.isIndexedBy ){
assert( pSrc->a[0].fg.isCte==0 );
pSrc->a[0].u2.pIBIndex = 0;
pSrc->a[0].fg.isIndexedBy = 0;
sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
}else if( pSrc->a[0].fg.isCte ){
pSrc->a[0].u2.pCteUse->nUse++;
}
/* generate the SELECT expression tree. */
pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0,
pOrderBy,0,pLimit
);
/* now generate the new WHERE rowid IN clause for the DELETE/UPDATE */
pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0);
sqlite3PExprAddSelect(pParse, pInClause, pSelect);
return pInClause;
}
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
/* && !defined(SQLITE_OMIT_SUBQUERY) */
/*
** Generate code for a DELETE FROM statement.
**
** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
** \________/ \________________/
** pTabList pWhere
*/
SQLITE_PRIVATE void sqlite3DeleteFrom(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table from which we should delete things */
Expr *pWhere, /* The WHERE clause. May be null */
ExprList *pOrderBy, /* ORDER BY clause. May be null */
Expr *pLimit /* LIMIT clause. May be null */
){
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
int i; /* Loop counter */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Index *pIdx; /* For looping over indices of the table */
int iTabCur; /* Cursor number for the table */
int iDataCur = 0; /* VDBE cursor for the canonical data source */
int iIdxCur = 0; /* Cursor number of the first index */
int nIdx; /* Number of indices */
sqlite3 *db; /* Main database structure */
AuthContext sContext; /* Authorization context */
NameContext sNC; /* Name context to resolve expressions in */
int iDb; /* Database number */
int memCnt = 0; /* Memory cell used for change counting */
int rcauth; /* Value returned by authorization callback */
int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
Index *pPk; /* The PRIMARY KEY index on the table */
int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */
i16 nPk = 1; /* Number of columns in the PRIMARY KEY */
int iKey; /* Memory cell holding key of row to be deleted */
i16 nKey; /* Number of memory cells in the row key */
int iEphCur = 0; /* Ephemeral table holding all primary key values */
int iRowSet = 0; /* Register for rowset of rows to delete */
int addrBypass = 0; /* Address of jump over the delete logic */
int addrLoop = 0; /* Top of the delete loop */
int addrEphOpen = 0; /* Instruction to open the Ephemeral table */
int bComplex; /* True if there are triggers or FKs or
** subqueries in the WHERE clause */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
Trigger *pTrigger; /* List of table triggers, if required */
#endif
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
assert( db->pParse==pParse );
if( pParse->nErr ){
goto delete_from_cleanup;
}
assert( db->mallocFailed==0 );
assert( pTabList->nSrc==1 );
/* Locate the table which we want to delete. This table has to be
** put in an SrcList structure because some of the subroutines we
** will be calling are designed to work with multiple tables and expect
** an SrcList* parameter instead of just a Table* parameter.
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto delete_from_cleanup;
/* Figure out if we have any triggers and if the table being
** deleted from is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
isView = IsView(pTab);
#else
# define pTrigger 0
# define isView 0
#endif
bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x10000 ){
sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__);
sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere,
pOrderBy, pLimit, pTrigger);
}
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){
pWhere = sqlite3LimitWhere(
pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE"
);
pOrderBy = 0;
pLimit = 0;
}
#endif
/* If pTab is really a view, make sure it has been initialized.
*/
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto delete_from_cleanup;
}
if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){
goto delete_from_cleanup;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb<db->nDb );
rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0,
db->aDb[iDb].zDbSName);
assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
if( rcauth==SQLITE_DENY ){
goto delete_from_cleanup;
}
assert(!isView || pTrigger);
/* Assign cursor numbers to the table and all its indices.
*/
assert( pTabList->nSrc==1 );
iTabCur = pTabList->a[0].iCursor = pParse->nTab++;
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
pParse->nTab++;
}
/* Start the view context
*/
if( isView ){
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
}
/* Begin generating code.
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ){
goto delete_from_cleanup;
}
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, bComplex, iDb);
/* If we are trying to delete from a view, realize that view into
** an ephemeral table.
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
sqlite3MaterializeView(pParse, pTab,
pWhere, pOrderBy, pLimit, iTabCur
);
iDataCur = iIdxCur = iTabCur;
pOrderBy = 0;
pLimit = 0;
}
#endif
/* Resolve the column names in the WHERE clause.
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
if( sqlite3ResolveExprNames(&sNC, pWhere) ){
goto delete_from_cleanup;
}
/* Initialize the counter of the number of rows deleted, if
** we are counting rows.
*/
if( (db->flags & SQLITE_CountRows)!=0
&& !pParse->nested
&& !pParse->pTriggerTab
&& !pParse->bReturning
){
memCnt = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
}
#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Prior to version 3.6.5,
if( pWInfo==0 ) goto delete_from_cleanup;
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF
|| OptimizationDisabled(db, SQLITE_OnePass) );
if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse);
if( sqlite3WhereUsesDeferredSeek(pWInfo) ){
sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur);
}
/* Keep track of the number of rows to be deleted */
if( memCnt ){
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
}
/* Extract the rowid or primary key for the current row */
if( pPk ){
for(i=0; i<nPk; i++){
assert( pPk->aiColumn[i]>=0 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
pPk->aiColumn[i], iPk+i);
}
iKey = iPk;
}else{
iKey = ++pParse->nMem;
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, -1, iKey);
}
if( eOnePass!=ONEPASS_OFF ){
/* For ONEPASS, no need to store the rowid/primary-key. There is only
** one, so just keep it in its register(s) and fall through to the
** delete code. */
nKey = nPk; /* OP_Found will use an unpacked key */
aToOpen = sqlite3DbMallocRawNN(db, nIdx+2);
if( aToOpen==0 ){
sqlite3WhereEnd(pWInfo);
goto delete_from_cleanup;
}
memset(aToOpen, 1, nIdx+1);
aToOpen[nIdx+1] = 0;
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
addrBypass = sqlite3VdbeMakeLabel(pParse);
}else{
if( pPk ){
/* Add the PK key for this row to the temporary table */
iKey = ++pParse->nMem;
nKey = 0; /* Zero tells OP_Found to use a composite key */
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
sqlite3IndexAffinityStr(pParse->db, pPk), nPk);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk);
}else{
/* Add the rowid of the row to be deleted to the RowSet */
nKey = 1; /* OP_DeferredSeek always uses a single rowid */
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
}
sqlite3WhereEnd(pWInfo);
}
/* Unless this is a view, open cursors for the table we are
** deleting from and all its indices. If this is a view, then the
** only effect this statement has is to fire the INSTEAD OF
** triggers.
*/
if( !isView ){
int iAddrOnce = 0;
if( eOnePass==ONEPASS_MULTI ){
iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
testcase( IsVirtual(pTab) );
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE,
iTabCur, aToOpen, &iDataCur, &iIdxCur);
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
if( eOnePass==ONEPASS_MULTI ){
sqlite3VdbeJumpHereOrPopInst(v, iAddrOnce);
}
}
/* Set up a loop over the rowids/primary-keys that were found in the
** where-clause loop above.
*/
if( eOnePass!=ONEPASS_OFF ){
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
assert( pPk!=0 || IsView(pTab) );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
VdbeCoverage(v);
}
}else if( pPk ){
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
if( IsVirtual(pTab) ){
sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey);
}else{
sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey);
}
assert( nKey==0 ); /* OP_Found will use a composite key */
}else{
addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
VdbeCoverage(v);
assert( nKey==1 );
}
/* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
sqlite3VtabMakeWritable(pParse, pTab);
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
sqlite3MayAbort(pParse);
if( eOnePass==ONEPASS_SINGLE ){
sqlite3VdbeAddOp1(v, OP_Close, iTabCur);
if( sqlite3IsToplevel(pParse) ){
pParse->isMultiWrite = 0;
}
}
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, OE_Abort);
}else
#endif
iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]);
}
/* End of the loop over all rowids/primary-keys. */
if( eOnePass!=ONEPASS_OFF ){
sqlite3VdbeResolveLabel(v, addrBypass);
sqlite3WhereEnd(pWInfo);
}else if( pPk ){
sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrLoop);
}else{
sqlite3VdbeGoto(v, addrLoop);
sqlite3VdbeJumpHere(v, addrLoop);
}
} /* End non-truncate path */
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
** autoincrement tables.
*/
if( pParse->nested==0 && pParse->pTriggerTab==0 ){
sqlite3AutoincrementEnd(pParse);
}
/* Return the number of rows that were deleted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( memCnt ){
sqlite3CodeChangeCount(v, memCnt, "rows deleted");
}
delete_from_cleanup:
sqlite3AuthContextPop(&sContext);
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprDelete(db, pWhere);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
sqlite3ExprListDelete(db, pOrderBy);
sqlite3ExprDelete(db, pLimit);
#endif
if( aToOpen ) sqlite3DbNNFreeNN(db, aToOpen);
return;
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
** they may interfere with compilation of other functions in this file
** (or in another file, if this file becomes part of the amalgamation). */
#ifdef isView
#undef isView
#endif
#ifdef pTrigger
#undef pTrigger
#endif
/*
** This routine generates VDBE code that causes a single row of a
** single table to be deleted. Both the original table entry and
** all indices are removed.
**
** Preconditions:
**
** 1. iDataCur is an open cursor on the btree that is the canonical data
** store for the table. (This will be either the table itself,
** in the case of a rowid table, or the PRIMARY KEY index in the case
** of a WITHOUT ROWID table.)
**
** 2. Read/write cursors for all indices of pTab must be open as
** cursor number iIdxCur+i for the i-th index.
**
** 3. The primary key for the row to be deleted must be stored in a
** sequence of nPk memory cells starting at iPk. If nPk==0 that means
** that a search record formed from OP_MakeRecord is contained in the
** single memory location iPk.
**
** eMode:
** Parameter eMode may be passed either ONEPASS_OFF (0), ONEPASS_SINGLE, or
** ONEPASS_MULTI. If eMode is not ONEPASS_OFF, then the cursor
** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF
** then this function must seek iDataCur to the entry identified by iPk
** and nPk before reading from it.
**
** If eMode is ONEPASS_MULTI, then this call is being made as part
** of a ONEPASS delete that affects multiple rows. In this case, if
** iIdxNoSeek is a valid cursor number (>=0) and is not the same as
** iDataCur, then its position should be preserved following the delete
** operation. Or, if iIdxNoSeek is not a valid cursor number, the
** position of iDataCur should be preserved instead.
**
** iIdxNoSeek:
** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur,
** then it identifies an index cursor (from within array of cursors
** starting at iIdxCur) that already points to the index entry to be deleted.
** Except, this optimization is disabled if there are BEFORE triggers since
** the trigger body might have moved the cursor.
*/
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
Parse *pParse, /* Parsing context */
Table *pTab, /* Table containing the row to be deleted */
Trigger *pTrigger, /* List of triggers to (potentially) fire */
int iDataCur, /* Cursor from which column data is extracted */
int iIdxCur, /* First index cursor */
int iPk, /* First memory cell containing the PRIMARY KEY */
i16 nPk, /* Number of PRIMARY KEY memory cells */
u8 count, /* If non-zero, increment the row change counter */
u8 onconf, /* Default ON CONFLICT policy for triggers */
u8 eMode, /* ONEPASS_OFF, _SINGLE, or _MULTI. See above */
int iIdxNoSeek /* Cursor number of cursor that does not need seeking */
){
Vdbe *v = pParse->pVdbe; /* Vdbe */
int iOld = 0; /* First register in OLD.* array */
int iLabel; /* Label resolved to end of generated code */
u8 opSeek; /* Seek opcode */
/* Vdbe is guaranteed to have been allocated by this stage. */
assert( v );
VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)",
iDataCur, iIdxCur, iPk, (int)nPk));
/* Seek cursor iCur to the row to delete. If this row no longer exists
** (this can happen if a trigger program has already deleted it), do
** not attempt to delete it or fire any DELETE triggers. */
iLabel = sqlite3VdbeMakeLabel(pParse);
opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
if( eMode==ONEPASS_OFF ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
VdbeCoverageIf(v, opSeek==OP_NotExists);
VdbeCoverageIf(v, opSeek==OP_NotFound);
}
/* If there are any triggers to fire, allocate a range of registers to
** use for the old.* references in the triggers. */
if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
u32 mask; /* Mask of OLD.* columns in use */
int iCol; /* Iterator used while populating OLD.* */
int addrStart; /* Start of BEFORE trigger programs */
/* TODO: Could use temporary registers here. Also could attempt to
** avoid copying the contents of the rowid register. */
mask = sqlite3TriggerColmask(
pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
);
mask |= sqlite3FkOldmask(pParse, pTab);
iOld = pParse->nMem+1;
pParse->nMem += (1 + pTab->nCol);
/* Populate the OLD.* pseudo-table register array. These values will be
** used by any BEFORE and AFTER triggers that exist. */
sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
for(iCol=0; iCol<pTab->nCol; iCol++){
testcase( mask!=0xffffffff && iCol==31 );
testcase( mask!=0xffffffff && iCol==32 );
if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
int kk = sqlite3TableColumnToStorage(pTab, iCol);
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+kk+1);
}
}
/* Invoke BEFORE DELETE trigger programs. */
addrStart = sqlite3VdbeCurrentAddr(v);
sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
);
/* If any BEFORE triggers were coded, then seek the cursor to the
** row to be deleted again. It may be that the BEFORE triggers moved
** the cursor or already deleted the row that the cursor was
** pointing to.
**
** Also disable the iIdxNoSeek optimization since the BEFORE trigger
** may have moved that cursor.
*/
if( addrStart<sqlite3VdbeCurrentAddr(v) ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
VdbeCoverageIf(v, opSeek==OP_NotExists);
VdbeCoverageIf(v, opSeek==OP_NotFound);
testcase( iIdxNoSeek>=0 );
iIdxNoSeek = -1;
}
/* Do FK processing. This call checks that any FK constraints that
** refer to this table (i.e. constraints attached to other tables)
** are not violated by deleting this row. */
sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0);
}
/* Delete the index and table entries. Skip this step if pTab is really
** a view (in which case the only effect of the DELETE statement is to
** fire the INSTEAD OF triggers).
**
** If variable 'count' is non-zero, then this OP_Delete instruction should
** invoke the update-hook. The pre-update-hook, on the other hand should
** be invoked unless table pTab is a system table. The difference is that
** the update-hook is not invoked for rows removed by REPLACE, but the
** pre-update-hook is.
*/
if( !IsView(pTab) ){
u8 p5 = 0;
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
}
if( eMode!=ONEPASS_OFF ){
sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE);
}
if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){
sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
}
if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION;
sqlite3VdbeChangeP5(v, p5);
}
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
** to the row just deleted. */
sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0);
/* Invoke AFTER DELETE trigger programs. */
if( pTrigger ){
sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
);
}
/* Jump here if the row had already been deleted before any BEFORE
** trigger programs were invoked. Or if a trigger program throws a
** RAISE(IGNORE) exception. */
sqlite3VdbeResolveLabel(v, iLabel);
VdbeModuleComment((v, "END: GenRowDel()"));
}
/*
** This routine generates VDBE code that causes the deletion of all
** index entries associated with a single row of a single table, pTab
**
** Preconditions:
**
** 1. A read/write cursor "iDataCur" must be open on the canonical storage
** btree for the table pTab. (This will be either the table itself
** for rowid tables or to the primary key index for WITHOUT ROWID
** tables.)
**
** 2. Read/write cursors for all indices of pTab must be open as
** cursor number iIdxCur+i for the i-th index. (The pTab->pIndex
** index is the 0-th index.)
**
** 3. The "iDataCur" cursor must be already be positioned on the row
** that is to be deleted.
*/
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(
Parse *pParse, /* Parsing and code generating context */
Table *pTab, /* Table containing the row to be deleted */
int iDataCur, /* Cursor of table holding data. */
int iIdxCur, /* First index cursor */
int *aRegIdx, /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
int iIdxNoSeek /* Do not delete from this cursor */
){
int i; /* Index loop counter */
int r1 = -1; /* Register holding an index key */
int iPartIdxLabel; /* Jump destination for skipping partial index entries */
Index *pIdx; /* Current index */
Index *pPrior = 0; /* Prior index */
Vdbe *v; /* The prepared statement under construction */
Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
v = pParse->pVdbe;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
assert( iIdxCur+i!=iDataCur || pPk==pIdx );
if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
if( pIdx==pPk ) continue;
if( iIdxCur+i==iIdxNoSeek ) continue;
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
&iPartIdxLabel, pPrior, r1);
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
pPrior = pIdx;
}
}
/*
** Generate code that will assemble an index key and stores 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. If pTab is a WITHOUT ROWID table, then
** iCur must be the cursor of the PRIMARY KEY index.
**
** Return a register number which is the first in a block of
** registers that holds the elements of the index key. The
** block of registers has already been deallocated by the time
** this routine returns.
**
** If *piPartIdxLabel is not NULL, fill it in with a label and jump
** to that label if pIdx is a partial index that should be skipped.
** The label should be resolved using sqlite3ResolvePartIdxLabel().
** A partial index should be skipped if its WHERE clause evaluates
** to false or null. If pIdx is not a partial index, *piPartIdxLabel
** will be set to zero which is an empty label that is ignored by
** sqlite3ResolvePartIdxLabel().
**
** The pPrior and regPrior parameters are used to implement a cache to
** avoid unnecessary register loads. If pPrior is not NULL, then it is
** a pointer to a different index for which an index key has just been
** computed into register regPrior. If the current pIdx index is generating
** its key into the same sequence of registers and if pPrior and pIdx share
** a column in common, then the register corresponding to that column already
** holds the correct value and the loading of that register is skipped.
** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK
** on a table with multiple indices, and especially with the ROWID or
** PRIMARY KEY columns of the index.
*/
SQLITE_PRIVATE int sqlite3GenerateIndexKey(
Parse *pParse, /* Parsing context */
Index *pIdx, /* The index for which to generate a key */
int iDataCur, /* Cursor number from which to take column data */
int regOut, /* Put the new key into this register if not 0 */
int prefixOnly, /* Compute only a unique prefix of the key */
int *piPartIdxLabel, /* OUT: Jump to this label to skip partial index */
Index *pPrior, /* Previously generated index key */
int regPrior /* Register holding previous generated key */
){
Vdbe *v = pParse->pVdbe;
int j;
int regBase;
int nCol;
if( piPartIdxLabel ){
if( pIdx->pPartIdxWhere ){
*piPartIdxLabel = sqlite3VdbeMakeLabel(pParse);
pParse->iSelfTab = iDataCur + 1;
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
pParse->iSelfTab = 0;
pPrior = 0; /* Ticket a9efb42811fa41ee 2019-11-02;
** pPartIdxWhere may have corrupted regPrior registers */
}else{
*piPartIdxLabel = 0;
}
}
nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
regBase = sqlite3GetTempRange(pParse, nCol);
if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0;
for(j=0; j<nCol; j++){
if( pPrior
&& pPrior->aiColumn[j]==pIdx->aiColumn[j]
&& pPrior->aiColumn[j]!=XN_EXPR
&& !pParse->pToplevel
&& !pParse->isMultiWrite
){
/* Special case: If this is an INSERT statement that will insert exactly
** one row into the table, raise a constraint immediately instead of
** incrementing a counter. This is necessary as the VM code is being
** generated for will not open a statement transaction. */
assert( nIncr==1 );
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
}else{
if( nIncr>0 && pFKey->isDeferred==0 ){
sqlite3MayAbort(pParse);
}
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
}
sqlite3VdbeResolveLabel(v, iOk);
sqlite3VdbeAddOp1(v, OP_Close, iCur);
}
/*
** Return an Expr object that refers to a memory register corresponding
** to column iCol of table pTab.
**
** regBase is the first of an array of register that contains the data
** for pTab. regBase itself holds the rowid. regBase+1 holds the first
** column. regBase+2 holds the second column, and so forth.
*/
static Expr *exprTableRegister(
Parse *pParse, /* Parsing and code generating context */
Table *pTab, /* The table whose content is at r[regBase]... */
int regBase, /* Contents of table pTab */
i16 iCol /* Which column of pTab is desired */
){
Expr *pExpr;
Column *pCol;
const char *zColl;
sqlite3 *db = pParse->db;
pExpr = sqlite3Expr(db, TK_REGISTER, 0);
if( pExpr ){
if( iCol>=0 && iCol!=pTab->iPKey ){
pCol = &pTab->aCol[iCol];
pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
pExpr->affExpr = pCol->affinity;
zColl = sqlite3ColumnColl(pCol);
if( zColl==0 ) zColl = db->pDfltColl->zName;
pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
}else{
pExpr->iTable = regBase;
pExpr->affExpr = SQLITE_AFF_INTEGER;
}
}
return pExpr;
}
/*
** Return an Expr object that refers to column iCol of table pTab which
** has cursor iCur.
*/
static Expr *exprTableColumn(
sqlite3 *db, /* The database connection */
Table *pTab, /* The table whose column is desired */
int iCursor, /* The open cursor on the table */
i16 iCol /* The column that is wanted */
){
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
if( pExpr ){
assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pTab;
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
}
return pExpr;
}
/*
** This function is called to generate code executed when a row is deleted
** from the parent table of foreign key constraint pFKey and, if pFKey is
** deferred, when a row is inserted into the same table. When generating
** code for an SQL UPDATE operation, this function may be called twice -
** once to "delete" the old row and once to "insert" the new row.
**
** Parameter nIncr is passed -1 when inserting a row (as this may decrease
** the number of FK violations in the db) or +1 when deleting one (as this
** may increase the number of FK constraint problems).
**
** The code generated by this function scans through the rows in the child
** table that correspond to the parent table row being deleted or inserted.
** For each child row found, one of the following actions is taken:
**
** Operation | FK type | Action taken
** --------------------------------------------------------------------------
** DELETE immediate Increment the "immediate constraint counter".
**
** INSERT immediate Decrement the "immediate constraint counter".
**
** DELETE deferred Increment the "deferred constraint counter".
**
** INSERT deferred Decrement the "deferred constraint counter".
**
** These operations are identified in the comment at the top of this file
** (fkey.c) as "I.2" and "D.2".
*/
static void fkScanChildren(
Parse *pParse, /* Parse context */
SrcList *pSrc, /* The child table to be scanned */
Table *pTab, /* The parent table */
Index *pIdx, /* Index on parent covering the foreign key */
FKey *pFKey, /* The foreign key linking pSrc to pTab */
int *aiCol, /* Map from pIdx cols to child table cols */
int regData, /* Parent row data starts here */
int nIncr /* Amount to increment deferred counter by */
){
sqlite3 *db = pParse->db; /* Database handle */
int i; /* Iterator variable */
Expr *pWhere = 0; /* WHERE clause to scan with */
NameContext sNameContext; /* Context used to resolve WHERE clause */
WhereInfo *pWInfo; /* Context used by sqlite3WhereXXX() */
int iFkIfZero = 0; /* Address of OP_FkIfZero */
Vdbe *v = sqlite3GetVdbe(pParse);
assert( pIdx==0 || pIdx->pTable==pTab );
assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol );
/* Find the parent table of this foreign key. Also find a unique index
** on the parent key columns in the parent table. If either of these
** schema items cannot be located, set an error in pParse and return
** early. */
if( pParse->disableTriggers ){
pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
}else{
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
}
if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
if( !isIgnoreErrors || db->mallocFailed ) return;
if( pTo==0 ){
/* If isIgnoreErrors is true, then a table is being dropped. In this
** case SQLite runs a "DELETE FROM xxx" on the table being dropped
** before actually dropping it in order to check FK constraints.
** If the parent table of an FK constraint on the current table is
** missing, behave as if it is empty. i.e. decrement the relevant
** FK counter for each row of the current table with non-NULL keys.
*/
Vdbe *v = sqlite3GetVdbe(pParse);
int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
for(i=0; i<pFKey->nCol; i++){
int iFromCol, iReg;
iFromCol = pFKey->aCol[i].iFrom;
iReg = sqlite3TableColumnToStorage(pFKey->pFrom,iFromCol) + regOld+1;
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v);
}
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
}
continue;
}
assert( pFKey->nCol==1 || (aiFree && pIdx) );
if( aiFree ){
aiCol = aiFree;
}else{
iCol = pFKey->aCol[0].iFrom;
aiCol = &iCol;
}
for(i=0; i<pFKey->nCol; i++){
if( aiCol[i]==pTab->iPKey ){
aiCol[i] = -1;
}
assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
/* Request permission to read the parent key columns. If the
** authorization callback returns SQLITE_IGNORE, behave as if any
** values read from the parent table are NULL. */
if( db->xAuth ){
int rcauth;
char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName;
rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
bIgnore = (rcauth==SQLITE_IGNORE);
}
#endif
}
/* Take a shared-cache advisory read-lock on the parent table. Allocate
** a cursor to use to search the unique index on the parent key columns
** in the parent table. */
sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName);
pParse->nTab++;
if( regOld!=0 ){
/* A row is being removed from the child table. Search for the parent.
** If the parent does not exist, removing the child row resolves an
** outstanding foreign key constraint violation. */
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore);
}
if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){
/* A row is being added to the child table. If a parent row cannot
** be found, adding the child row has violated the FK constraint.
**
** If this operation is being performed as part of a trigger program
** that is actually a "SET NULL" action belonging to this very
** foreign key, then omit this scan altogether. As all child key
** values are guaranteed to be NULL, it is not possible for adding
** this row to cause an FK violation. */
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore);
}
sqlite3DbFree(db, aiFree);
}
/* Loop through all the foreign key constraints that refer to this table.
** (the "child" constraints) */
for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
Index *pIdx = 0; /* Foreign key index for pFKey */
SrcList *pSrc;
int *aiCol = 0;
if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){
continue;
}
if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs)
&& !pParse->pToplevel && !pParse->isMultiWrite
){
assert( regOld==0 && regNew!=0 );
/* Inserting a single row into a parent table cannot cause (or fix)
** an immediate foreign key violation. So do nothing in this case. */
continue;
}
if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
if( !isIgnoreErrors || db->mallocFailed ) return;
continue;
}
assert( aiCol || pFKey->nCol==1 );
/* Create a SrcList structure containing the child table. We need the
** child table as a SrcList for sqlite3WhereBegin() */
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
SrcItem *pItem = pSrc->a;
pItem->pSTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
pItem->pSTab->nTabRef++;
pItem->iCursor = pParse->nTab++;
FKey *pFKey; /* Iterator variable */
FKey *pNext; /* Copy of pFKey->pNextFrom */
assert( IsOrdinaryTable(pTab) );
assert( db!=0 );
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
/* Remove the FK from the fkeyHash hash table. */
if( db->pnBytesFreed==0 ){
if( pFKey->pPrevTo ){
pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
}else{
const char *z = (pFKey->pNextTo ? pFKey->pNextTo->zTo : pFKey->zTo);
sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, pFKey->pNextTo);
}
if( pFKey->pNextTo ){
pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
}
}
/* EV: R-30323-21917 Each foreign key constraint in SQLite is
** classified as either immediate or deferred.
*/
assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 );
/* Delete any triggers created to implement actions for this FK. */
#ifndef SQLITE_OMIT_TRIGGER
fkTriggerDelete(db, pFKey->apTrigger[0]);
fkTriggerDelete(db, pFKey->apTrigger[1]);
#endif
pNext = pFKey->pNextFrom;
sqlite3DbFree(db, pFKey);
}
}
#endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */
/************** End of fkey.c ************************************************/
/************** Begin file insert.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
*/
/* #include "sqliteInt.h" */
/*
** Generate code that will
**
** (1) acquire a lock for table pTab then
** (2) open pTab as cursor iCur.
**
** If pTab is a WITHOUT ROWID table, then it is the PRIMARY KEY index
** for that table that is actually opened.
*/
SQLITE_PRIVATE void sqlite3OpenTable(
Parse *pParse, /* Generate code into this VDBE */
int iCur, /* The cursor number of the table */
int iDb, /* The database index in sqlite3.aDb[] */
Table *pTab, /* The table to be opened */
int opcode /* OP_OpenRead or OP_OpenWrite */
){
Vdbe *v;
assert( !IsVirtual(pTab) );
assert( pParse->pVdbe!=0 );
v = pParse->pVdbe;
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
if( !pParse->db->noSharedCache ){
sqlite3TableLock(pParse, iDb, pTab->tnum,
(opcode==OP_OpenWrite)?1:0, pTab->zName);
}
if( HasRowid(pTab) ){
sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol);
VdbeComment((v, "%s", pTab->zName));
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
assert( pPk->tnum==pTab->tnum || CORRUPT_DB );
sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
VdbeComment((v, "%s", pTab->zName));
}
}
/*
** Return a pointer to the column affinity string associated with index
** pIdx. A column affinity string has one character for each column in
** the table, according to the affinity of the column:
**
** Character Column affinity
** ------------------------------
** 'A' BLOB
** 'B' TEXT
** 'C' NUMERIC
** 'D' INTEGER
** 'F' REAL
**
** An extra 'D' is appended to the end of the string to cover the
** rowid that appears as the last column in every index.
**
** Memory for the buffer containing the column index affinity string
** is managed along with the rest of the Index structure. It will be
** released when sqlite3DeleteIndex() is called.
*/
static SQLITE_NOINLINE const char *computeIndexAffStr(sqlite3 *db, Index *pIdx){
/* The first time a column affinity string for a particular index is
** required, it is allocated and populated here. It is then stored as
** a member of the Index structure for subsequent use.
**
** The column affinity string will eventually be deleted by
** sqliteDeleteIndex() when the Index structure itself is cleaned
** up.
*/
int n;
Table *pTab = pIdx->pTable;
pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
if( !pIdx->zColAff ){
sqlite3OomFault(db);
*/
static int exprListIsConstant(Parse *pParse, ExprList *pRow){
int ii;
for(ii=0; ii<pRow->nExpr; ii++){
if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0;
}
return 1;
}
/*
** Return true if all expressions in the expression-list passed as the
** only argument are both constant and have no affinity.
*/
static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){
int ii;
if( exprListIsConstant(pParse,pRow)==0 ) return 0;
for(ii=0; ii<pRow->nExpr; ii++){
Expr *pExpr = pRow->a[ii].pExpr;
assert( pExpr->op!=TK_RAISE );
assert( pExpr->affExpr==0 );
if( 0!=sqlite3ExprAffinity(pExpr) ) return 0;
}
return 1;
}
/*
** This function is called by the parser for the second and subsequent
** rows of a multi-row VALUES clause. Argument pLeft is the part of
** the VALUES clause already parsed, argument pRow is the vector of values
** for the new row. The Select object returned represents the complete
** VALUES clause, including the new row.
**
** There are two ways in which this may be achieved - by incremental
** coding of a co-routine (the "co-routine" method) or by returning a
** Select object equivalent to the following (the "UNION ALL" method):
**
** "pLeft UNION ALL SELECT pRow"
**
** If the VALUES clause contains a lot of rows, this compound Select
** object may consume a lot of memory.
**
** When the co-routine method is used, each row that will be returned
** by the VALUES clause is coded into part of a co-routine as it is
** passed to this function. The returned Select object is equivalent to:
**
** SELECT * FROM (
** Select object to read co-routine
** )
**
** The co-routine method is used in most cases. Exceptions are:
**
** a) If the current statement has a WITH clause. This is to avoid
** statements like:
**
** WITH cte AS ( VALUES('x'), ('y') ... )
** SELECT * FROM cte AS a, cte AS b;
**
** This will not work, as the co-routine uses a hard-coded register
** for its OP_Yield instructions, and so it is not possible for two
** cursors to iterate through it concurrently.
**
** b) The schema is currently being parsed (i.e. the VALUES clause is part
** of a schema item like a VIEW or TRIGGER). In this case there is no VM
** being generated when parsing is taking place, and so generating
** a co-routine is not possible.
**
** c) There are non-constant expressions in the VALUES clause (e.g.
** the VALUES clause is part of a correlated sub-query).
**
** d) One or more of the values in the first row of the VALUES clause
** has an affinity (i.e. is a CAST expression). This causes problems
** because the complex rules SQLite uses (see function
** sqlite3SubqueryColumnTypes() in select.c) to determine the effective
** affinity of such a column for all rows require access to all values in
** the column simultaneously.
*/
SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
if( pParse->bHasWith /* condition (a) above */
|| pParse->db->init.busy /* condition (b) above */
|| exprListIsConstant(pParse,pRow)==0 /* condition (c) above */
|| (pLeft->pSrc->nSrc==0 &&
exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */
|| IN_SPECIAL_PARSE
){
/* The co-routine method cannot be used. Fall back to UNION ALL. */
Select *pSelect = 0;
int f = SF_Values | SF_MultiValue;
if( pLeft->pSrc->nSrc ){
sqlite3MultiValuesEnd(pParse, pLeft);
f = SF_Values;
}else if( pLeft->pPrior ){
/* In this case set the SF_MultiValue flag only if it was set on pLeft */
f = (f & pLeft->selFlags);
}
pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0);
pLeft->selFlags &= ~(u32)SF_MultiValue;
if( pSelect ){
pSelect->op = TK_ALL;
pSelect->pPrior = pLeft;
pLeft = pSelect;
}
}else{
SrcItem *p = 0; /* SrcItem that reads from co-routine */
if( pLeft->pSrc->nSrc==0 ){
/* Co-routine has not yet been started and the special Select object
** that accesses the co-routine has not yet been created. This block
** does both those things. */
Vdbe *v = sqlite3GetVdbe(pParse);
Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0);
/* Ensure the database schema has been read. This is to ensure we have
** the correct text encoding. */
if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){
sqlite3ReadSchema(pParse);
}
if( pRet ){
SelectDest dest;
}
}else{
p = &pLeft->pSrc->a[0];
assert( !p->fg.isTabFunc && !p->fg.isIndexedBy );
p->u1.nRow++;
}
if( pParse->nErr==0 ){
Subquery *pSubq;
assert( p!=0 );
assert( p->fg.isSubquery );
pSubq = p->u4.pSubq;
assert( pSubq!=0 );
assert( pSubq->pSelect!=0 );
assert( pSubq->pSelect->pEList!=0 );
if( pSubq->pSelect->pEList->nExpr!=pRow->nExpr ){
sqlite3SelectWrongNumTermsError(pParse, pSubq->pSelect);
}else{
sqlite3ExprCodeExprList(pParse, pRow, pSubq->regResult, 0, 0);
sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, pSubq->regReturn);
}
}
sqlite3ExprListDelete(pParse->db, pRow);
}
return pLeft;
}
/* Forward declaration */
static int xferOptimization(
Parse *pParse, /* Parser context */
Table *pDest, /* The table we are inserting into */
Select *pSelect, /* A SELECT statement to use as the data source */
int onError, /* How to handle constraint errors */
int iDbDest /* The database of pDest */
);
/*
** This routine is called to handle SQL of the following forms:
**
** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),...
** insert into TABLE (IDLIST) select
** insert into TABLE (IDLIST) default values
**
** The IDLIST following the table name is always optional. If omitted,
** then a list of all (non-hidden) columns for the table is substituted.
** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST
** is omitted.
**
** For the pSelect parameter holds the values to be inserted for the
** first two forms shown above. A VALUES clause is really just short-hand
** for a SELECT statement that omits the FROM clause and everything else
** that follows. If the pSelect parameter is NULL, that means that the
** DEFAULT VALUES form of the INSERT statement is intended.
**
** The code generated follows one of four templates. For a simple
** insert with data coming from a single-row VALUES clause, the code executes
** once straight down through. Pseudo-code follows (we call this
** the "1st template"):
**
** open write cursor to <table> and its indices
** put VALUES clause expressions into registers
** write the resulting record into <table>
** cleanup
**
** The three remaining templates assume the statement is of the form
**
** INSERT INTO <table> SELECT ...
**
** If the SELECT clause is of the restricted form "SELECT * FROM <table2>" -
** in other words if the SELECT pulls all columns from a single table
** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and
** if <table2> and <table1> are distinct tables but have identical
** schemas, including all the same indices, then a special optimization
** is invoked that copies raw records from <table2> over to <table1>.
** See the xferOptimization() function for the implementation of this
** template. This is the 2nd template.
**
** open a write cursor to <table>
** open read cursor on <table2>
** transfer all records in <table2> over to <table>
** close cursors
** foreach index on <table>
** open a write cursor on the <table> index
** open a read cursor on the corresponding <table2> index
** transfer all records from the read to the write cursors
** close cursors
** end foreach
**
** The 3rd template is for when the second template does not apply
** and the SELECT clause does not read from <table> at any time.
** The generated code follows this template:
**
** X <- A
** goto B
** A: setup for the SELECT
** loop over the rows in the SELECT
** load values into registers R..R+n
** yield X
** end loop
** cleanup after the SELECT
** end-coroutine X
** B: open write cursor to <table> and its indices
** C: yield X, at EOF goto D
** insert the select result into <table> from R..R+n
** goto C
** D: cleanup
**
** The 4th template is used if the insert statement takes its
** values from a SELECT but the data is being inserted into a table
** that is also read as part of the SELECT. In the third form,
** we have to use an intermediate table to store the results of
** the select. The template is like this:
**
** X <- A
** goto B
** A: setup for the SELECT
** loop over the tables in the SELECT
** load value into register R..R+n
** yield X
** end loop
** cleanup after the SELECT
** end co-routine R
** B: open temp table
** L: yield X, at EOF goto M
** insert row from R..R+n into temp table
** goto L
** M: open write cursor to <table> and its indices
** rewind temp table
** C: loop over rows of intermediate table
** transfer values form intermediate table into <table>
** end loop
** D: cleanup
*/
SQLITE_PRIVATE void sqlite3Insert(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* Name of table into which we are inserting */
Select *pSelect, /* A SELECT statement to use as the data source */
IdList *pColumn, /* Column names corresponding to IDLIST, or NULL. */
int onError, /* How to handle constraint errors */
Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */
){
sqlite3 *db; /* The main database structure */
Table *pTab; /* The table to insert into. aka TABLE */
int i, j; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */
Index *pIdx; /* For looping over indices of the table */
int nColumn; /* Number of columns in the data */
int nHidden = 0; /* Number of hidden columns if TABLE is virtual */
int iDataCur = 0; /* VDBE cursor that is the main data repository */
int iIdxCur = 0; /* First index cursor */
int ipkColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
int endOfLoop; /* Label for the end of the insertion loop */
int srcTab = 0; /* Data comes from this temporary cursor if >=0 */
int addrInsTop = 0; /* Jump to label "D" */
int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */
SelectDest dest; /* Destination for SELECT on rhs of INSERT */
int iDb; /* Index of database holding TABLE */
u8 useTempTable = 0; /* Store SELECT results in intermediate table */
u8 appendFlag = 0; /* True if the insert is likely to be an append */
u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
u8 bIdListInOrder; /* True if IDLIST is in table order */
ExprList *pList = 0; /* List of VALUES() to be inserted */
int iRegStore; /* Register in which to store next column */
/* Register allocations */
int regFromSelect = 0;/* Base register for data coming from SELECT */
int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */
int regRowCount = 0; /* Memory cell used for the row counter */
int regIns; /* Block of regs holding rowid+data being inserted */
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int *aRegIdx = 0; /* One register allocated to each index */
int *aTabColMap = 0; /* Mapping from pTab columns to pCol entries */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to insert into a view */
Trigger *pTrigger; /* List of triggers on pTab, if required */
int tmask; /* Mask of trigger times */
#endif
db = pParse->db;
assert( db->pParse==pParse );
if( pParse->nErr ){
goto insert_cleanup;
}
assert( db->mallocFailed==0 );
dest.iSDParm = 0; /* Suppress a harmless compiler warning */
/* If the Select object is really just a simple VALUES() list with a
** single row (the common case) then keep that one row of values
** and discard the other (unused) parts of the pSelect object
*/
if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
pList = pSelect->pEList;
pSelect->pEList = 0;
sqlite3SelectDelete(db, pSelect);
pSelect = 0;
}
/* Locate the table into which we will be inserting new information.
*/
assert( pTabList->nSrc==1 );
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ){
goto insert_cleanup;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb<db->nDb );
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0,
db->aDb[iDb].zDbSName) ){
goto insert_cleanup;
}
withoutRowid = !HasRowid(pTab);
/* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
** to generate a unique primary key value.
*/
if( !appendFlag ){
int addr1;
if( !IsVirtual(pTab) ){
addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
sqlite3VdbeJumpHere(v, addr1);
}else{
addr1 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, addr1+2); VdbeCoverage(v);
}
sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v);
}
}else if( IsVirtual(pTab) || withoutRowid ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
}else{
sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
appendFlag = 1;
}
autoIncStep(pParse, regAutoinc, regRowid);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Compute the new value for generated columns after all other
** columns have already been computed. This must be done after
** computing the ROWID in case one of the generated columns
** is derived from the INTEGER PRIMARY KEY. */
if( pTab->tabFlags & TF_HasGenerated ){
sqlite3ComputeGeneratedColumns(pParse, regRowid+1, pTab);
}
#endif
/* Generate code to check constraints and generate index keys and
** do the insertion.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
sqlite3MayAbort(pParse);
}else
#endif
{
int isReplace = 0;/* Set to true if constraints may cause a replace */
int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
);
if( db->flags & SQLITE_ForeignKeys ){
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
}
/* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
** constraints or (b) there are no triggers and this table is not a
** parent table in a foreign key constraint. It is safe to set the
** flag in the second case as if any REPLACE constraint is hit, an
** OP_Delete or OP_IdxDelete instruction will be executed on each
** cursor that is disturbed. And these instructions both clear the
** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
** functionality. */
bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v));
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
regIns, aRegIdx, 0, appendFlag, bUseSeek
);
}
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
}else if( pParse->bReturning ){
/* If there is a RETURNING clause, populate the rowid register with
** constant value -1, in case one or more of the returned expressions
** refer to the "rowid" of the view. */
sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
#endif
}
/* Update the count of rows that are inserted
*/
if( regRowCount ){
sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
}
if( pTrigger ){
/* Code AFTER triggers */
sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
pTab, regData-2-pTab->nCol, onError, endOfLoop);
}
/* The bottom of the main insertion loop, if the data source
** is a SELECT statement.
*/
sqlite3VdbeResolveLabel(v, endOfLoop);
if( useTempTable ){
sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrInsTop);
sqlite3VdbeAddOp1(v, OP_Close, srcTab);
}else if( pSelect ){
sqlite3VdbeGoto(v, addrCont);
#ifdef SQLITE_DEBUG
/* If we are jumping back to an OP_Yield that is preceded by an
** OP_ReleaseReg, set the p5 flag on the OP_Goto so that the
** OP_ReleaseReg will be included in the loop. */
if( sqlite3VdbeGetOp(v, addrCont-1)->opcode==OP_ReleaseReg ){
assert( sqlite3VdbeGetOp(v, addrCont)->opcode==OP_Yield );
sqlite3VdbeChangeP5(v, 1);
}
#endif
sqlite3VdbeJumpHere(v, addrInsTop);
}
#ifndef SQLITE_OMIT_XFER_OPT
insert_end:
#endif /* SQLITE_OMIT_XFER_OPT */
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
** autoincrement tables.
*/
if( pParse->nested==0 && pParse->pTriggerTab==0 ){
sqlite3AutoincrementEnd(pParse);
}
/* Return the next index from the list. Return NULL when out of indexes */
static Index *indexIteratorNext(IndexIterator *pIter, int *pIx){
if( pIter->eType ){
int i = ++pIter->i;
if( i>=pIter->u.ax.nIdx ){
*pIx = i;
return 0;
}
*pIx = pIter->u.ax.aIdx[i].ix;
return pIter->u.ax.aIdx[i].p;
}else{
++(*pIx);
pIter->u.lx.pIdx = pIter->u.lx.pIdx->pNext;
return pIter->u.lx.pIdx;
}
}
/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
**
** The regNewData parameter is the first register in a range that contains
** the data to be inserted or the data after the update. There will be
** pTab->nCol+1 registers in this range. The first register (the one
** that regNewData points to) will contain the new rowid, or NULL in the
** case of a WITHOUT ROWID table. The second register in the range will
** contain the content of the first table column. The third register will
** contain the content of the second table column. And so forth.
**
** The regOldData parameter is similar to regNewData except that it contains
** the data prior to an UPDATE rather than afterwards. regOldData is zero
** for an INSERT. This routine can distinguish between UPDATE and INSERT by
** checking regOldData for zero.
**
** For an UPDATE, the pkChng boolean is true if the true primary key (the
** rowid for a normal table or the PRIMARY KEY for a WITHOUT ROWID table)
** might be modified by the UPDATE. If pkChng is false, then the key of
** the iDataCur content table is guaranteed to be unchanged by the UPDATE.
**
** For an INSERT, the pkChng boolean indicates whether or not the rowid
** was explicitly specified as part of the INSERT statement. If pkChng
** is zero, it means that the either rowid is computed automatically or
** that the table is a WITHOUT ROWID table and has no rowid. On an INSERT,
** pkChng will only be true if the INSERT statement provides an integer
** value for either the rowid column or its INTEGER PRIMARY KEY alias.
**
** The code generated by this routine will store new index entries into
** registers identified by aRegIdx[]. No index entry is created for
** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is
** the same as the order of indices on the linked list of indices
** at pTab->pIndex.
**
** (2019-05-07) The generated code also creates a new record for the
** main table, if pTab is a rowid table, and stores that record in the
** register identified by aRegIdx[nIdx] - in other words in the first
** entry of aRegIdx[] past the last index. It is important that the
** record be generated during constraint checks to avoid affinity changes
** to the register content that occur after constraint checks but before
** the new record is inserted.
**
** The caller must have already opened writeable cursors on the main
** table and all applicable indices (that is to say, all indices for which
** aRegIdx[] is not zero). iDataCur is the cursor for the main table when
** inserting or updating a rowid table, or the cursor for the PRIMARY KEY
** index when operating on a WITHOUT ROWID table. iIdxCur is the cursor
** for the first index in the pTab->pIndex list. Cursors for other indices
** are at iIdxCur+N for the N-th element of the pTab->pIndex list.
**
** This routine also generates code to check constraints. NOT NULL,
** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
** then the appropriate action is performed. There are five possible
** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
**
** Constraint type Action What Happens
** --------------- ---------- ----------------------------------------
** any ROLLBACK The current transaction is rolled back and
** sqlite3_step() returns immediately with a
** return code of SQLITE_CONSTRAINT.
**
** any ABORT Back out changes from the current command
** only (do not do a complete rollback) then
** cause sqlite3_step() to return immediately
** with SQLITE_CONSTRAINT.
**
** any FAIL Sqlite3_step() returns immediately with a
** return code of SQLITE_CONSTRAINT. The
** transaction is not rolled back and any
** changes to prior rows are retained.
**
** any IGNORE The attempt in insert or update the current
** row is skipped, without throwing an error.
** Processing continues with the next row.
** (There is an immediate jump to ignoreDest.)
**
** NOT NULL REPLACE The NULL value is replace by the default
** value for that column. If the default value
** is NULL, the action is the same as ABORT.
**
** UNIQUE REPLACE The other row that conflicts with the row
** being inserted is removed.
**
** CHECK REPLACE Illegal. The results in an exception.
**
** Which action to take is determined by the overrideError parameter.
** Or if overrideError==OE_Default, then the pParse->onError parameter
** is used. Or if pParse->onError==OE_Default then the onError value
** for the constraint is used.
*/
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
Parse *pParse, /* The parser context */
Table *pTab, /* The table being inserted or updated */
int *aRegIdx, /* Use register aRegIdx[i] for index i. 0 for unused */
int iDataCur, /* Canonical data cursor (main table or PK index) */
int iIdxCur, /* First index cursor */
int regNewData, /* First register in a range holding values to insert */
int regOldData, /* Previous content. 0 for INSERTs */
u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */
u8 overrideError, /* Override onError to this if not OE_Default */
int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */
int *aiChng, /* column i is unchanged if aiChng[i]<0 */
Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */
){
Vdbe *v; /* VDBE under construction */
Index *pIdx; /* Pointer to one of the indices */
Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */
sqlite3 *db; /* Database connection */
int i; /* loop counter */
int ix; /* Index loop counter */
int nCol; /* Number of columns */
int onError; /* Conflict resolution strategy */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
Upsert *pUpsertClause = 0; /* The specific ON CONFLICT clause for pIdx */
u8 isUpdate; /* True if this is an UPDATE operation */
u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
int upsertIpkReturn = 0; /* Address of Goto at end of IPK uniqueness check */
int upsertIpkDelay = 0; /* Address of Goto to bypass initial IPK check */
int ipkTop = 0; /* Top of the IPK uniqueness check */
int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */
/* Variables associated with retesting uniqueness constraints after
** replace triggers fire have run */
int regTrigCnt; /* Register used to count replace trigger invocations */
int addrRecheck = 0; /* Jump here to recheck all uniqueness constraints */
int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */
Trigger *pTrigger; /* List of DELETE triggers on the table pTab */
int nReplaceTrig = 0; /* Number of replace triggers coded */
IndexIterator sIdxIter; /* Index iterator */
isUpdate = regOldData!=0;
db = pParse->db;
v = pParse->pVdbe;
assert( v!=0 );
assert( !IsView(pTab) ); /* This table is not a VIEW */
nCol = pTab->nCol;
/* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
** normal rowid tables. nPkField is the number of key fields in the
** pPk index or 1 for a rowid table. In other words, nPkField is the
** number of fields in the true primary key of the table. */
if( HasRowid(pTab) ){
pPk = 0;
nPkField = 1;
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
nPkField = pPk->nKeyCol;
}
/* Record that this module has started */
VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)",
iDataCur, iIdxCur, regNewData, regOldData, pkChng));
/* Test all NOT NULL constraints.
*/
sqlite3VdbeJumpHere(v, ipkBottom);
}
/* Recheck all uniqueness constraints after replace triggers have run */
testcase( regTrigCnt!=0 && nReplaceTrig==0 );
assert( regTrigCnt!=0 || nReplaceTrig==0 );
if( nReplaceTrig ){
sqlite3VdbeAddOp2(v, OP_IfNot, regTrigCnt, lblRecheckOk);VdbeCoverage(v);
if( !pPk ){
if( isUpdate ){
sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRecheck, regOldData);
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRecheck, regNewData);
VdbeCoverage(v);
sqlite3RowidConstraint(pParse, OE_Abort, pTab);
}else{
sqlite3VdbeGoto(v, addrRecheck);
}
sqlite3VdbeResolveLabel(v, lblRecheckOk);
}
/* Generate the table record */
if( HasRowid(pTab) ){
int regRec = aRegIdx[ix];
sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nNVCol, regRec);
sqlite3SetMakeRecordP5(v, pTab);
if( !bAffinityDone ){
sqlite3TableAffinity(v, pTab, 0);
}
}
*pbMayReplace = seenReplace;
VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}
#ifdef SQLITE_ENABLE_NULL_TRIM
/*
** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)
** to be the number of columns in table pTab that must not be NULL-trimmed.
**
** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero.
*/
SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
u16 i;
/* Records with omitted columns are only allowed for schema format
** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
if( pTab->pSchema->file_format<2 ) return;
for(i=pTab->nCol-1; i>0; i--){
if( pTab->aCol[i].iDflt!=0 ) break;
if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
}
sqlite3VdbeChangeP5(v, i+1);
}
#endif
/*
** Table pTab is a WITHOUT ROWID table that is being written to. The cursor
** number is iCur, and register regData contains the new record for the
** PK index. This function adds code to invoke the pre-update hook,
** if one is registered.
*/
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
static void codeWithoutRowidPreupdate(
Parse *pParse, /* Parse context */
Table *pTab, /* Table being updated */
int iCur, /* Cursor number for table */
int regData /* Data containing new record */
){
Vdbe *v = pParse->pVdbe;
int r = sqlite3GetTempReg(pParse);
assert( !HasRowid(pTab) );
assert( 0==(pParse->db->mDbFlags & DBFLAG_Vacuum) || CORRUPT_DB );
sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
sqlite3VdbeAddOp4(v, OP_Insert, iCur, regData, r, (char*)pTab, P4_TABLE);
sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
sqlite3ReleaseTempReg(pParse, r);
}
#else
# define codeWithoutRowidPreupdate(a,b,c,d)
#endif
/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
** A consecutive range of registers starting at regNewData contains the
** rowid and the content to be inserted.
**
** The arguments to this routine should be the same as the first six
** arguments to sqlite3GenerateConstraintChecks.
*/
SQLITE_PRIVATE void sqlite3CompleteInsertion(
Parse *pParse, /* The parser context */
Table *pTab, /* the table into which we are inserting */
int iDataCur, /* Cursor of the canonical data source */
int iIdxCur, /* First index cursor */
int regNewData, /* Range of content */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
int update_flags, /* True for UPDATE, False for INSERT */
int appendBias, /* True if this is likely to be an append */
int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
Vdbe *v; /* Prepared statements under construction */
Index *pIdx; /* An index being inserted or updated */
u8 pik_flags; /* flag values passed to the btree insert */
int i; /* Loop counter */
assert( update_flags==0
|| update_flags==OPFLAG_ISUPDATE
|| update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
);
v = pParse->pVdbe;
assert( v!=0 );
assert( !IsView(pTab) ); /* This table is not a VIEW */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
/* All REPLACE indexes are at the end of the list */
assert( pIdx->onError!=OE_Replace
|| pIdx->pNext==0
|| pIdx->pNext->onError==OE_Replace );
if( aRegIdx[i]==0 ) continue;
if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
}
pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
pik_flags |= OPFLAG_NCHANGE;
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
if( update_flags==0 ){
codeWithoutRowidPreupdate(pParse, pTab, iIdxCur+i, aRegIdx[i]);
}
}
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
aRegIdx[i]+1,
pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
sqlite3VdbeChangeP5(v, pik_flags);
}
if( !HasRowid(pTab) ) return;
if( pParse->nested ){
pik_flags = 0;
}else{
pik_flags = OPFLAG_NCHANGE;
pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID);
}
if( appendBias ){
pik_flags |= OPFLAG_APPEND;
}
if( useSeekResult ){
pik_flags |= OPFLAG_USESEEKRESULT;
}
sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, aRegIdx[i], regNewData);
if( !pParse->nested ){
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
}
sqlite3VdbeChangeP5(v, pik_flags);
}
/*
** Allocate cursors for the pTab table and all its indices and generate
** code to open and initialized those cursors.
**
** The cursor for the object that contains the complete data (normally
** the table itself, but the PRIMARY KEY index in the case of a WITHOUT
** ROWID table) is returned in *piDataCur. The first index cursor is
** returned in *piIdxCur. The number of indices is returned.
**
** Use iBase as the first cursor (either the *piDataCur for rowid tables
** or the first index for WITHOUT ROWID tables) if it is non-negative.
** If iBase is negative, then allocate the next available cursor.
**
** For a rowid table, *piDataCur will be exactly one less than *piIdxCur.
** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range
** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the
** pTab->pIndex list.
**
** If pTab is a virtual table, then this routine is a no-op and the
** *piDataCur and *piIdxCur values are left uninitialized.
*/
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(
Parse *pParse, /* Parsing context */
Table *pTab, /* Table to be opened */
int op, /* OP_OpenRead or OP_OpenWrite */
u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */
int iBase, /* Use this for the table cursor, if there is one */
u8 *aToOpen, /* If not NULL: boolean for each table and index */
int *piDataCur, /* Write the database source cursor number here */
int *piIdxCur /* Write the first index cursor number here */
){
int i;
int iDb;
int iDataCur;
Index *pIdx;
Vdbe *v;
assert( op==OP_OpenRead || op==OP_OpenWrite );
assert( op==OP_OpenWrite || p5==0 );
assert( piDataCur!=0 );
assert( piIdxCur!=0 );
if( IsVirtual(pTab) ){
/* This routine is a no-op for virtual tables. Leave the output
** variables *piDataCur and *piIdxCur set to illegal cursor numbers
** for improved error detection. */
*piDataCur = *piIdxCur = -999;
return 0;
}
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
v = pParse->pVdbe;
assert( v!=0 );
if( iBase<0 ) iBase = pParse->nTab;
iDataCur = iBase++;
*piDataCur = iDataCur;
if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){
sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op);
}else if( pParse->db->noSharedCache==0 ){
sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName);
}
*piIdxCur = iBase;
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
int iIdxCur = iBase++;
assert( pIdx->pSchema==pTab->pSchema );
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
*piDataCur = iIdxCur;
p5 = 0;
}
if( aToOpen==0 || aToOpen[i+1] ){
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
sqlite3VdbeChangeP5(v, p5);
VdbeComment((v, "%s", pIdx->zName));
}
}
if( iBase>pParse->nTab ) pParse->nTab = iBase;
return i;
}
#ifdef SQLITE_TEST
/*
** The following global variable is incremented whenever the
** transfer optimization is used. This is used for testing
** purposes only - to make sure the transfer optimization really
** is happening when it is supposed to.
*/
SQLITE_API int sqlite3_xferopt_count;
#endif /* SQLITE_TEST */
#ifndef SQLITE_OMIT_XFER_OPT
/*
** Check to see if index pSrc is compatible as a source of data
** for index pDest in an insert transfer optimization. The rules
** for a compatible index:
**
** * The index is over the same set of columns
** * The same DESC and ASC markings occurs on all columns
** * The same onError processing (OE_Abort, OE_Ignore, etc)
** * The same collating sequence on each column
** * The index has the exact same WHERE clause
*/
static int xferCompatibleIndex(Index *pDest, Index *pSrc){
int i;
iTab = cnt++;
}else{
iTab = cnt;
for(pIdx=pTab->pIndex; ALWAYS(pIdx); pIdx=pIdx->pNext){
if( IsPrimaryKeyIndex(pIdx) ) break;
iTab++;
}
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->pPartIdxWhere==0 ){
addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+cnt, 0, 8+iTab);
VdbeCoverageNeverNull(v);
sqlite3VdbeLoadString(v, 4, pIdx->zName);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, addr);
}
cnt++;
}
}
/* Make sure all the indices are constructed correctly.
*/
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx, *pPk;
Index *pPrior = 0; /* Previous index */
int loopTop;
int iDataCur, iIdxCur;
int r1 = -1;
int bStrict; /* True for a STRICT table */
int r2; /* Previous key for WITHOUT ROWID tables */
int mxCol; /* Maximum non-virtual column number */
if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
if( !IsOrdinaryTable(pTab) ) continue;
if( isQuick || HasRowid(pTab) ){
pPk = 0;
r2 = 0;
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol);
sqlite3VdbeAddOp3(v, OP_Null, 1, r2, r2+pPk->nKeyCol-1);
}
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
/* reg[7] counts the number of entries in the table.
** reg[8+i] counts the number of entries in the i-th index
*/
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
}
assert( pParse->nMem>=8+j );
assert( sqlite3NoTempsInRange(pParse,1,7+j) );
sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
/* Fetch the right-most column from the table. This will cause
** the entire record header to be parsed and sanity checked. It
** will also prepopulate the cursor column cache that is used
** by the OP_IsType code, so it is a required step.
*/
assert( !IsVirtual(pTab) );
if( HasRowid(pTab) ){
mxCol = -1;
for(j=0; j<pTab->nCol; j++){
if( (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)==0 ) mxCol++;
}
if( mxCol==pTab->iPKey ) mxCol--;
}else{
/* COLFLAG_VIRTUAL columns are not included in the WITHOUT ROWID
** PK index column-count, so there is no need to account for them
** in this case. */
mxCol = sqlite3PrimaryKeyIndex(pTab)->nColumn-1;
}
if( mxCol>=0 ){
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, mxCol, 3);
sqlite3VdbeTypeofColumn(v, 3);
}
if( !isQuick ){
if( pPk ){
/* Verify WITHOUT ROWID keys are in ascending order */
int a1;
char *zErr;
a1 = sqlite3VdbeAddOp4Int(v, OP_IdxGT, iDataCur, 0,r2,pPk->nKeyCol);
VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_IsNull, r2); VdbeCoverage(v);
zErr = sqlite3MPrintf(db,
"row not in PRIMARY KEY order for %s",
pTab->zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, a1);
sqlite3VdbeJumpHere(v, a1+1);
for(j=0; j<pPk->nKeyCol; j++){
sqlite3ExprCodeLoadIndexColumn(pParse, pPk, iDataCur, j, r2+j);
}
}
}
/* Verify datatypes for all columns:
**
** (1) NOT NULL columns may not contain a NULL
** (2) Datatype must be exact for non-ANY columns in STRICT tables
** (3) Datatype for TEXT columns in non-STRICT tables must be
** NULL, TEXT, or BLOB.
** (4) Datatype for numeric columns in non-STRICT tables must not
** be a TEXT value that can be losslessly converted to numeric.
*/
bStrict = (pTab->tabFlags & TF_Strict)!=0;
for(j=0; j<pTab->nCol; j++){
char *zErr;
Column *pCol = pTab->aCol + j; /* The column to be checked */
int labelError; /* Jump here to report an error */
int labelOk; /* Jump here if all looks ok */
int p1, p3, p4; /* Operands to the OP_IsType opcode */
int doTypeCheck; /* Check datatypes (besides NOT NULL) */
if( j==pTab->iPKey ) continue;
if( bStrict ){
};
int i;
pParse->nMem = 2;
for(i=0; i<db->nDb; i++){
Btree *pBt;
const char *zState = "unknown";
int j;
if( db->aDb[i].zDbSName==0 ) continue;
pBt = db->aDb[i].pBt;
if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
zState = "closed";
}else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0,
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
zState = azLockName[j];
}
sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState);
}
break;
}
#endif
#if defined(SQLITE_ENABLE_CEROD)
case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){
if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
sqlite3_activate_cerod(&zRight[6]);
}
}
break;
#endif
} /* End of the PRAGMA switch */
/* The following block is a no-op unless SQLITE_DEBUG is defined. Its only
** purpose is to execute assert() statements to verify that if the
** PragFlg_NoColumns1 flag is set and the caller specified an argument
** to the PRAGMA, the implementation has not added any OP_ResultRow
** instructions to the VM. */
if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){
sqlite3VdbeVerifyNoResultRow(v);
}
pragma_out:
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*****************************************************************************
** Implementation of an eponymous virtual table that runs a pragma.
**
*/
typedef struct PragmaVtab PragmaVtab;
typedef struct PragmaVtabCursor PragmaVtabCursor;
struct PragmaVtab {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db; /* The database connection to which it belongs */
const PragmaName *pName; /* Name of the pragma */
u8 nHidden; /* Number of hidden columns */
u8 iHidden; /* Index of the first hidden column */
};
struct PragmaVtabCursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
sqlite3_stmt *pPragma; /* The pragma statement to run */
sqlite_int64 iRowid; /* Current rowid */
char *azArg[2]; /* Value of the argument and schema */
};
/*
** Pragma virtual table module xConnect method.
*/
static int pragmaVtabConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
const PragmaName *pPragma = (const PragmaName*)pAux;
PragmaVtab *pTab = 0;
int rc;
int i, j;
char cSep = '(';
StrAccum acc;
char zBuf[200];
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
sqlite3_str_appendall(&acc, "CREATE TABLE x");
for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){
sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]);
cSep = ',';
}
if( i==0 ){
sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName);
i++;
}
j = 0;
if( pPragma->mPragFlg & PragFlg_Result1 ){
sqlite3_str_appendall(&acc, ",arg HIDDEN");
j++;
}
if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){
sqlite3_str_appendall(&acc, ",schema HIDDEN");
j++;
}
sqlite3_str_append(&acc, ")", 1);
sqlite3StrAccumFinish(&acc);
assert( strlen(zBuf) < sizeof(zBuf)-1 );
rc = sqlite3_declare_vtab(db, zBuf);
if( rc==SQLITE_OK ){
pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab));
if( pTab==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pTab, 0, sizeof(PragmaVtab));
pTab->pName = pPragma;
pTab->db = db;
pTab->iHidden = i;
pTab->nHidden = j;
}
}else{
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
*ppVtab = (sqlite3_vtab*)pTab;
return rc;
}
/*
** Pragma virtual table module xDisconnect method.
*/
static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){
PragmaVtab *pTab = (PragmaVtab*)pVtab;
sqlite3_free(pTab);
return SQLITE_OK;
}
/* Figure out the best index to use to search a pragma virtual table.
**
** There are not really any index choices. But we want to encourage the
** query planner to give == constraints on as many hidden parameters as
** possible, and especially on the first hidden parameter. So return a
** high cost if hidden parameters are unconstrained.
*/
static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
PragmaVtab *pTab = (PragmaVtab*)tab;
const struct sqlite3_index_constraint *pConstraint;
int i, j;
int seen[2];
pIdxInfo->estimatedCost = (double)1;
if( pTab->nHidden==0 ){ return SQLITE_OK; }
pConstraint = pIdxInfo->aConstraint;
seen[0] = 0;
seen[1] = 0;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->iColumn < pTab->iHidden ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pConstraint->usable==0 ) return SQLITE_CONSTRAINT;
j = pConstraint->iColumn - pTab->iHidden;
assert( j < 2 );
seen[j] = i+1;
}
if( seen[0]==0 ){
pIdxInfo->estimatedCost = (double)2147483647;
pIdxInfo->estimatedRows = 2147483647;
return SQLITE_OK;
}
j = seen[0]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 1;
pIdxInfo->aConstraintUsage[j].omit = 1;
pIdxInfo->estimatedCost = (double)20;
pIdxInfo->estimatedRows = 20;
if( seen[1] ){
j = seen[1]-1;
pIdxInfo->aConstraintUsage[j].argvIndex = 2;
pIdxInfo->aConstraintUsage[j].omit = 1;
}
return SQLITE_OK;
}
/* Create a new cursor for the pragma virtual table */
static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
PragmaVtabCursor *pCsr;
pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr));
if( pCsr==0 ) return SQLITE_NOMEM;
memset(pCsr, 0, sizeof(PragmaVtabCursor));
pCsr->base.pVtab = pVtab;
*ppCursor = &pCsr->base;
return SQLITE_OK;
}
/* Clear all content from pragma virtual table cursor. */
static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
int i;
sqlite3_finalize(pCsr->pPragma);
pCsr->pPragma = 0;
pCsr->iRowid = 0;
for(i=0; i<ArraySize(pCsr->azArg); i++){
sqlite3_free(pCsr->azArg[i]);
pCsr->azArg[i] = 0;
}
}
/* Close a pragma virtual table cursor */
static int pragmaVtabClose(sqlite3_vtab_cursor *cur){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur;
pragmaVtabCursorClear(pCsr);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/* Advance the pragma virtual table cursor to the next row */
static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
int rc = SQLITE_OK;
/* Increment the xRowid value */
pCsr->iRowid++;
assert( pCsr->pPragma );
if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){
rc = sqlite3_finalize(pCsr->pPragma);
pCsr->pPragma = 0;
pragmaVtabCursorClear(pCsr);
}
return rc;
}
/*
** Pragma virtual table module xFilter method.
*/
static int pragmaVtabFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
int rc;
int i, j;
StrAccum acc;
char *zSql;
UNUSED_PARAMETER(idxNum);
UNUSED_PARAMETER(idxStr);
pragmaVtabCursorClear(pCsr);
j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1;
for(i=0; i<argc; i++, j++){
const char *zText = (const char*)sqlite3_value_text(argv[i]);
assert( j<ArraySize(pCsr->azArg) );
assert( pCsr->azArg[j]==0 );
if( zText ){
pCsr->azArg[j] = sqlite3_mprintf("%s", zText);
if( pCsr->azArg[j]==0 ){
return SQLITE_NOMEM;
}
}
}
sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]);
sqlite3_str_appendall(&acc, "PRAGMA ");
if( pCsr->azArg[1] ){
sqlite3_str_appendf(&acc, "%Q.", pCsr->azArg[1]);
}
sqlite3_str_appendall(&acc, pTab->pName->zName);
if( pCsr->azArg[0] ){
sqlite3_str_appendf(&acc, "=%Q", pCsr->azArg[0]);
}
zSql = sqlite3StrAccumFinish(&acc);
if( zSql==0 ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK ){
pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
return rc;
}
return pragmaVtabNext(pVtabCursor);
}
/*
** Pragma virtual table module xEof method.
*/
static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
return (pCsr->pPragma==0);
}
/* The xColumn method simply returns the corresponding column from
** the PRAGMA.
*/
static int pragmaVtabColumn(
sqlite3_vtab_cursor *pVtabCursor,
sqlite3_context *ctx,
int i
){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
if( i<pTab->iHidden ){
sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i));
}else{
sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT);
}
return SQLITE_OK;
}
/*
** Pragma virtual table module xRowid method.
*/
static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){
PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
*p = pCsr->iRowid;
return SQLITE_OK;
}
/* The pragma virtual table object */
static const sqlite3_module pragmaVtabModule = {
0, /* iVersion */
0, /* xCreate - create a table */
pragmaVtabConnect, /* xConnect - connect to an existing table */
pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */
pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */
0, /* xDestroy - Drop a table */
pragmaVtabOpen, /* xOpen - open a cursor */
pragmaVtabClose, /* xClose - close a cursor */
pragmaVtabFilter, /* xFilter - configure scan constraints */
pragmaVtabNext, /* xNext - advance a cursor */
pragmaVtabEof, /* xEof */
pragmaVtabColumn, /* xColumn - read data */
pragmaVtabRowid, /* xRowid - read data */
0, /* xUpdate - write data */
0, /* xBegin - begin transaction */
0, /* xSync - sync transaction */
0, /* xCommit - commit transaction */
0, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
0, /* xRename - rename the table */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
/*
** Check to see if zTabName is really the name of a pragma. If it is,
** then register an eponymous virtual table for that pragma and return
** a pointer to the Module object for the new virtual table.
*/
SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){
const PragmaName *pName;
assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 );
pName = pragmaLocate(zName+7);
if( pName==0 ) return 0;
if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0;
assert( sqlite3HashFind(&db->aModule, zName)==0 );
return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#endif /* SQLITE_OMIT_PRAGMA */
/************** End of pragma.c **********************************************/
/************** Begin file prepare.c *****************************************/
/*
** 2005 May 25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
*/
/* #include "sqliteInt.h" */
/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
static void corruptSchema(
}
return 0;
}
/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file. The index of the
** database file is given by iDb. iDb==0 is used for the main
** database. iDb==1 should never be used. iDb>=2 is used for
** auxiliary databases. Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
int rc;
int i;
#ifndef SQLITE_OMIT_DEPRECATED
int size;
#endif
Db *pDb;
char const *azArg[6];
int meta[5];
InitData initData;
const char *zSchemaTabName;
int openedTransaction = 0;
int mask = ((db->mDbFlags & DBFLAG_EncodingFixed) | ~DBFLAG_EncodingFixed);
assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pSchema );
assert( sqlite3_mutex_held(db->mutex) );
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
db->init.busy = 1;
/* Construct the in-memory representation schema tables (sqlite_schema or
** sqlite_temp_schema) by invoking the parser directly. The appropriate
** table name will be inserted automatically by the parser so we can just
** use the abbreviation "x" here. The parser will also automatically tag
** the schema table as read-only. */
azArg[0] = "table";
azArg[1] = zSchemaTabName = SCHEMA_TABLE(iDb);
azArg[2] = azArg[1];
azArg[3] = "1";
azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text,"
"rootpage int,sql text)";
azArg[5] = 0;
initData.db = db;
initData.iDb = iDb;
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
initData.mInitFlags = mFlags;
initData.nInitRow = 0;
initData.mxPage = 0;
sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
db->mDbFlags &= mask;
if( initData.rc ){
rc = initData.rc;
goto error_out;
}
/* Create a cursor to hold the database open
*/
pDb = &db->aDb[iDb];
if( pDb->pBt==0 ){
assert( iDb==1 );
DbSetProperty(db, 1, DB_SchemaLoaded);
rc = SQLITE_OK;
goto error_out;
}
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
if( sqlite3BtreeTxnState(pDb->pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
goto initone_error_out;
}
openedTransaction = 1;
}
/* Get the database meta information.
**
** Meta values are as follows:
** meta[0] Schema cookie. Changes with each schema change.
** meta[1] File format of schema layer.
** meta[2] Size of the page cache.
** meta[3] Largest rootpage (auto/incr_vacuum mode)
** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE
** meta[5] User version
** meta[6] Incremental vacuum mode
** meta[7] unused
** meta[8] unused
** meta[9] unused
**
** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
** the possible values of meta[4].
*/
for(i=0; i<ArraySize(meta); i++){
sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
}
if( (db->flags & SQLITE_ResetDatabase)!=0 ){
memset(meta, 0, sizeof(meta));
}
pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1];
/* If opening a non-empty database, check the text encoding. For the
** main database, set sqlite3.enc to the encoding of the main database.
** For an attached db, it is an error if the encoding is not the same
** as sqlite3.enc.
*/
if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */
if( iDb==0 && (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){
u8 encoding;
#ifndef SQLITE_OMIT_UTF16
/* If opening the main database, set ENC(db). */
encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
if( encoding==0 ) encoding = SQLITE_UTF8;
#else
**
** If the new record does not need to be inserted into the sorter,
** jump to the next iteration of the loop. If the pSort->labelOBLopt
** value is not zero, then it is a label of where to jump. Otherwise,
** just bypass the row insert logic. See the header comment on the
** sqlite3WhereOrderByLimitOptLabel() function for additional info.
*/
int iCsr = pSort->iECursor;
sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0);
iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE,
iCsr, 0, regBase+nOBSat, nExpr-nOBSat);
VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_Delete, iCsr);
}
if( regRecord==0 ){
regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase);
}
if( pSort->sortFlags & SORTFLAG_UseSorter ){
op = OP_SorterInsert;
}else{
op = OP_IdxInsert;
}
sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
regBase+nOBSat, nBase-nOBSat);
if( iSkip ){
sqlite3VdbeChangeP2(v, iSkip,
pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v));
}
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
pSort->addrPushEnd = sqlite3VdbeCurrentAddr(v)-1;
#endif
}
/*
** Add code to implement the OFFSET
*/
static void codeOffset(
Vdbe *v, /* Generate code into this VM */
int iOffset, /* Register holding the offset counter */
int iContinue /* Jump here to skip the current record */
){
if( iOffset>0 ){
sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
VdbeComment((v, "OFFSET"));
}
}
/*
** Add code that will check to make sure the array of registers starting at
** iMem form a distinct entry. This is used by both "SELECT DISTINCT ..." and
** distinct aggregates ("SELECT count(DISTINCT <expr>) ..."). Three strategies
** are available. Which is used depends on the value of parameter eTnctType,
** as follows:
**
** WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP:
** Build an ephemeral table that contains all entries seen before and
** skip entries which have been seen before.
**
** Parameter iTab is the cursor number of an ephemeral table that must
** be opened before the VM code generated by this routine is executed.
** The ephemeral cursor table is queried for a record identical to the
** record formed by the current array of registers. If one is found,
** jump to VM address addrRepeat. Otherwise, insert a new record into
** the ephemeral cursor and proceed.
**
** The returned value in this case is a copy of parameter iTab.
**
** WHERE_DISTINCT_ORDERED:
** In this case rows are being delivered sorted order. The ephemeral
** table is not required. Instead, the current set of values
** is compared against previous row. If they match, the new row
** is not distinct and control jumps to VM address addrRepeat. Otherwise,
** the VM program proceeds with processing the new row.
**
** The returned value in this case is the register number of the first
** in an array of registers used to store the previous result row so that
** it can be compared to the next. The caller must ensure that this
** register is initialized to NULL. (The fixDistinctOpenEph() routine
** will take care of this initialization.)
**
** WHERE_DISTINCT_UNIQUE:
** In this case it has already been determined that the rows are distinct.
** No special action is required. The return value is zero.
**
** Parameter pEList is the list of expressions used to generated the
** contents of each row. It is used by this routine to determine (a)
** how many elements there are in the array of registers and (b) the
** collation sequences that should be used for the comparisons if
** eTnctType is WHERE_DISTINCT_ORDERED.
*/
static int codeDistinct(
Parse *pParse, /* Parsing and code generating context */
int eTnctType, /* WHERE_DISTINCT_* value */
int iTab, /* A sorting index used to test for distinctness */
int addrRepeat, /* Jump to here if not distinct */
ExprList *pEList, /* Expression for each element */
int regElem /* First element */
){
int iRet = 0;
int nResultCol = pEList->nExpr;
Vdbe *v = pParse->pVdbe;
switch( eTnctType ){
case WHERE_DISTINCT_ORDERED: {
int i;
int iJump; /* Jump destination */
int regPrev; /* Previous row content */
/* Allocate space for the previous row */
iRet = regPrev = pParse->nMem+1;
pParse->nMem += nResultCol;
iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
for(i=0; i<nResultCol; i++){
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
if( i<nResultCol-1 ){
sqlite3VdbeAddOp3(v, OP_Ne, regElem+i, iJump, regPrev+i);
VdbeCoverage(v);
}else{
sqlite3VdbeAddOp3(v, OP_Eq, regElem+i, addrRepeat, regPrev+i);
VdbeCoverage(v);
}
sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
** No adjustments necessary. This function is a no-op.
**
** WHERE_DISTINCT_UNIQUE:
**
** The ephemeral table is not needed. So change the
** OP_OpenEphemeral opcode into an OP_Noop.
**
** WHERE_DISTINCT_ORDERED:
**
** The ephemeral table is not needed. But we do need register
** iVal to be initialized to NULL. So change the OP_OpenEphemeral
** into an OP_Null on the iVal register.
*/
static void fixDistinctOpenEph(
Parse *pParse, /* Parsing and code generating context */
int eTnctType, /* WHERE_DISTINCT_* value */
int iVal, /* Value returned by codeDistinct() */
int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */
){
if( pParse->nErr==0
&& (eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED)
){
Vdbe *v = pParse->pVdbe;
sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
}
if( eTnctType==WHERE_DISTINCT_ORDERED ){
/* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared
** bit on the first register of the previous value. This will cause the
** OP_Ne added in codeDistinct() to always fail on the first iteration of
** the loop even if the first row is all NULLs. */
VdbeOp *pOp = sqlite3VdbeGetOp(v, iOpenEphAddr);
pOp->opcode = OP_Null;
pOp->p1 = 1;
pOp->p2 = iVal;
}
}
}
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
/*
** This function is called as part of inner-loop generation for a SELECT
** statement with an ORDER BY that is not optimized by an index. It
** determines the expressions, if any, that the sorter-reference
** optimization should be used for. The sorter-reference optimization
** is used for SELECT queries like:
**
** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10
**
** If the optimization is used for expression "bigblob", then instead of
** storing values read from that column in the sorter records, the PK of
** the row from table t1 is stored instead. Then, as records are extracted from
** the sorter to return to the user, the required value of bigblob is
** retrieved directly from table t1. If the values are very large, this
** can be more efficient than storing them directly in the sorter records.
**
** The ExprList_item.fg.bSorterRef flag is set for each expression in pEList
** for which the sorter-reference optimization should be enabled.
** Additionally, the pSort->aDefer[] array is populated with entries
** for all cursors required to evaluate all selected expressions. Finally.
** output variable (*ppExtra) is set to an expression list containing
** expressions for all extra PK values that should be stored in the
** sorter records.
*/
static void selectExprDefer(
Parse *pParse, /* Leave any error here */
SortCtx *pSort, /* Sorter context */
ExprList *pEList, /* Expressions destined for sorter */
ExprList **ppExtra /* Expressions to append to sorter record */
){
int i;
int nDefer = 0;
ExprList *pExtra = 0;
for(i=0; i<pEList->nExpr; i++){
struct ExprList_item *pItem = &pEList->a[i];
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
Table *pTab;
if( pExpr->op==TK_COLUMN
&& pExpr->iColumn>=0
&& ALWAYS( ExprUseYTab(pExpr) )
&& (pTab = pExpr->y.pTab)!=0
&& IsOrdinaryTable(pTab)
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)!=0
){
int j;
for(j=0; j<nDefer; j++){
if( pSort->aDefer[j].iCsr==pExpr->iTable ) break;
}
if( j==nDefer ){
if( nDefer==ArraySize(pSort->aDefer) ){
continue;
}else{
int nKey = 1;
int k;
Index *pPk = 0;
if( !HasRowid(pTab) ){
pPk = sqlite3PrimaryKeyIndex(pTab);
nKey = pPk->nKeyCol;
}
for(k=0; k<nKey; k++){
Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pExpr->iTable;
assert( ExprUseYTab(pNew) );
pNew->y.pTab = pExpr->y.pTab;
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
}
}
pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
pSort->aDefer[nDefer].nKey = nKey;
nDefer++;
}
}
pItem->fg.bSorterRef = 1;
}
}
}
*/
if( hasDistinct ){
int eType = pDistinct->eTnctType;
int iTab = pDistinct->tabTnct;
assert( nResultCol==p->pEList->nExpr );
iTab = codeDistinct(pParse, eType, iTab, iContinue, p->pEList, regResult);
fixDistinctOpenEph(pParse, eType, iTab, pDistinct->addrTnct);
if( pSort==0 ){
codeOffset(v, p->iOffset, iContinue);
}
}
switch( eDest ){
/* In this mode, write each query result to the key of the temporary
** table iParm.
*/
#ifndef SQLITE_OMIT_COMPOUND_SELECT
case SRT_Union: {
int r1;
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
break;
}
/* Construct a record from the query result, but instead of
** saving that record, use it as a key to delete elements from
** the temporary table iParm.
*/
case SRT_Except: {
sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol);
break;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
/* Store the result as data using a unique key.
*/
case SRT_Fifo:
case SRT_DistFifo:
case SRT_Table:
case SRT_EphemTab: {
int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1);
testcase( eDest==SRT_Table );
testcase( eDest==SRT_EphemTab );
testcase( eDest==SRT_Fifo );
testcase( eDest==SRT_DistFifo );
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG)
/* A destination of SRT_Table and a non-zero iSDParm2 parameter means
** that this is an "UPDATE ... FROM" on a virtual table or view. In this
** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC.
** This does not affect operation in any way - it just allows MakeRecord
** to process OPFLAG_NOCHANGE values without an assert() failing. */
if( eDest==SRT_Table && pDest->iSDParm2 ){
sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
}
#endif
#ifndef SQLITE_OMIT_CTE
if( eDest==SRT_DistFifo ){
/* If the destination is DistFifo, then cursor (iParm+1) is open
** on an ephemeral index. If the current row is already present
** in the index, do not write it to the output. If not, add the
** current row to the index and proceed with writing it to the
** output table as well. */
int addr = sqlite3VdbeCurrentAddr(v) + 4;
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
VdbeCoverage(v);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol);
assert( pSort==0 );
}
#endif
if( pSort ){
assert( regResult==regOrig );
pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg);
}else{
int r2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3ReleaseTempReg(pParse, r2);
}
sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1);
break;
}
case SRT_Upfrom: {
if( pSort ){
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
int i2 = pDest->iSDParm2;
int r1 = sqlite3GetTempReg(pParse);
/* If the UPDATE FROM join is an aggregate that matches no rows, it
** might still be trying to return one row, because that is what
** aggregates do. Don't record that empty row in the output table. */
sqlite3VdbeAddOp2(v, OP_IsNull, regResult, iBreak); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord,
regResult+(i2<0), nResultCol-(i2<0), r1);
if( i2<0 ){
sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regResult);
}else{
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, i2);
}
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
/* If we are creating a set for an "expr IN (SELECT ...)" construct,
** then there should be a single item on the stack. Write this
** item into the set table with bogus data.
*/
case SRT_Set: {
if( pSort ){
/* At first glance you would think we could optimize out the
** ORDER BY in this case since the order of entries in the set
** does not matter. But there might be a LIMIT clause, in which
** case the order does matter */
}else{
int r1 = sqlite3GetTempReg(pParse);
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
if( pDest->iSDParm2 ){
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
regResult, nResultCol);
ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
}
sqlite3ReleaseTempReg(pParse, r1);
}
break;
}
/* If any row exist in the result set, record that fact and abort.
*/
case SRT_Exists: {
sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);
/* The LIMIT clause will terminate the loop for us */
break;
}
/* If this is a scalar select that is part of an expression, then
** store the results in the appropriate memory cell or array of
** memory cells and break out of the scan loop.
*/
case SRT_Mem: {
if( pSort ){
assert( nResultCol<=pDest->nSdst );
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
assert( nResultCol==pDest->nSdst );
assert( regResult==iParm );
/* The LIMIT clause will jump out of the loop for us */
}
break;
}
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
case SRT_Coroutine: /* Send data to a co-routine */
case SRT_Output: { /* Return the results */
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
if( pSort ){
pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol,
nPrefixReg);
}else if( eDest==SRT_Coroutine ){
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}else{
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
}
break;
}
#ifndef SQLITE_OMIT_CTE
/* Write the results into a priority queue that is order according to
** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an
** index with pSO->nExpr+2 columns. Build a key using pSO for the first
** pSO->nExpr columns, then make sure all keys are unique by adding a
** final OP_Sequence column. The last column is the record as a blob.
*/
case SRT_DistQueue:
case SRT_Queue: {
int nKey;
int r1, r2, r3;
int addrTest = 0;
ExprList *pSO;
pSO = pDest->pOrderBy;
assert( pSO );
nKey = pSO->nExpr;
r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3GetTempRange(pParse, nKey+2);
r3 = r2+nKey+1;
if( eDest==SRT_DistQueue ){
/* If the destination is DistQueue, then cursor (iParm+1) is open
** on a second ephemeral index that holds all values every previously
** added to the queue. */
addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0,
regResult, nResultCol);
VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3);
if( eDest==SRT_DistQueue ){
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
}
for(i=0; i<nKey; i++){
sqlite3VdbeAddOp2(v, OP_SCopy,
regResult + pSO->a[i].u.x.iOrderByCol - 1,
r2+i);
}
sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempRange(pParse, r2, nKey+2);
break;
}
#endif /* SQLITE_OMIT_CTE */
#if !defined(SQLITE_OMIT_TRIGGER)
/* Discard the results. This is used for SELECT statements inside
** the body of a TRIGGER. The purpose of such selects is to call
** user-defined functions that have side effects. We do not care
** about the actual results of the select.
*/
default: {
assert( eDest==SRT_Discard );
break;
}
#endif
}
/* Jump to the end of the loop if the LIMIT is reached. Except, if
** there is a sorter, in which case the sorter has already limited
** the output for us.
*/
if( pSort==0 && p->iLimit ){
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
}
}
/*
** Allocate a KeyInfo object sufficient for an index of N key columns and
** X extra columns.
*/
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
int nExtra = (N+X)*(sizeof(CollSeq*)+1);
KeyInfo *p;
assert( X>=0 );
if( NEVER(N+X>0xffff) ) return (KeyInfo*)sqlite3OomFault(db);
p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra);
return z;
}
#ifndef SQLITE_OMIT_EXPLAIN
/*
** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
** is a no-op. Otherwise, it adds a single row of output to the EQP result,
** where the caption is of the form:
**
** "USE TEMP B-TREE FOR xxx"
**
** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which
** is determined by the zUsage argument.
*/
static void explainTempTable(Parse *pParse, const char *zUsage){
ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage));
}
/*
** Assign expression b to lvalue a. A second, no-op, version of this macro
** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
** in sqlite3Select() to assign values to structure member variables that
** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
** code with #ifndef directives.
*/
# define explainSetInteger(a, b) a = b
#else
/* No-op versions of the explainXXX() functions and macros. */
# define explainTempTable(y,z)
# define explainSetInteger(y,z)
#endif
/*
** If the inner loop was generated using a non-null pOrderBy argument,
** then the results were placed in a sorter. After the loop is terminated
** we need to run the sorter and output the results. The following
** routine generates the code needed to do that.
*/
static void generateSortTail(
Parse *pParse, /* Parsing context */
Select *p, /* The SELECT statement */
SortCtx *pSort, /* Information on the ORDER BY clause */
int nColumn, /* Number of columns of data */
SelectDest *pDest /* Write the sorted results here */
){
Vdbe *v = pParse->pVdbe; /* The prepared statement */
int addrBreak = pSort->labelDone; /* Jump here to exit loop */
int addrContinue = sqlite3VdbeMakeLabel(pParse);/* Jump here for next cycle */
int addr; /* Top of output loop. Jump for Next. */
int addrOnce = 0;
int iTab;
ExprList *pOrderBy = pSort->pOrderBy;
int eDest = pDest->eDest;
int iParm = pDest->iSDParm;
int regRow;
int regRowid;
int iCol;
int nKey; /* Number of key columns in sorter record */
int iSortTab; /* Sorter cursor to read from */
int i;
int bSeq; /* True if sorter record includes seq. no. */
int nRefKey = 0;
struct ExprList_item *aOutEx = p->pEList->a;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int addrExplain; /* Address of OP_Explain instruction */
#endif
nKey = pOrderBy->nExpr - pSort->nOBSat;
if( pSort->nOBSat==0 || nKey==1 ){
ExplainQueryPlan2(addrExplain, (pParse, 0,
"USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat?"LAST TERM OF ":""
));
}else{
ExplainQueryPlan2(addrExplain, (pParse, 0,
"USE TEMP B-TREE FOR LAST %d TERMS OF ORDER BY", nKey
));
}
sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd);
sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush);
assert( addrBreak<0 );
if( pSort->labelBkOut ){
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
sqlite3VdbeGoto(v, addrBreak);
sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
}
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
/* Open any cursors needed for sorter-reference expressions */
for(i=0; i<pSort->nDefer; i++){
Table *pTab = pSort->aDefer[i].pTab;
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead);
nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey);
}
#endif
iTab = pSort->iECursor;
if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){
if( eDest==SRT_Mem && p->iOffset ){
sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst);
}
regRowid = 0;
regRow = pDest->iSdst;
}else{
regRowid = sqlite3GetTempReg(pParse);
if( eDest==SRT_EphemTab || eDest==SRT_Table ){
regRow = sqlite3GetTempReg(pParse);
nColumn = 0;
}else{
regRow = sqlite3GetTempRange(pParse, nColumn);
}
}
if( pSort->sortFlags & SORTFLAG_UseSorter ){
int regSortOut = ++pParse->nMem;
iSortTab = pParse->nTab++;
if( pSort->labelBkOut ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut,
nKey+1+nColumn+nRefKey);
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
VdbeCoverage(v);
assert( p->iLimit==0 && p->iOffset==0 );
sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab);
bSeq = 0;
}else{
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
iSortTab = iTab;
bSeq = 1;
if( p->iOffset>0 ){
sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
}
}
for(i=0, iCol=nKey+bSeq-1; i<nColumn; i++){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
if( aOutEx[i].fg.bSorterRef ) continue;
#endif
if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
}
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
if( pSort->nDefer ){
int iKey = iCol+1;
int regKey = sqlite3GetTempRange(pParse, nRefKey);
for(i=0; i<pSort->nDefer; i++){
int iCsr = pSort->aDefer[i].iCsr;
** inserted into the Queue table. The iDistinct table keeps a copy of all rows
** that have ever been inserted into Queue and causes duplicates to be
** discarded. If the operator is UNION ALL, then duplicates are allowed.
**
** If the query has an ORDER BY, then entries in the Queue table are kept in
** ORDER BY order and the first entry is extracted for each cycle. Without
** an ORDER BY, the Queue table is just a FIFO.
**
** If a LIMIT clause is provided, then the iteration stops after LIMIT rows
** have been output to pDest. A LIMIT of zero means to output no rows and a
** negative LIMIT means to output all rows. If there is also an OFFSET clause
** with a positive value, then the first OFFSET outputs are discarded rather
** than being sent to pDest. The LIMIT count does not begin until after OFFSET
** rows have been skipped.
*/
static void generateWithRecursiveQuery(
Parse *pParse, /* Parsing context */
Select *p, /* The recursive SELECT to be coded */
SelectDest *pDest /* What to do with query results */
){
SrcList *pSrc = p->pSrc; /* The FROM clause of the recursive query */
int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */
Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
Select *pSetup; /* The setup query */
Select *pFirstRec; /* Left-most recursive term */
int addrTop; /* Top of the loop */
int addrCont, addrBreak; /* CONTINUE and BREAK addresses */
int iCurrent = 0; /* The Current table */
int regCurrent; /* Register holding Current table */
int iQueue; /* The Queue table */
int iDistinct = 0; /* To ensure unique results if UNION */
int eDest = SRT_Fifo; /* How to write to Queue */
SelectDest destQueue; /* SelectDest targeting the Queue table */
int i; /* Loop counter */
int rc; /* Result code */
ExprList *pOrderBy; /* The ORDER BY clause */
Expr *pLimit; /* Saved LIMIT and OFFSET */
int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin ){
sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries");
return;
}
#endif
/* Obtain authorization to do a recursive query */
if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
/* Process the LIMIT and OFFSET clauses, if they exist */
addrBreak = sqlite3VdbeMakeLabel(pParse);
p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit;
regLimit = p->iLimit;
regOffset = p->iOffset;
p->pLimit = 0;
p->iLimit = p->iOffset = 0;
pOrderBy = p->pOrderBy;
/* Locate the cursor number of the Current table */
for(i=0; ALWAYS(i<pSrc->nSrc); i++){
if( pSrc->a[i].fg.isRecursive ){
iCurrent = pSrc->a[i].iCursor;
break;
}
}
/* Allocate cursors numbers for Queue and Distinct. The cursor number for
** the Distinct table must be exactly one greater than Queue in order
** for the SRT_DistFifo and SRT_DistQueue destinations to work. */
iQueue = pParse->nTab++;
if( p->op==TK_UNION ){
eDest = pOrderBy ? SRT_DistQueue : SRT_DistFifo;
iDistinct = pParse->nTab++;
}else{
eDest = pOrderBy ? SRT_Queue : SRT_Fifo;
}
sqlite3SelectDestInit(&destQueue, eDest, iQueue);
/* Allocate cursors for Current, Queue, and Distinct. */
regCurrent = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
if( pOrderBy ){
KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
(char*)pKeyInfo, P4_KEYINFO);
destQueue.pOrderBy = pOrderBy;
}else{
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
}
VdbeComment((v, "Queue table"));
if( iDistinct ){
p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
p->selFlags |= SF_UsesEphemeral;
}
/* Detach the ORDER BY clause from the compound SELECT */
p->pOrderBy = 0;
/* Figure out how many elements of the compound SELECT are part of the
** recursive query. Make sure no recursive elements use aggregate
** functions. Mark the recursive elements as UNION ALL even if they
** are really UNION because the distinctness will be enforced by the
** iDistinct table. pFirstRec is left pointing to the left-most
** recursive term of the CTE.
*/
for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){
if( pFirstRec->selFlags & SF_Aggregate ){
sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
goto end_of_recursive_query;
}
pFirstRec->op = TK_ALL;
if( (pFirstRec->pPrior->selFlags & SF_Recursive)==0 ) break;
}
/* Store the results of the setup-query in Queue. */
pSetup = pFirstRec->pPrior;
pSetup->pNext = 0;
ExplainQueryPlan((pParse, 1, "SETUP"));
rc = sqlite3Select(pParse, pSetup, &destQueue);
pSetup->pNext = p;
if( rc ) goto end_of_recursive_query;
/* Find the next row in the Queue and output that row */
addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v);
/* Transfer the next row in Queue over to Current */
sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */
if( pOrderBy ){
sqlite3VdbeAddOp3(v, OP_Column, iQueue, pOrderBy->nExpr+1, regCurrent);
}else{
sqlite3VdbeAddOp2(v, OP_RowData, iQueue, regCurrent);
}
sqlite3VdbeAddOp1(v, OP_Delete, iQueue);
/* Output the single row in Current */
addrCont = sqlite3VdbeMakeLabel(pParse);
codeOffset(v, regOffset, addrCont);
selectInnerLoop(pParse, p, iCurrent,
0, 0, pDest, addrCont, addrBreak);
/* Generate code to handle the case of A<B
*/
VdbeNoopComment((v, "A-lt-B subroutine"));
addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
sqlite3VdbeGoto(v, labelCmpr);
/* Generate code to handle the case of A==B
*/
if( op==TK_ALL ){
addrAeqB = addrAltB;
}else if( op==TK_INTERSECT ){
addrAeqB = addrAltB;
addrAltB++;
}else{
VdbeNoopComment((v, "A-eq-B subroutine"));
addrAeqB =
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v);
sqlite3VdbeGoto(v, labelCmpr);
}
/* Generate code to handle the case of A>B
*/
VdbeNoopComment((v, "A-gt-B subroutine"));
addrAgtB = sqlite3VdbeCurrentAddr(v);
if( op==TK_ALL || op==TK_UNION ){
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
}
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
sqlite3VdbeGoto(v, labelCmpr);
/* This code runs once to initialize everything.
*/
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v);
/* Implement the main merge loop
*/
sqlite3VdbeResolveLabel(v, labelCmpr);
sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
(char*)pKeyMerge, P4_KEYINFO);
sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v);
/* Jump to the this point in order to terminate the query.
*/
sqlite3VdbeResolveLabel(v, labelEnd);
/* Make arrangements to free the 2nd and subsequent arms of the compound
** after the parse has finished */
if( pSplit->pPrior ){
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSplit->pPrior);
}
pSplit->pPrior = pPrior;
pPrior->pNext = pSplit;
sqlite3ExprListDelete(db, pPrior->pOrderBy);
pPrior->pOrderBy = 0;
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
ExplainQueryPlanPop(pParse);
return pParse->nErr!=0;
}
#endif
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* An instance of the SubstContext object describes an substitution edit
** to be performed on a parse tree.
**
** All references to columns in table iTable are to be replaced by corresponding
** expressions in pEList.
**
** ## About "isOuterJoin":
**
** The isOuterJoin column indicates that the replacement will occur into a
** position in the parent that is NULL-able due to an OUTER JOIN. Either the
** target slot in the parent is the right operand of a LEFT JOIN, or one of
** the left operands of a RIGHT JOIN. In either case, we need to potentially
** bypass the substituted expression with OP_IfNullRow.
**
** Suppose the original expression is an integer constant. Even though the table
** has the nullRow flag set, because the expression is an integer constant,
** it will not be NULLed out. So instead, we insert an OP_IfNullRow opcode
** that checks to see if the nullRow flag is set on the table. If the nullRow
** flag is set, then the value in the register is set to NULL and the original
** expression is bypassed. If the nullRow flag is not set, then the original
** expression runs to populate the register.
**
** Example where this is needed:
**
** CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
** CREATE TABLE t2(x INT UNIQUE);
**
** SELECT a,b,m,x FROM t1 LEFT JOIN (SELECT 59 AS m,x FROM t2) ON b=x;
**
** When the subquery on the right side of the LEFT JOIN is flattened, we
** have to add OP_IfNullRow in front of the OP_Integer that implements the
** "m" value of the subquery so that a NULL will be loaded instead of 59
** when processing a non-matched row of the left.
*/
typedef struct SubstContext {
Parse *pParse; /* The parsing context */
int iTable; /* Replace references to this table */
int iNewTable; /* New table number */
int isOuterJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */
int nSelDepth; /* Depth of sub-query recursion. Top==1 */
ExprList *pEList; /* Replacement expressions */
ExprList *pCList; /* Collation sequences for replacement expr */
} SubstContext;
/* Forward Declarations */
static void substExprList(SubstContext*, ExprList*);
static void substSelect(SubstContext*, Select*, int);
/*
** Scan through the expression pExpr. Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
** entry in pEList. (But leave references to the ROWID column
** unchanged.)
**
** This routine is part of the flattening procedure. A subquery
** whose result set is defined by pEList appears as entry in the
** FROM clause of a SELECT such that the VDBE cursor assigned to that
** FORM clause entry is iTable. This routine makes the necessary
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
static Expr *substExpr(
SubstContext *pSubst, /* Description of the substitution */
Expr *pExpr /* Expr in which substitution occurs */
){
if( pExpr==0 ) return 0;
if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON)
&& pExpr->w.iJoin==pSubst->iTable
){
testcase( ExprHasProperty(pExpr, EP_InnerON) );
pExpr->w.iJoin = pSubst->iNewTable;
}
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pSubst->iTable
&& !ExprHasProperty(pExpr, EP_FixedCol)
){
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
}else
#endif
{
Expr *pNew;
int iColumn;
Expr *pCopy;
Expr ifNullRow;
iColumn = pExpr->iColumn;
assert( iColumn>=0 );
assert( pSubst->pEList!=0 && iColumn<pSubst->pEList->nExpr );
assert( pExpr->pRight==0 );
pCopy = pSubst->pEList->a[iColumn].pExpr;
if( sqlite3ExprIsVector(pCopy) ){
sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
}else{
sqlite3 *db = pSubst->pParse->db;
if( pSubst->isOuterJoin
&& (pCopy->op!=TK_COLUMN || pCopy->iTable!=pSubst->iNewTable)
){
memset(&ifNullRow, 0, sizeof(ifNullRow));
ifNullRow.op = TK_IF_NULL_ROW;
ifNullRow.pLeft = pCopy;
ifNullRow.iTable = pSubst->iNewTable;
ifNullRow.iColumn = -99;
ifNullRow.flags = EP_IfNullRow;
pCopy = &ifNullRow;
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pNew);
return pExpr;
}
if( pSubst->isOuterJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
if( pNew->op==TK_TRUEFALSE ){
pNew->u.iValue = sqlite3ExprTruthValue(pNew);
SrcList *pSrc;
SrcItem *pItem;
int i;
if( !p ) return;
pSubst->nSelDepth++;
do{
substExprList(pSubst, p->pEList);
substExprList(pSubst, p->pGroupBy);
substExprList(pSubst, p->pOrderBy);
p->pHaving = substExpr(pSubst, p->pHaving);
p->pWhere = substExpr(pSubst, p->pWhere);
pSrc = p->pSrc;
assert( pSrc!=0 );
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
if( pItem->fg.isSubquery ){
substSelect(pSubst, pItem->u4.pSubq->pSelect, 1);
}
if( pItem->fg.isTabFunc ){
substExprList(pSubst, pItem->u1.pFuncArg);
}
}
}while( doPrior && (p = p->pPrior)!=0 );
pSubst->nSelDepth--;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** pSelect is a SELECT statement and pSrcItem is one item in the FROM
** clause of that SELECT.
**
** This routine scans the entire SELECT statement and recomputes the
** pSrcItem->colUsed mask.
*/
static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
SrcItem *pItem;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
pItem = pWalker->u.pSrcItem;
if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue;
if( pExpr->iColumn<0 ) return WRC_Continue;
pItem->colUsed |= sqlite3ExprColUsed(pExpr);
return WRC_Continue;
}
static void recomputeColumnsUsed(
Select *pSelect, /* The complete SELECT statement */
SrcItem *pSrcItem /* Which FROM clause item to recompute */
){
Walker w;
if( NEVER(pSrcItem->pSTab==0) ) return;
memset(&w, 0, sizeof(w));
w.xExprCallback = recomputeColumnsUsedExpr;
w.xSelectCallback = sqlite3SelectWalkNoop;
w.u.pSrcItem = pSrcItem;
pSrcItem->colUsed = 0;
sqlite3WalkSelect(&w, pSelect);
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Assign new cursor numbers to each of the items in pSrc. For each
** new cursor number assigned, set an entry in the aCsrMap[] array
** to map the old cursor number to the new:
**
** aCsrMap[iOld+1] = iNew;
**
** The array is guaranteed by the caller to be large enough for all
** existing cursor numbers in pSrc. aCsrMap[0] is the array size.
**
** If pSrc contains any sub-selects, call this routine recursively
** on the FROM clause of each such sub-select, with iExcept set to -1.
*/
static void srclistRenumberCursors(
Parse *pParse, /* Parse context */
int *aCsrMap, /* Array to store cursor mappings in */
SrcList *pSrc, /* FROM clause to renumber */
int iExcept /* FROM clause item to skip */
){
int i;
SrcItem *pItem;
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
if( i!=iExcept ){
Select *p;
assert( pItem->iCursor < aCsrMap[0] );
if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor+1]==0 ){
aCsrMap[pItem->iCursor+1] = pParse->nTab++;
}
pItem->iCursor = aCsrMap[pItem->iCursor+1];
if( pItem->fg.isSubquery ){
for(p=pItem->u4.pSubq->pSelect; p; p=p->pPrior){
srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
}
}
}
}
}
/*
** *piCursor is a cursor number. Change it if it needs to be mapped.
*/
static void renumberCursorDoMapping(Walker *pWalker, int *piCursor){
int *aCsrMap = pWalker->u.aiCol;
int iCsr = *piCursor;
if( iCsr < aCsrMap[0] && aCsrMap[iCsr+1]>0 ){
*piCursor = aCsrMap[iCsr+1];
}
}
/*
** Expression walker callback used by renumberCursors() to update
** Expr objects to match newly assigned cursor numbers.
*/
static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
int op = pExpr->op;
if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){
renumberCursorDoMapping(pWalker, &pExpr->iTable);
}
if( ExprHasProperty(pExpr, EP_OuterON) ){
renumberCursorDoMapping(pWalker, &pExpr->w.iJoin);
}
return WRC_Continue;
}
/*
** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
** of the SELECT statement passed as the second argument, and to each
** cursor in the FROM clause of any FROM clause sub-selects, recursively.
** Except, do not assign a new cursor number to the iExcept'th element in
** the FROM clause of (*p). Update all expressions and other references
** to refer to the new cursor numbers.
**
** Argument aCsrMap is an array that may be used for temporary working
** space. Two guarantees are made by the caller:
**
** * the array is larger than the largest cursor number used within the
** select statement passed as an argument, and
**
** * the array entries for all cursor numbers that do *not* appear in
** FROM clauses of the select statement as described above are
** initialized to zero.
*/
static void renumberCursors(
Parse *pParse, /* Parse context */
Select *p, /* Select to renumber cursors within */
int iExcept, /* FROM clause item to skip */
int *aCsrMap /* Working space */
){
Walker w;
srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept);
memset(&w, 0, sizeof(w));
w.u.aiCol = aCsrMap;
w.xExprCallback = renumberCursorsCb;
w.xSelectCallback = sqlite3SelectWalkNoop;
sqlite3WalkSelect(&w, p);
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
** If pSel is not part of a compound SELECT, return a pointer to its
** expression list. Otherwise, return a pointer to the expression list
** of the leftmost SELECT in the compound.
*/
static ExprList *findLeftmostExprlist(Select *pSel){
while( pSel->pPrior ){
pSel = pSel->pPrior;
}
return pSel->pEList;
}
/*
** Return true if any of the result-set columns in the compound query
** have incompatible affinities on one or more arms of the compound.
*/
static int compoundHasDifferentAffinities(Select *p){
int ii;
ExprList *pList;
assert( p!=0 );
assert( p->pEList!=0 );
assert( p->pPrior!=0 );
pList = p->pEList;
for(ii=0; ii<pList->nExpr; ii++){
char aff;
Select *pSub1;
assert( pList->a[ii].pExpr!=0 );
aff = sqlite3ExprAffinity(pList->a[ii].pExpr);
for(pSub1=p->pPrior; pSub1; pSub1=pSub1->pPrior){
assert( pSub1->pEList!=0 );
assert( pSub1->pEList->nExpr>ii );
assert( pSub1->pEList->a[ii].pExpr!=0 );
if( sqlite3ExprAffinity(pSub1->pEList->a[ii].pExpr)!=aff ){
return 1;
}
}
}
return 0;
}
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries as a performance optimization.
** This routine returns 1 if it makes changes and 0 if no flattening occurs.
**
** To understand the concept of flattening, consider the following
** query:
** an ORDER BY clause. Ticket #3773. We could relax this constraint
** somewhat by saying that the terms of the ORDER BY clause must
** appear as unmodified result columns in the outer query. But we
** have other optimizations in mind to deal with that case.
**
** (21) If the subquery uses LIMIT then the outer query may not be
** DISTINCT. (See ticket [752e1646fc]).
**
** (22) The subquery may not be a recursive CTE.
**
** (23) If the outer query is a recursive CTE, then the sub-query may not be
** a compound query. This restriction is because transforming the
** parent to a compound query confuses the code that handles
** recursive queries in multiSelect().
**
** (**) We no longer attempt to flatten aggregate subqueries. Was:
** The subquery may not be an aggregate that uses the built-in min() or
** or max() functions. (Without this restriction, a query like:
** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
** return the value X for which Y was maximal.)
**
** (25) If either the subquery or the parent query contains a window
** function in the select list or ORDER BY clause, flattening
** is not attempted.
**
** (26) The subquery may not be the right operand of a RIGHT JOIN.
** See also (3) for restrictions on LEFT JOIN.
**
** (27) The subquery may not contain a FULL or RIGHT JOIN unless it
** is the first element of the parent query. Two subcases:
** (27a) the subquery is not a compound query.
** (27b) the subquery is a compound query and the RIGHT JOIN occurs
** in any arm of the compound query. (See also (17g).)
**
** (28) The subquery is not a MATERIALIZED CTE. (This is handled
** in the caller before ever reaching this routine.)
**
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
** uses aggregates.
**
** If flattening is not attempted, this routine is a no-op and returns 0.
** If flattening is attempted this routine returns 1.
**
** All of the expression analysis must occur on both the outer query and
** the subquery before this routine runs.
*/
static int flattenSubquery(
Parse *pParse, /* Parsing context */
Select *p, /* The parent or outer SELECT statement */
int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
int isAgg /* True if outer SELECT uses aggregate functions */
){
const char *zSavedAuthContext = pParse->zAuthContext;
Select *pParent; /* Current UNION ALL term of the other query */
Select *pSub; /* The inner query or "subquery" */
Select *pSub1; /* Pointer to the rightmost select in sub-query */
SrcList *pSrc; /* The FROM clause of the outer query */
SrcList *pSubSrc; /* The FROM clause of the subquery */
int iParent; /* VDBE cursor number of the pSub result set temp table */
int iNewParent = -1;/* Replacement table for iParent */
int isOuterJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
int i; /* Loop counter */
Expr *pWhere; /* The WHERE clause */
SrcItem *pSubitem; /* The subquery */
sqlite3 *db = pParse->db;
Walker w; /* Walker to persist agginfo data */
int *aCsrMap = 0;
/* Check to see if flattening is permitted. Return 0 if not.
*/
assert( p!=0 );
assert( p->pPrior==0 );
if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
pSubitem = &pSrc->a[iFrom];
iParent = pSubitem->iCursor;
assert( pSubitem->fg.isSubquery );
pSub = pSubitem->u4.pSubq->pSelect;
assert( pSub!=0 );
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin || pSub->pWin ) return 0; /* Restriction (25) */
#endif
pSubSrc = pSub->pSrc;
assert( pSubSrc );
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
** because they could be computed at compile-time. But when LIMIT and OFFSET
** became arbitrary expressions, we were forced to add restrictions (13)
** and (14). */
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
return 0; /* Restriction (15) */
}
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */
if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
return 0; /* Restrictions (8)(9) */
}
if( p->pOrderBy && pSub->pOrderBy ){
return 0; /* Restriction (11) */
}
if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
return 0; /* Restriction (21) */
}
if( pSub->selFlags & (SF_Recursive) ){
return 0; /* Restrictions (22) */
}
/*
** If the subquery is the right operand of a LEFT JOIN, then the
** subquery may not be a join itself (3a). Example of why this is not
** allowed:
**
pSubitem->pSTab = 0;
p->pOrderBy = 0;
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlite3SelectDup(db, p, 0);
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->op = TK_ALL;
pSubitem->pSTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
pNew->selId = ++pParse->nSelect;
if( aCsrMap && ALWAYS(db->mallocFailed==0) ){
renumberCursors(pParse, pNew, iFrom, aCsrMap);
}
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
p->pPrior = pNew;
TREETRACE(0x4,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
assert( pSubitem->fg.isSubquery==0 );
}
sqlite3DbFree(db, aCsrMap);
if( db->mallocFailed ){
assert( pSubitem->fg.fixedSchema==0 );
assert( pSubitem->fg.isSubquery==0 );
assert( pSubitem->u4.zDatabase==0 );
sqlite3SrcItemAttachSubquery(pParse, pSubitem, pSub1, 0);
return 1;
}
/* Defer deleting the Table object associated with the
** subquery until code generation is
** complete, since there may still exist Expr.pTab entries that
** refer to the subquery even after flattening. Ticket #3346.
**
** pSubitem->pSTab is always non-NULL by test restrictions and tests above.
*/
if( ALWAYS(pSubitem->pSTab!=0) ){
Table *pTabToDel = pSubitem->pSTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel);
testcase( pToplevel->earlyCleanup );
}else{
pTabToDel->nTabRef--;
}
pSubitem->pSTab = 0;
}
/* The following loop runs once for each term in a compound-subquery
** flattening (as described above). If we are doing a different kind
** of flattening - a flattening other than a compound-subquery flattening -
** then this loop only runs once.
**
** This loop moves all of the FROM elements of the subquery into the
** the FROM clause of the outer query. Before doing this, remember
** the cursor number for the original outer query FROM element in
** iParent. The iParent cursor will never be used. Subsequent code
** will scan expressions looking for iParent references and replace
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = pSubitem->fg.jointype;
assert( pSub!=0 );
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
/* The subquery uses a single slot of the FROM clause of the outer
** query. If the subquery has more than one element in its FROM clause,
** then expand the outer query to make space for it to hold all elements
** of the subquery.
**
** Example:
**
** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
**
** The outer query has 3 slots in its FROM clause. One slot of the
** outer query (the middle slot) is used by the subquery. The next
** block of code will expand the outer query FROM clause to 4 slots.
** The middle slot is expanded to two slots in order to make space
** for the two elements in the FROM clause of the subquery.
*/
if( nSubSrc>1 ){
pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
if( pSrc==0 ) break;
pParent->pSrc = pSrc;
pSubitem = &pSrc->a[iFrom];
}
/* Transfer the FROM clause terms from the subquery into the
** outer query.
*/
iNewParent = pSubSrc->a[0].iCursor;
for(i=0; i<nSubSrc; i++){
SrcItem *pItem = &pSrc->a[i+iFrom];
assert( pItem->fg.isTabFunc==0 );
assert( pItem->fg.isSubquery
|| pItem->fg.fixedSchema
|| pItem->u4.zDatabase==0 );
if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
*pItem = pSubSrc->a[i];
pItem->fg.jointype |= (jointype & JT_LTORJ);
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSubitem->fg.jointype |= jointype;
/* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
**
** Example:
**
** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
** \ \_____________ subquery __________/ /
** \_____________________ outer query ______________________________/
Select *pSel;
Table *pTab;
assert( pFrom->fg.isSubquery );
assert( pFrom->u4.pSubq!=0 );
pSel = pFrom->u4.pSubq->pSelect;
assert( pSel );
pFrom->pSTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
if( pTab==0 ) return SQLITE_NOMEM;
pTab->nTabRef = 1;
if( pFrom->zAlias ){
pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias);
}else{
pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom);
}
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
pTab->eTabType = TABTYP_VIEW;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
/* The usual case - do not allow ROWID on a subquery */
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
#else
/* Legacy compatibility mode */
pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid;
#endif
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
/*
** Check the N SrcItem objects to the right of pBase. (N might be zero!)
** If any of those SrcItem objects have a USING clause containing zName
** then return true.
**
** If N is zero, or none of the N SrcItem objects to the right of pBase
** contains a USING clause, or if none of the USING clauses contain zName,
** then return false.
*/
static int inAnyUsingClause(
const char *zName, /* Name we are looking for */
SrcItem *pBase, /* The base SrcItem. Looking at pBase[1] and following */
int N /* How many SrcItems to check */
){
while( N>0 ){
N--;
pBase++;
if( pBase->fg.isUsing==0 ) continue;
if( NEVER(pBase->u3.pUsing==0) ) continue;
if( sqlite3IdListIndex(pBase->u3.pUsing, zName)>=0 ) return 1;
}
return 0;
}
/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
**
** (1) Make sure VDBE cursor numbers have been assigned to every
** element of the FROM clause.
**
** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
** defines FROM clause. When views appear in the FROM clause,
** fill pTabList->a[].pSelect with a copy of the SELECT statement
** that implements the view. A copy is made of the view's SELECT
** statement so that we can freely modify or delete that statement
** without worrying about messing up the persistent representation
** of the view.
**
** (3) Add terms to the WHERE clause to accommodate the NATURAL keyword
** on joins and the ON and USING clause of joins.
**
** (4) Scan the list of columns in the result set (pEList) looking
** for instances of the "*" operator or the TABLE.* operator.
** If found, expand each "*" to be every column in every table
** and TABLE.* to be every column in TABLE.
**
*/
static int selectExpander(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i, j, k, rc;
SrcList *pTabList;
ExprList *pEList;
SrcItem *pFrom;
sqlite3 *db = pParse->db;
Expr *pE, *pRight, *pExpr;
u16 selFlags = p->selFlags;
u32 elistFlags = 0;
p->selFlags |= SF_Expanded;
if( db->mallocFailed ){
return WRC_Abort;
}
assert( p->pSrc!=0 );
if( (selFlags & SF_Expanded)!=0 ){
return WRC_Prune;
}
if( pWalker->eCode ){
/* Renumber selId because it has been copied from a view */
p->selId = ++pParse->nSelect;
}
pTabList = p->pSrc;
pEList = p->pEList;
if( pParse->pWith && (p->selFlags & SF_View) ){
if( p->pWith==0 ){
p->pWith = (With*)sqlite3DbMallocZero(db, SZ_WITH(1) );
if( p->pWith==0 ){
return WRC_Abort;
}
}
p->pWith->bView = 1;
}
sqlite3WithPush(pParse, p->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
** the FROM clause of the SELECT statement.
*/
sqlite3SrcListAssignCursors(pParse, pTabList);
/* Look up every table named in the FROM clause of the select. If
** an entry of the FROM clause is a subquery instead of a table or view,
** then create a transient table structure to describe the subquery.
*/
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab;
assert( pFrom->fg.isRecursive==0 || pFrom->pSTab!=0 );
if( pFrom->pSTab ) continue;
assert( pFrom->fg.isRecursive==0 );
if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
Select *pSel;
assert( pFrom->fg.isSubquery && pFrom->u4.pSubq!=0 );
pSel = pFrom->u4.pSubq->pSelect;
/* A sub-query in the FROM clause of a SELECT */
assert( pSel!=0 );
assert( pFrom->pSTab==0 );
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
#ifndef SQLITE_OMIT_CTE
}else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
if( rc>1 ) return WRC_Abort;
pTab = pFrom->pSTab;
assert( pTab!=0 );
#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pSTab==0 );
pFrom->pSTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
if( pTab->nTabRef>=0xffff ){
sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
pTab->zName);
pFrom->pSTab = 0;
return WRC_Abort;
}
pTab->nTabRef++;
if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
return WRC_Abort;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
if( !IsOrdinaryTable(pTab) ){
i16 nCol;
u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->fg.isSubquery==0 );
if( IsView(pTab) ){
if( (db->flags & SQLITE_EnableView)==0
&& pTab->pSchema!=db->aDb[1].pSchema
){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
pTab->zName);
}
sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1);
}
NameContext *pNC
){
int i;
assert( pAggInfo!=0 );
assert( pAggInfo->iFirstReg==0 );
pNC->ncFlags |= NC_InAggFunc;
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
assert( pExpr->op==TK_FUNCTION || pExpr->op==TK_AGG_FUNCTION );
assert( ExprUseXList(pExpr) );
sqlite3ExprAnalyzeAggList(pNC, pExpr->x.pList);
if( pExpr->pLeft ){
assert( pExpr->pLeft->op==TK_ORDER );
assert( ExprUseXList(pExpr->pLeft) );
sqlite3ExprAnalyzeAggList(pNC, pExpr->pLeft->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
assert( !IsWindowFunc(pExpr) );
if( ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3ExprAnalyzeAggregates(pNC, pExpr->y.pWin->pFilter);
}
#endif
}
pNC->ncFlags &= ~NC_InAggFunc;
}
/*
** An index on expressions is being used in the inner loop of an
** aggregate query with a GROUP BY clause. This routine attempts
** to adjust the AggInfo object to take advantage of index and to
** perhaps use the index as a covering index.
**
*/
static void optimizeAggregateUseOfIndexedExpr(
Parse *pParse, /* Parsing context */
Select *pSelect, /* The SELECT statement being processed */
AggInfo *pAggInfo, /* The aggregate info */
NameContext *pNC /* Name context used to resolve agg-func args */
){
assert( pAggInfo->iFirstReg==0 );
assert( pSelect!=0 );
assert( pSelect->pGroupBy!=0 );
pAggInfo->nColumn = pAggInfo->nAccumulator;
if( ALWAYS(pAggInfo->nSortingColumn>0) ){
int mx = pSelect->pGroupBy->nExpr - 1;
int j, k;
for(j=0; j<pAggInfo->nColumn; j++){
k = pAggInfo->aCol[j].iSorterColumn;
if( k>mx ) mx = k;
}
pAggInfo->nSortingColumn = mx+1;
}
analyzeAggFuncArgs(pAggInfo, pNC);
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x20 ){
IndexedExpr *pIEpr;
TREETRACE(0x20, pParse, pSelect,
("AggInfo (possibly) adjusted for Indexed Exprs\n"));
sqlite3TreeViewSelect(0, pSelect, 0);
for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){
printf("data-cursor=%d index={%d,%d}\n",
pIEpr->iDataCur, pIEpr->iIdxCur, pIEpr->iIdxCol);
sqlite3TreeViewExpr(0, pIEpr->pExpr, 0);
}
printAggInfo(pAggInfo);
}
#else
UNUSED_PARAMETER(pSelect);
UNUSED_PARAMETER(pParse);
#endif
}
/*
** Walker callback for aggregateConvertIndexedExprRefToColumn().
*/
static int aggregateIdxEprRefToColCallback(Walker *pWalker, Expr *pExpr){
AggInfo *pAggInfo;
struct AggInfo_col *pCol;
UNUSED_PARAMETER(pWalker);
if( pExpr->pAggInfo==0 ) return WRC_Continue;
if( pExpr->op==TK_AGG_COLUMN ) return WRC_Continue;
if( pExpr->op==TK_AGG_FUNCTION ) return WRC_Continue;
if( pExpr->op==TK_IF_NULL_ROW ) return WRC_Continue;
pAggInfo = pExpr->pAggInfo;
if( NEVER(pExpr->iAgg>=pAggInfo->nColumn) ) return WRC_Continue;
assert( pExpr->iAgg>=0 );
pCol = &pAggInfo->aCol[pExpr->iAgg];
pExpr->op = TK_AGG_COLUMN;
pExpr->iTable = pCol->iTable;
pExpr->iColumn = pCol->iColumn;
ExprClearProperty(pExpr, EP_Skip|EP_Collate|EP_Unlikely);
return WRC_Prune;
}
/*
** Convert every pAggInfo->aFunc[].pExpr such that any node within
** those expressions that has pAppInfo set is changed into a TK_AGG_COLUMN
** opcode.
*/
static void aggregateConvertIndexedExprRefToColumn(AggInfo *pAggInfo){
int i;
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = aggregateIdxEprRefToColCallback;
for(i=0; i<pAggInfo->nFunc; i++){
sqlite3WalkExpr(&w, pAggInfo->aFunc[i].pFExpr);
}
}
/*
** Allocate a block of registers so that there is one register for each
** pAggInfo->aCol[] and pAggInfo->aFunc[] entry in pAggInfo. The first
** register in this block is stored in pAggInfo->iFirstReg.
**
** This routine may only be called once for each AggInfo object. Prior
** to calling this routine:
**
** * The aCol[] and aFunc[] arrays may be modified
** * The AggInfoColumnReg() and AggInfoFuncReg() macros may not be used
**
Vdbe *v = pParse->pVdbe;
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
if( pParse->nErr ) return;
pList = pF->pFExpr->x.pList;
if( pF->iOBTab>=0 ){
/* For an ORDER BY aggregate, calls to OP_AggStep were deferred. Inputs
** were stored in emphermal table pF->iOBTab. Here, we extract those
** inputs (in ORDER BY order) and make all calls to OP_AggStep
** before doing the OP_AggFinal call. */
int iTop; /* Start of loop for extracting columns */
int nArg; /* Number of columns to extract */
int nKey; /* Key columns to be skipped */
int regAgg; /* Extract into this array */
int j; /* Loop counter */
assert( pF->pFunc!=0 );
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
if( pF->bOBPayload==0 ){
nKey = 0;
}else{
assert( pF->pFExpr->pLeft!=0 );
assert( ExprUseXList(pF->pFExpr->pLeft) );
assert( pF->pFExpr->pLeft->x.pList!=0 );
nKey = pF->pFExpr->pLeft->x.pList->nExpr;
if( ALWAYS(!pF->bOBUnique) ) nKey++;
}
iTop = sqlite3VdbeAddOp1(v, OP_Rewind, pF->iOBTab); VdbeCoverage(v);
for(j=nArg-1; j>=0; j--){
sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, nKey+j, regAgg+j);
}
if( pF->bUseSubtype ){
int regSubtype = sqlite3GetTempReg(pParse);
int iBaseCol = nKey + nArg + (pF->bOBPayload==0 && pF->bOBUnique==0);
for(j=nArg-1; j>=0; j--){
sqlite3VdbeAddOp3(v, OP_Column, pF->iOBTab, iBaseCol+j, regSubtype);
sqlite3VdbeAddOp2(v, OP_SetSubtype, regSubtype, regAgg+j);
}
sqlite3ReleaseTempReg(pParse, regSubtype);
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u16)nArg);
sqlite3VdbeAddOp2(v, OP_Next, pF->iOBTab, iTop+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, iTop);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
}
sqlite3VdbeAddOp2(v, OP_AggFinal, AggInfoFuncReg(pAggInfo,i),
pList ? pList->nExpr : 0);
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
}
}
/*
** Generate code that will update the accumulator memory cells for an
** aggregate based on the current cursor position.
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
**
** For an ORDER BY aggregate, the actual accumulator memory cell update
** is deferred until after all input rows have been received, so that they
** can be run in the requested order. In that case, instead of invoking
** OP_AggStep to update the accumulator, just add the arguments that would
** have been passed into OP_AggStep into the sorting ephemeral table
** (along with the appropriate sort key).
*/
static void updateAccumulator(
Parse *pParse,
int regAcc,
AggInfo *pAggInfo,
int eDistinctType
){
Vdbe *v = pParse->pVdbe;
int i;
int regHit = 0;
int addrHitTest = 0;
struct AggInfo_func *pF;
struct AggInfo_col *pC;
assert( pAggInfo->iFirstReg>0 );
if( pParse->nErr ) return;
pAggInfo->directMode = 1;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
int nArg;
int addrNext = 0;
int regAgg;
int regAggSz = 0;
int regDistinct = 0;
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
assert( !IsWindowFunc(pF->pFExpr) );
assert( pF->pFunc!=0 );
pList = pF->pFExpr->x.pList;
if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
if( pAggInfo->nAccumulator
&& (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
&& regAcc
){
/* If regAcc==0, there there exists some min() or max() function
** without a FILTER clause that will ensure the magnet registers
** are populated. */
if( regHit==0 ) regHit = ++pParse->nMem;
/* If this is the first row of the group (regAcc contains 0), clear the
** "magnet" register regHit so that the accumulator registers
** are populated if the FILTER clause jumps over the the
** invocation of min() or max() altogether. Or, if this is not
** the first row (regAcc contains 1), set the magnet register so that
** the accumulators are not populated unless the min()/max() is invoked
** and indicates that they should be. */
sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit);
}
addrNext = sqlite3VdbeMakeLabel(pParse);
ExprSetProperty(pWhere, EP_IntValue);
assert( p->pWhere!=0 );
pSub->pSrc->a[0].fg.fromExists = 1;
pSub->pSrc->a[0].fg.jointype |= JT_CROSS;
p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc);
if( pSubWhere ){
p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere);
pSub->pWhere = 0;
}
pSub->pSrc = 0;
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSub);
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x100000 ){
TREETRACE(0x100000,pParse,p,
("After EXISTS-to-JOIN optimization:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
existsToJoin(pParse, p, pSubWhere);
}
}
}
}
/*
** Type used for Walker callbacks by selectCheckOnClauses().
*/
typedef struct CheckOnCtx CheckOnCtx;
struct CheckOnCtx {
SrcList *pSrc; /* SrcList for this context */
int iJoin; /* Cursor numbers must be =< than this */
CheckOnCtx *pParent; /* Parent context */
};
/*
** True if the SrcList passed as the only argument contains at least
** one RIGHT or FULL JOIN. False otherwise.
*/
#define hasRightJoin(pSrc) (((pSrc)->a[0].fg.jointype & JT_LTORJ)!=0)
/*
** The xExpr callback for the search of invalid ON clause terms.
*/
static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx;
/* Check if pExpr is root or near-root of an ON clause constraint that needs
** to be checked to ensure that it does not refer to tables in its FROM
** clause to the right of itself. i.e. it is either:
**
** + an ON clause on an OUTER join, or
** + an ON clause on an INNER join within a FROM that features at
** least one RIGHT or FULL join.
*/
if( (ExprHasProperty(pExpr, EP_OuterON))
|| (ExprHasProperty(pExpr, EP_InnerON) && hasRightJoin(pCtx->pSrc))
){
/* If CheckOnCtx.iJoin is already set, then fall through and process
** this expression node as normal. Or, if CheckOnCtx.iJoin is still 0,
** set it to the cursor number of the RHS of the join to which this
** ON expression was attached and then iterate through the entire
** expression. */
assert( pCtx->iJoin==0 || pCtx->iJoin==pExpr->w.iJoin );
if( pCtx->iJoin==0 ){
pCtx->iJoin = pExpr->w.iJoin;
sqlite3WalkExprNN(pWalker, pExpr);
pCtx->iJoin = 0;
return WRC_Prune;
}
}
if( pExpr->op==TK_COLUMN ){
/* A column expression. Find the SrcList (if any) to which it refers.
** Then, if CheckOnCtx.iJoin indicates that this expression is part of an
** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it
** does not refer to a table to the right of CheckOnCtx.iJoin. */
do {
SrcList *pSrc = pCtx->pSrc;
int iTab = pExpr->iTable;
if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
if( pCtx->iJoin && iTab>pCtx->iJoin ){
sqlite3ErrorMsg(pWalker->pParse,
"ON clause references tables to its right");
return WRC_Abort;
}
break;
}
pCtx = pCtx->pParent;
}while( pCtx );
}
return WRC_Continue;
}
/*
** The xSelect callback for the search of invalid ON clause terms.
*/
static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx;
if( pSelect->pSrc==pCtx->pSrc || pSelect->pSrc->nSrc==0 ){
return WRC_Continue;
}else{
CheckOnCtx sCtx;
memset(&sCtx, 0, sizeof(sCtx));
sCtx.pSrc = pSelect->pSrc;
sCtx.pParent = pCtx;
pWalker->u.pCheckOnCtx = &sCtx;
sqlite3WalkSelect(pWalker, pSelect);
pWalker->u.pCheckOnCtx = pCtx;
pSelect->selFlags &= ~SF_OnToWhere;
return WRC_Prune;
}
}
/*
** Check all ON clauses in pSelect to verify that they do not reference
** columns to the right.
*/
static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
Walker w;
CheckOnCtx sCtx;
if( distFlag!=0 && eDist!=WHERE_DISTINCT_NOOP ){
struct AggInfo_func *pF = &pAggInfo->aFunc[0];
fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
}
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
/* Aggregate functions without GROUP BY. tag-select-0820 */
Table *pTab;
if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
/* tag-select-0821
**
** If isSimpleCount() returns a pointer to a Table structure, then
** the SQL statement is of the form:
**
** SELECT count(*) FROM <tbl>
**
** where the Table structure returned represents table <tbl>.
**
** This statement is so common that it is optimized specially. The
** OP_Count instruction is executed either on the intkey table that
** contains the data for table <tbl> or on one of its indexes. It
** is better to execute the op on an index, as indexes are almost
** always spread across less pages than their corresponding tables.
*/
const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */
Index *pIdx; /* Iterator variable */
KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */
Index *pBest = 0; /* Best index found so far */
Pgno iRoot = pTab->tnum; /* Root page of scanned b-tree */
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
/* Search for the index that has the lowest scan cost.
**
** (2011-04-15) Do not do a full scan of an unordered index.
**
** (2013-10-03) Do not count the entries in a partial index.
**
** In practice the KeyInfo structure will not be used. It is only
** passed to keep OP_OpenRead happy.
*/
if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
if( !p->pSrc->a[0].fg.notIndexed ){
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->bUnordered==0
&& pIdx->szIdxRow<pTab->szTabRow
&& pIdx->pPartIdxWhere==0
&& (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
){
pBest = pIdx;
}
}
}
if( pBest ){
iRoot = pBest->tnum;
pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest);
}
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, (int)iRoot, iDb, 1);
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
}
assignAggregateRegisters(pParse, pAggInfo);
sqlite3VdbeAddOp2(v, OP_Count, iCsr, AggInfoFuncReg(pAggInfo,0));
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
explainSimpleCount(pParse, pTab, pBest);
}else{
/* The general case of an aggregate query without GROUP BY
** tag-select-0822 */
int regAcc = 0; /* "populate accumulators" flag */
ExprList *pDistinct = 0;
u16 distFlag = 0;
int eDist;
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
** will contain 0 the first time the inner loop runs, and 1 thereafter.
** The code generated by updateAccumulator() uses this to ensure
** that the accumulator registers are (a) updated only once if
** there are no min() or max functions or (b) always updated for the
** first row visited by the aggregate, so that they are updated at
** least once even if the FILTER clause means the min() or max()
** function visits zero rows. */
if( pAggInfo->nAccumulator ){
for(i=0; i<pAggInfo->nFunc; i++){
if( ExprHasProperty(pAggInfo->aFunc[i].pFExpr, EP_WinFunc) ){
continue;
}
if( pAggInfo->aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ){
break;
}
}
if( i==pAggInfo->nFunc ){
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
}else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
assert( ExprUseXList(pAggInfo->aFunc[0].pFExpr) );
pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
}
assignAggregateRegisters(pParse, pAggInfo);
/* This case runs if the aggregate has no GROUP BY clause. The
** processing is much simpler since there is only a single row
** of output.
*/
assert( p->pGroupBy==0 );
resetAccumulator(pParse, pAggInfo);
/* If this query is a candidate for the min/max optimization, then
** minMaxFlag will have been previously set to either
** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will
** be an appropriate ORDER BY expression for the optimization.
*/
assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );
** being updated.
*/
static int indexColumnIsBeingUpdated(
Index *pIdx, /* The index to check */
int iCol, /* Which column of the index to check */
int *aXRef, /* aXRef[j]>=0 if column j is being updated */
int chngRowid /* true if the rowid is being updated */
){
i16 iIdxCol = pIdx->aiColumn[iCol];
assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */
if( iIdxCol>=0 ){
return aXRef[iIdxCol]>=0;
}
assert( iIdxCol==XN_EXPR );
assert( pIdx->aColExpr!=0 );
assert( pIdx->aColExpr->a[iCol].pExpr!=0 );
return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr,
aXRef,chngRowid);
}
/*
** Check to see if index pIdx is a partial index whose conditional
** expression might change values due to an UPDATE. Return true if
** the index is subject to change and false if the index is guaranteed
** to be unchanged. This is an optimization. False-positives are a
** performance degradation, but false-negatives can result in a corrupt
** index and incorrect answers.
**
** aXRef[j] will be non-negative if column j of the original table is
** being updated. chngRowid will be true if the rowid of the table is
** being updated.
*/
static int indexWhereClauseMightChange(
Index *pIdx, /* The index to check */
int *aXRef, /* aXRef[j]>=0 if column j is being updated */
int chngRowid /* true if the rowid is being updated */
){
if( pIdx->pPartIdxWhere==0 ) return 0;
return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere,
aXRef, chngRowid);
}
/*
** Allocate and return a pointer to an expression of type TK_ROW with
** Expr.iColumn set to value (iCol+1). The resolver will modify the
** expression to be a TK_COLUMN reading column iCol of the first
** table in the source-list (pSrc->a[0]).
*/
static Expr *exprRowColumn(Parse *pParse, int iCol){
Expr *pRet = sqlite3PExpr(pParse, TK_ROW, 0, 0);
if( pRet ) pRet->iColumn = iCol+1;
return pRet;
}
/*
** Assuming both the pLimit and pOrderBy parameters are NULL, this function
** generates VM code to run the query:
**
** SELECT <other-columns>, pChanges FROM pTabList WHERE pWhere
**
** and write the results to the ephemeral table already opened as cursor
** iEph. None of pChanges, pTabList or pWhere are modified or consumed by
** this function, they must be deleted by the caller.
**
** Or, if pLimit and pOrderBy are not NULL, and pTab is not a view:
**
** SELECT <other-columns>, pChanges FROM pTabList
** WHERE pWhere
** GROUP BY <other-columns>
** ORDER BY pOrderBy LIMIT pLimit
**
** If pTab is a view, the GROUP BY clause is omitted.
**
** Exactly how results are written to table iEph, and exactly what
** the <other-columns> in the query above are is determined by the type
** of table pTabList->a[0].pTab.
**
** If the table is a WITHOUT ROWID table, then argument pPk must be its
** PRIMARY KEY. In this case <other-columns> are the primary key columns
** of the table, in order. The results of the query are written to ephemeral
** table iEph as index keys, using OP_IdxInsert.
**
** If the table is actually a view, then <other-columns> are all columns of
** the view. The results are written to the ephemeral table iEph as records
** with automatically assigned integer keys.
**
** If the table is a virtual or ordinary intkey table, then <other-columns>
** is its rowid. For a virtual table, the results are written to iEph as
** records with automatically assigned integer keys For intkey tables, the
** rowid value in <other-columns> is used as the integer key, and the
** remaining fields make up the table record.
*/
static void updateFromSelect(
Parse *pParse, /* Parse context */
int iEph, /* Cursor for open eph. table */
Index *pPk, /* PK if table 0 is WITHOUT ROWID */
ExprList *pChanges, /* List of expressions to return */
SrcList *pTabList, /* List of tables to select from */
Expr *pWhere, /* WHERE clause for query */
ExprList *pOrderBy, /* ORDER BY clause */
Expr *pLimit /* LIMIT clause */
){
int i;
SelectDest dest;
Select *pSelect = 0;
ExprList *pList = 0;
ExprList *pGrp = 0;
Expr *pLimit2 = 0;
ExprList *pOrderBy2 = 0;
sqlite3 *db = pParse->db;
Table *pTab = pTabList->a[0].pSTab;
SrcList *pSrc;
Expr *pWhere2;
int eDest;
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( pOrderBy && pLimit==0 ) {
sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on UPDATE");
return;
}
pOrderBy2 = sqlite3ExprListDup(db, pOrderBy, 0);
for(i=0; i<pTab->nCol; i++){
pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
}
eDest = SRT_Table;
}else{
eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( pLimit ){
pGrp = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
}
#endif
}
assert( pChanges!=0 || pParse->db->mallocFailed );
if( pChanges ){
for(i=0; i<pChanges->nExpr; i++){
pList = sqlite3ExprListAppend(pParse, pList,
sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
);
}
}
pSelect = sqlite3SelectNew(pParse, pList,
pSrc, pWhere2, pGrp, 0, pOrderBy2,
SF_UFSrcCheck|SF_IncludeHidden|SF_UpdateFrom, pLimit2
);
if( pSelect ) pSelect->selFlags |= SF_OrderByReqd;
sqlite3SelectDestInit(&dest, eDest, iEph);
dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
sqlite3Select(pParse, pSelect, &dest);
sqlite3SelectDelete(db, pSelect);
}
/*
** Process an UPDATE statement.
**
** UPDATE OR IGNORE tbl SET a=b, c=d FROM tbl2... WHERE e<5 AND f NOT NULL;
** \_______/ \_/ \______/ \_____/ \________________/
** onError | pChanges | pWhere
** \_______________________/
** pTabList
*/
SQLITE_PRIVATE void sqlite3Update(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table in which we should change things */
ExprList *pChanges, /* Things to be changed */
Expr *pWhere, /* The WHERE clause. May be null */
int onError, /* How to handle constraint errors */
ExprList *pOrderBy, /* ORDER BY clause. May be null */
Expr *pLimit, /* LIMIT clause. May be null */
Upsert *pUpsert /* ON CONFLICT clause, or null */
){
int i, j, k; /* Loop counters */
Table *pTab; /* The table to be updated */
int addrTop = 0; /* VDBE instruction address of the start of the loop */
WhereInfo *pWInfo = 0; /* Information about the WHERE clause */
Vdbe *v; /* The virtual database engine */
Index *pIdx; /* For looping over indices */
Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
int nIdx; /* Number of indices that need updating */
int nAllIdx; /* Total number of indexes */
int iBaseCur; /* Base cursor number */
int iDataCur; /* Cursor for the canonical data btree */
int iIdxCur; /* Cursor for the first index */
sqlite3 *db; /* The database structure */
int *aRegIdx = 0; /* Registers for to each index and the main table */
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
u8 *aToOpen; /* 1 for tables and indices to be opened */
u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */
u8 chngRowid; /* Rowid changed in a normal table */
u8 chngKey; /* Either chngPk or chngRowid */
Expr *pRowidExpr = 0; /* Expression defining the new record number */
int iRowidExpr = -1; /* Index of "rowid=" (or IPK) assignment in pChanges */
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
int eOnePass; /* ONEPASS_XXX value from where.c */
int hasFK; /* True if foreign key processing is required */
int labelBreak; /* Jump here to break out of UPDATE loop */
int labelContinue; /* Jump here to continue next step of UPDATE loop */
int flags; /* Flags for sqlite3WhereBegin() */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True when updating a view (INSTEAD OF trigger) */
Trigger *pTrigger; /* List of triggers on pTab, if required */
int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
#endif
int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */
int iEph = 0; /* Ephemeral table holding all primary key values */
int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
int addrOpen = 0; /* Address of OP_OpenEphemeral */
int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */
i16 nPk = 0; /* Number of components of the PRIMARY KEY */
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */
int nChangeFrom = 0; /* If there is a FROM, pChanges->nExpr, else 0 */
/* Register Allocations */
int regRowCount = 0; /* A count of rows changed */
int regOldRowid = 0; /* The old rowid */
int regNewRowid = 0; /* The new rowid */
int regNew = 0; /* Content of the NEW.* table in triggers */
int regOld = 0; /* Content of OLD.* table in triggers */
int regRowSet = 0; /* Rowset of rows to be updated */
int regKey = 0; /* composite PRIMARY KEY value */
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
assert( db->pParse==pParse );
if( pParse->nErr ){
goto update_cleanup;
}
assert( db->mallocFailed==0 );
/* Locate the table which we want to update.
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto update_cleanup;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
/* Figure out if we have any triggers and if the table being
** updated is a view.
*/
#ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
isView = IsView(pTab);
assert( pTrigger || tmask==0 );
#else
# define pTrigger 0
# define isView 0
# define tmask 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x10000 ){
sqlite3TreeViewLine(0, "In sqlite3Update() at %s:%d", __FILE__, __LINE__);
sqlite3TreeViewUpdate(pParse->pWith, pTabList, pChanges, pWhere,
onError, pOrderBy, pLimit, pUpsert, pTrigger);
}
#endif
/* If there was a FROM clause, set nChangeFrom to the number of expressions
** in the change-list. Otherwise, set it to 0. There cannot be a FROM
** clause if this function is being called to generate code for part of
** an UPSERT statement. */
nChangeFrom = (pTabList->nSrc>1) ? pChanges->nExpr : 0;
assert( nChangeFrom==0 || pUpsert==0 );
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView && nChangeFrom==0 ){
pWhere = sqlite3LimitWhere(
pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE"
);
pOrderBy = 0;
pLimit = 0;
}
#endif
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto update_cleanup;
}
if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){
goto update_cleanup;
}
/* Allocate a cursors for the main database table and for all indices.
** The index cursors might not be used, but if they are used they
** need to occur right after the database cursor. So go ahead and
** allocate enough space, just in case.
*/
iBaseCur = iDataCur = pParse->nTab++;
iIdxCur = iDataCur+1;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
testcase( pPk!=0 && pPk!=pTab->pIndex );
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
if( pPk==pIdx ){
iDataCur = pParse->nTab;
}
pParse->nTab++;
}
if( pUpsert ){
/* On an UPSERT, reuse the same cursors already opened by INSERT */
iDataCur = pUpsert->iDataCur;
iIdxCur = pUpsert->iIdxCur;
pParse->nTab = iBaseCur;
}
pTabList->a[0].iCursor = iDataCur;
/* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
** Initialize aXRef[] and aToOpen[] to their default values.
*/
aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx+1) + nIdx+2 );
if( aXRef==0 ) goto update_cleanup;
aRegIdx = aXRef+pTab->nCol;
aToOpen = (u8*)(aRegIdx+nIdx+1);
memset(aToOpen, 1, nIdx+1);
aToOpen[nIdx+1] = 0;
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
/* Initialize the name-context */
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto update_cleanup;
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
** column to be updated, make sure we have authorization to change
** that column.
*/
chngRowid = chngPk = 0;
for(i=0; i<pChanges->nExpr; i++){
/* If this is an UPDATE with a FROM clause, do not resolve expressions
** here. The call to sqlite3Select() below will do that. */
if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
j = sqlite3ColumnIndex(pTab, pChanges->a[i].zEName);
if( j>=0 ){
if( j==pTab->iPKey ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
iRowidExpr = i;
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
chngPk = 1;
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
sqlite3ErrorMsg(pParse,
"cannot UPDATE generated column \"%s\"",
pTab->aCol[j].zCnName);
goto update_cleanup;
}
#endif
if( pTab->tabFlags & TF_HasGenerated ){
int bProgress;
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
do{
bProgress = 0;
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]>=0 ) continue;
if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
if( sqlite3ExprReferencesUpdatedColumn(
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
aXRef, chngRowid)
){
aXRef[i] = 99999;
bProgress = 1;
}
}
}while( bProgress );
}
#endif
/* The SET expressions are not actually used inside the WHERE loop.
** So reset the colUsed mask. Unless this is a virtual table. In that
** case, set all bits of the colUsed mask (to ensure that the virtual
** table implementation makes all columns available).
*/
pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0;
hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
/* There is one entry in the aRegIdx[] array for each index on the table
** being updated. Fill in aRegIdx[] with a register number that will hold
** the key for accessing each index.
*/
if( onError==OE_Replace ) bReplace = 1;
for(nAllIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nAllIdx++){
int reg;
if( chngKey || hasFK>1 || pIdx==pPk
|| indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
}else{
reg = 0;
for(i=0; i<pIdx->nKeyCol; i++){
if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
if( onError==OE_Default && pIdx->onError==OE_Replace ){
bReplace = 1;
}
break;
}
}
}
if( reg==0 ) aToOpen[nAllIdx+1] = 0;
aRegIdx[nAllIdx] = reg;
}
aRegIdx[nAllIdx] = ++pParse->nMem; /* Register storing the table record */
if( bReplace ){
/* If REPLACE conflict resolution might be invoked, open cursors on all
** indexes in case they are needed to delete records. */
memset(aToOpen, 1, nIdx+1);
}
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);
/* Allocate required registers. */
if( !IsVirtual(pTab) ){
/* For now, regRowSet and aRegIdx[nAllIdx] share the same register.
** If regRowSet turns out to be needed, then aRegIdx[nAllIdx] will be
** reallocated. aRegIdx[nAllIdx] is the register in which the main
** table record is written. regRowSet holds the RowSet for the
** two-pass update algorithm. */
assert( aRegIdx[nAllIdx]==pParse->nMem );
regRowSet = aRegIdx[nAllIdx];
regOldRowid = regNewRowid = ++pParse->nMem;
if( chngPk || pTrigger || hasFK ){
regOld = pParse->nMem + 1;
pParse->nMem += pTab->nCol;
}
if( chngKey || pTrigger || hasFK ){
regNewRowid = ++pParse->nMem;
}
regNew = pParse->nMem + 1;
pParse->nMem += pTab->nCol;
}
/* Start the view context. */
if( isView ){
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
}
/* If we are trying to update a view, realize that view into
** an ephemeral table.
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( nChangeFrom==0 && isView ){
sqlite3MaterializeView(pParse, pTab,
pWhere, pOrderBy, pLimit, iDataCur
);
pOrderBy = 0;
pLimit = 0;
}
#endif
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pWhere) ){
goto update_cleanup;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Virtual tables must be handled separately */
if( IsVirtual(pTab) ){
updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
pWhere, onError);
goto update_cleanup;
}
#endif
/* Jump to labelBreak to abandon further processing of this UPDATE */
labelContinue = labelBreak = sqlite3VdbeMakeLabel(pParse);
/* Not an UPSERT. Normal processing. Begin by
** initialize the count of updated rows */
if( (db->flags&SQLITE_CountRows)!=0
&& !pParse->pTriggerTab
&& !pParse->nested
&& !pParse->bReturning
&& pUpsert==0
){
regRowCount = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
}
if( nChangeFrom==0 && HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
iEph = pParse->nTab++;
addrOpen = sqlite3VdbeAddOp3(v, OP_OpenEphemeral, iEph, 0, regRowSet);
}else{
assert( pPk!=0 || HasRowid(pTab) );
nPk = pPk ? pPk->nKeyCol : 0;
iPk = pParse->nMem+1;
pParse->nMem += nPk;
pParse->nMem += nChangeFrom;
regKey = ++pParse->nMem;
if( pUpsert==0 ){
int nEphCol = nPk + nChangeFrom + (isView ? pTab->nCol : 0);
iEph = pParse->nTab++;
if( pPk ) sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1);
addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nEphCol);
if( pPk ){
KeyInfo *pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pPk);
if( pKeyInfo ){
pKeyInfo->nAllField = nEphCol;
sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
}
}
if( nChangeFrom ){
updateFromSelect(
pParse, iEph, pPk, pChanges, pTabList, pWhere, pOrderBy, pLimit
);
#ifndef SQLITE_OMIT_SUBQUERY
if( isView ) iDataCur = iEph;
#endif
}
}
}
if( nChangeFrom ){
sqlite3MultiWrite(pParse);
eOnePass = ONEPASS_OFF;
nKey = nPk;
regKey = iPk;
}else{
if( pUpsert ){
/* If this is an UPSERT, then all cursors have already been opened by
** the outer INSERT and the data cursor should be pointing at the row
** that is to be updated. So bypass the code that searches for the
** row(s) to be updated.
*/
pWInfo = 0;
eOnePass = ONEPASS_SINGLE;
sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
bFinishSeek = 0;
}else{
/* Begin the database scan.
**
** Do not consider a single-pass strategy for a multi-row update if
** there is anything that might disrupt the cursor being used to do
** the UPDATE:
** (1) This is a nested UPDATE
** (2) There are triggers
** (3) There are FOREIGN KEY constraints
** (4) There are REPLACE conflict handlers
** (5) There are subqueries in the WHERE clause
*/
flags = WHERE_ONEPASS_DESIRED;
if( !pParse->nested
&& !pTrigger
&& !hasFK
&& !chngKey
&& !bReplace
&& (pWhere==0 || !ExprHasProperty(pWhere, EP_Subquery))
){
flags |= WHERE_ONEPASS_MULTIROW;
}
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur);
if( pWInfo==0 ) goto update_cleanup;
/* A one-pass strategy that might update more than one row may not
** be used if any column of the index used for the scan is being
** updated. Otherwise, if there is an index on "b", statements like
** the following could create an infinite loop:
**
** UPDATE t1 SET b=b+1 WHERE b>?
**
** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI
** strategy that uses an index for which one or more columns are being
** updated. */
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
bFinishSeek = sqlite3WhereUsesDeferredSeek(pWInfo);
if( eOnePass!=ONEPASS_SINGLE ){
sqlite3MultiWrite(pParse);
if( eOnePass==ONEPASS_MULTI ){
int iCur = aiCurOnePass[1];
if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
eOnePass = ONEPASS_OFF;
}
assert( iCur!=iDataCur || !HasRowid(pTab) );
}
}
}
if( HasRowid(pTab) ){
/* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF
** mode, write the rowid into the FIFO. In either of the one-pass modes,
** leave it in register regOldRowid. */
sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
if( eOnePass==ONEPASS_OFF ){
aRegIdx[nAllIdx] = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid);
}else{
if( ALWAYS(addrOpen) ) sqlite3VdbeChangeToNoop(v, addrOpen);
}
}else{
/* Read the PK of the current row into an array of registers. In
** ONEPASS_OFF mode, serialize the array into a record and store it in
** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change
** the OP_OpenEphemeral instruction to a Noop (the ephemeral table
#endif
/* Fire any BEFORE UPDATE triggers. This happens before constraints are
** verified. One could argue that this is wrong.
*/
if( tmask&TRIGGER_BEFORE ){
sqlite3TableAffinity(v, pTab, regNew);
sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue);
if( !isView ){
/* The row-trigger may have deleted the row being updated. In this
** case, jump to the next row. No updates or AFTER triggers are
** required. This behavior - what happens when the row being updated
** is deleted or renamed by a BEFORE trigger - is left undefined in the
** documentation.
*/
if( pPk ){
sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
VdbeCoverage(v);
}else{
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
VdbeCoverage(v);
}
/* After-BEFORE-trigger-reload-loop:
** If it did not delete it, the BEFORE trigger may still have modified
** some of the columns of the row being updated. Load the values for
** all columns not modified by the update statement into their registers
** in case this has happened. Only unmodified columns are reloaded.
** The values computed for modified columns use the values before the
** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26)
** for an example.
*/
for(i=0, k=regNew; i<pTab->nCol; i++, k++){
if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
}else if( aXRef[i]<0 && i!=pTab->iPKey ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
}
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( pTab->tabFlags & TF_HasGenerated ){
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
}
#endif
}
}
if( !isView ){
/* Do constraint checks. */
assert( regOldRowid>0 );
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,
aXRef, 0);
/* If REPLACE conflict handling may have been used, or if the PK of the
** row is changing, then the GenerateConstraintChecks() above may have
** moved cursor iDataCur. Reseek it. */
if( bReplace || chngKey ){
if( pPk ){
sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
}else{
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
}
VdbeCoverage(v);
}
/* Do FK constraint checks. */
if( hasFK ){
sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
}
/* Delete the index entries associated with the current record. */
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);
/* We must run the OP_FinishSeek opcode to resolve a prior
** OP_DeferredSeek if there is any possibility that there have been
** no OP_Column opcodes since the OP_DeferredSeek was issued. But
** we want to avoid the OP_FinishSeek if possible, as running it
** costs CPU cycles. */
if( bFinishSeek ){
sqlite3VdbeAddOp1(v, OP_FinishSeek, iDataCur);
}
/* If changing the rowid value, or if there are foreign key constraints
** to process, delete the old record. Otherwise, add a noop OP_Delete
** to invoke the pre-update hook.
**
** That (regNew==regnewRowid+1) is true is also important for the
** pre-update hook. If the caller invokes preupdate_new(), the returned
** value is copied from memory cell (regNewRowid+1+iCol), where iCol
** is the column index supplied by the user.
*/
assert( regNew==regNewRowid+1 );
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
sqlite3VdbeAddOp3(v, OP_Delete, iDataCur,
OPFLAG_ISUPDATE | ((hasFK>1 || chngKey) ? 0 : OPFLAG_ISNOOP),
regNewRowid
);
if( eOnePass==ONEPASS_MULTI ){
assert( hasFK==0 && chngKey==0 );
sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
}
if( !pParse->nested ){
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
}
#else
if( hasFK>1 || chngKey ){
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
}
#endif
if( hasFK ){
sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);
}
/* Insert the new index entries and the new record. */
sqlite3CompleteInsertion(
** have redundant ON CONFLICT clauses. */
pUpsert->isDup = 1;
}
break;
}
if( pUpsert->pUpsertIdx==0 ){
char zWhich[16];
if( nClause==0 && pUpsert->pNextUpsert==0 ){
zWhich[0] = 0;
}else{
sqlite3_snprintf(sizeof(zWhich),zWhich,"%r ", nClause+1);
}
sqlite3ErrorMsg(pParse, "%sON CONFLICT clause does not match any "
"PRIMARY KEY or UNIQUE constraint", zWhich);
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
/*
** Return true if pUpsert is the last ON CONFLICT clause with a
** conflict target, or if pUpsert is followed by another ON CONFLICT
** clause that targets the INTEGER PRIMARY KEY.
*/
SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert *pUpsert){
Upsert *pNext;
if( NEVER(pUpsert==0) ) return 0;
pNext = pUpsert->pNextUpsert;
while( 1 /*exit-by-return*/ ){
if( pNext==0 ) return 1;
if( pNext->pUpsertTarget==0 ) return 1;
if( pNext->pUpsertIdx==0 ) return 1;
if( !pNext->isDup ) return 0;
pNext = pNext->pNextUpsert;
}
return 0;
}
/*
** Given the list of ON CONFLICT clauses described by pUpsert, and
** a particular index pIdx, return a pointer to the particular ON CONFLICT
** clause that applies to the index. Or, if the index is not subject to
** any ON CONFLICT clause, return NULL.
*/
SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert *pUpsert, Index *pIdx){
while(
pUpsert
&& pUpsert->pUpsertTarget!=0
&& pUpsert->pUpsertIdx!=pIdx
){
pUpsert = pUpsert->pNextUpsert;
}
return pUpsert;
}
/*
** Generate bytecode that does an UPDATE as part of an upsert.
**
** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK.
** In this case parameter iCur is a cursor open on the table b-tree that
** currently points to the conflicting table row. Otherwise, if pIdx
** is not NULL, then pIdx is the constraint that failed and iCur is a
** cursor points to the conflicting row.
*/
SQLITE_PRIVATE void sqlite3UpsertDoUpdate(
Parse *pParse, /* The parsing and code-generating context */
Upsert *pUpsert, /* The ON CONFLICT clause for the upsert */
Table *pTab, /* The table being updated */
Index *pIdx, /* The UNIQUE constraint that failed */
int iCur /* Cursor for pIdx (or pTab if pIdx==NULL) */
){
Vdbe *v = pParse->pVdbe;
sqlite3 *db = pParse->db;
SrcList *pSrc; /* FROM clause for the UPDATE */
int iDataCur;
int i;
Upsert *pTop = pUpsert;
assert( v!=0 );
assert( pUpsert!=0 );
iDataCur = pUpsert->iDataCur;
pUpsert = sqlite3UpsertOfIndex(pTop, pIdx);
VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
if( pIdx && iCur!=iDataCur ){
if( HasRowid(pTab) ){
int regRowid = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid);
sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regRowid);
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
int nPk = pPk->nKeyCol;
int iPk = pParse->nMem+1;
pParse->nMem += nPk;
for(i=0; i<nPk; i++){
int k;
assert( pPk->aiColumn[i]>=0 );
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
VdbeComment((v, "%s.%s", pIdx->zName,
pTab->aCol[pPk->aiColumn[i]].zCnName));
}
sqlite3VdbeVerifyAbortable(v, OE_Abort);
i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
"corrupt database", P4_STATIC);
sqlite3MayAbort(pParse);
sqlite3VdbeJumpHere(v, i);
}
}
/* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does.
** So we have to make a copy before passing it down into sqlite3Update() */
pSrc = sqlite3SrcListDup(db, pTop->pUpsertSrc, 0);
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
}
}
sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert);
** a separate source file for easier editing.
*/
#ifndef SQLITE_WHEREINT_H
#define SQLITE_WHEREINT_H
/* Forward references
*/
typedef struct WhereClause WhereClause;
typedef struct WhereMaskSet WhereMaskSet;
typedef struct WhereOrInfo WhereOrInfo;
typedef struct WhereAndInfo WhereAndInfo;
typedef struct WhereLevel WhereLevel;
typedef struct WhereLoop WhereLoop;
typedef struct WherePath WherePath;
typedef struct WhereTerm WhereTerm;
typedef struct WhereLoopBuilder WhereLoopBuilder;
typedef struct WhereScan WhereScan;
typedef struct WhereOrCost WhereOrCost;
typedef struct WhereOrSet WhereOrSet;
typedef struct WhereMemBlock WhereMemBlock;
typedef struct WhereRightJoin WhereRightJoin;
/*
** This object is a header on a block of allocated memory that will be
** automatically freed when its WInfo object is destructed.
*/
struct WhereMemBlock {
WhereMemBlock *pNext; /* Next block in the chain */
u64 sz; /* Bytes of space */
};
/*
** Extra information attached to a WhereLevel that is a RIGHT JOIN.
*/
struct WhereRightJoin {
int iMatch; /* Cursor used to determine prior matched rows */
int regBloom; /* Bloom filter for iRJMatch */
int regReturn; /* Return register for the interior subroutine */
int addrSubrtn; /* Starting address for the interior subroutine */
int endSubrtn; /* The last opcode in the interior subroutine */
};
/*
** This object contains information needed to implement a single nested
** loop in WHERE clause.
**
** Contrast this object with WhereLoop. This object describes the
** implementation of the loop. WhereLoop describes the algorithm.
** This object contains a pointer to the WhereLoop algorithm as one of
** its elements.
**
** The WhereInfo object contains a single instance of this object for
** each term in the FROM clause (which is to say, for each of the
** nested loops as implemented). The order of WhereLevel objects determines
** the loop nested order, with WhereInfo.a[0] being the outer loop and
** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop.
*/
struct WhereLevel {
int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
int iTabCur; /* The VDBE cursor used to access the table */
int iIdxCur; /* The VDBE cursor used to access pIdx */
int addrBrk; /* Jump here to break out of the loop */
int addrHalt; /* Abort the query due to empty table or similar */
int addrNxt; /* Jump here to start the next IN combination */
int addrSkip; /* Jump here for next iteration of skip-scan */
int addrCont; /* Jump here to continue with the next loop cycle */
int addrFirst; /* First instruction of interior of the loop */
int addrBody; /* Beginning of the body of this loop */
int regBignull; /* big-null flag reg. True if a NULL-scan is needed */
int addrBignull; /* Jump here for next part of big-null scan */
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
int addrLikeRep; /* LIKE range processing address */
#endif
int regFilter; /* Bloom filter */
WhereRightJoin *pRJ; /* Extra information for RIGHT JOIN */
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to end the loop */
union { /* Information that depends on pWLoop->wsFlags */
struct {
int nIn; /* Number of entries in aInLoop[] */
struct InLoop {
int iCur; /* The VDBE cursor used by this IN operator */
int addrInTop; /* Top of the IN loop */
int iBase; /* Base register of multi-key index record */
int nPrefix; /* Number of prior entries in the key */
u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
} *aInLoop; /* Information about each nested IN operator */
} in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
Index *pCoveringIdx; /* Possible covering index for WHERE_MULTI_OR */
} u;
struct WhereLoop *pWLoop; /* The selected WhereLoop object */
Bitmask notReady; /* FROM entries not usable at this level */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int addrVisit; /* Address at which row is visited */
#endif
};
/*
** Each instance of this object represents an algorithm for evaluating one
** term of a join. Every term of the FROM clause will have at least
** one corresponding WhereLoop object (unless INDEXED BY constraints
** prevent a query solution - which is an error) and many terms of the
** FROM clause will have multiple WhereLoop objects, each describing a
** potential way of implementing that FROM-clause term, together with
** dependencies and cost estimates for using the chosen algorithm.
**
** Query planning consists of building up a collection of these WhereLoop
** objects, then computing a particular sequence of WhereLoop objects, with
** one WhereLoop object per FROM clause term, that satisfy all dependencies
** and that minimize the overall cost.
*/
struct WhereLoop {
Bitmask prereq; /* Bitmask of other loops that must run first */
Bitmask maskSelf; /* Bitmask identifying table iTab */
#ifdef SQLITE_DEBUG
char cId; /* Symbolic ID of this loop for debugging use */
#endif
u8 iTab; /* Position in FROM clause of table for this loop */
u8 iSortIdx; /* Sorting index number. 0==None */
LogEst rSetup; /* One-time setup cost (ex: create transient index) */
LogEst rRun; /* Cost of running each loop */
LogEst nOut; /* Estimated number of output rows */
union {
struct { /* Information for internal btree tables */
u16 nEq; /* Number of equality constraints */
u16 nBtm; /* Size of BTM vector */
u16 nTop; /* Size of TOP vector */
u16 nDistinctCol; /* Index columns used to sort for DISTINCT */
Index *pIndex; /* Index used, or NULL */
ExprList *pOrderBy; /* ORDER BY clause if this is really a subquery */
} btree;
struct { /* Information for virtual tables */
int idxNum; /* Index number */
u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */
u32 bOmitOffset : 1; /* True to let virtual table handle offset */
u32 bIdxNumHex : 1; /* Show idxNum as hex in EXPLAIN QUERY PLAN */
i8 isOrdered; /* True if satisfies ORDER BY */
u16 omitMask; /* Terms that may be omitted */
char *idxStr; /* Index identifier string */
u32 mHandleIn; /* Terms to handle as IN(...) instead of == */
} vtab;
} u;
Bitmask prereq; /* Prerequisites */
LogEst rRun; /* Cost of running this subquery */
LogEst nOut; /* Number of outputs for this subquery */
};
/* The WhereOrSet object holds a set of possible WhereOrCosts that
** correspond to the subquery(s) of OR-clause processing. Only the
** best N_OR_COST elements are retained.
*/
#define N_OR_COST 3
struct WhereOrSet {
u16 n; /* Number of valid a[] entries */
WhereOrCost a[N_OR_COST]; /* Set of best costs */
};
/*
** Each instance of this object holds a sequence of WhereLoop objects
** that implement some or all of a query plan.
**
** Think of each WhereLoop object as a node in a graph with arcs
** showing dependencies and costs for travelling between nodes. (That is
** not a completely accurate description because WhereLoop costs are a
** vector, not a scalar, and because dependencies are many-to-one, not
** one-to-one as are graph nodes. But it is a useful visualization aid.)
** Then a WherePath object is a path through the graph that visits some
** or all of the WhereLoop objects once.
**
** The "solver" works by creating the N best WherePath objects of length
** 1. Then using those as a basis to compute the N best WherePath objects
** of length 2. And so forth until the length of WherePaths equals the
** number of nodes in the FROM clause. The best (lowest cost) WherePath
** at the end is the chosen query plan.
*/
struct WherePath {
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
LogEst nRow; /* Estimated number of rows generated by this path */
LogEst rCost; /* Total cost of this path */
LogEst rUnsort; /* Total cost of this path ignoring sorting costs */
i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
};
/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause. Each WHERE
** clause subexpression is separated from the others by AND operators,
** usually, or sometimes subexpressions separated by OR.
**
** All WhereTerms are collected into a single WhereClause structure.
** The following identity holds:
**
** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm
**
** When a term is of the form:
**
** X <op> <expr>
**
** where X is a column name and <op> is one of certain operators,
** then WhereTerm.leftCursor and WhereTerm.u.leftColumn record the
** cursor number and column number for X. WhereTerm.eOperator records
** the <op> using a bitmask encoding defined by WO_xxx below. The
** use of a bitmask encoding for the operator allows us to search
** quickly for terms that match any of several different operators.
**
** A WhereTerm might also be two or more subterms connected by OR:
**
** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
**
** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR
** and the WhereTerm.u.pOrInfo field points to auxiliary information that
** is collected about the OR clause.
**
** If a term in the WHERE clause does not match either of the two previous
** categories, then eOperator==0. The WhereTerm.pExpr field is still set
** to the original subexpression content and wtFlags is set up appropriately
** but no other fields in the WhereTerm object are meaningful.
**
** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers,
** but they do so indirectly. A single WhereMaskSet structure translates
** cursor number into bits and the translated bit is stored in the prereq
** fields. The translation is used in order to maximize the number of
** bits that will fit in a Bitmask. The VDBE cursor numbers might be
** spread out over the non-negative integers. For example, the cursor
** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The WhereMaskSet
** translates these sparse cursor numbers into consecutive integers
** beginning with 0 in order to make the best possible use of the available
** bits in the Bitmask. So, in the example above, the cursor numbers
** would be mapped into integers 0 through 7.
**
** The number of terms in a join is limited by the number of bits
** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
** is only able to process joins with 64 or fewer tables.
*/
struct WhereTerm {
Expr *pExpr; /* Pointer to the subexpression that is this term */
WhereClause *pWC; /* The clause this term is part of */
LogEst truthProb; /* Probability of truth for this expression */
u16 wtFlags; /* TERM_xxx bit flags. See below */
u16 eOperator; /* A WO_xx value describing <op> */
u8 nChild; /* Number of children that must disable us */
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
int iParent; /* Disable pWC->a[iParent] when this term disabled */
int leftCursor; /* Cursor number of X in "X <op> <expr>" */
#ifdef SQLITE_DEBUG
int iTerm; /* Which WhereTerm is this, for debug purposes */
#endif
union {
struct {
int leftColumn; /* Column number of X in "X <op> <expr>" */
int iField; /* Field in (?,?,?) IN (SELECT...) vector */
} x; /* Opcode other than OP_OR or OP_AND */
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
} u;
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
};
/*
** Allowed values of WhereTerm.wtFlags
*/
#define TERM_DYNAMIC 0x0001 /* Need to call sqlite3ExprDelete(db, pExpr) */
#define TERM_VIRTUAL 0x0002 /* Added by the optimizer. Do not code */
#define TERM_CODED 0x0004 /* This term is already coded */
#define TERM_COPIED 0x0008 /* Has a child */
#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OK 0x0040 /* Used during OR-clause processing */
#define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x0400 /* The original LIKE operator */
#define TERM_IS 0x0800 /* Term.pExpr is an IS operator */
#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
#define TERM_HEURTRUTH 0x2000 /* Heuristic truthProb used */
#ifdef SQLITE_ENABLE_STAT4
# define TERM_HIGHTRUTH 0x4000 /* Term excludes few rows */
#else
# define TERM_HIGHTRUTH 0 /* Only used with STAT4 */
#endif
#define TERM_SLICE 0x8000 /* One slice of a row-value/vector comparison */
/*
** An instance of the WhereScan object is used as an iterator for locating
** terms in the WHERE clause that are useful to the query planner.
*/
struct WhereScan {
WhereClause *pOrigWC; /* Original, innermost WhereClause */
WhereClause *pWC; /* WhereClause currently being scanned */
const char *zCollName; /* Required collating sequence, if not NULL */
Expr *pIdxExpr; /* Search for this index expression */
int k; /* Resume scanning at this->pWC->a[this->k] */
u32 opMask; /* Acceptable operators */
char idxaff; /* Must match this affinity, if zCollName!=NULL */
unsigned char iEquiv; /* Current slot in aiCur[] and aiColumn[] */
unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
int aiCur[11]; /* Cursors in the equivalence class */
i16 aiColumn[11]; /* Corresponding column number in the eq-class */
};
/*
** An instance of the following structure holds all information about a
** WHERE clause. Mostly this is a container for one or more WhereTerms.
**
** Explanation of pOuter: For a WHERE clause of the form
**
** a AND ((b AND c) OR (d AND e)) AND f
**
** There are separate WhereClause objects for the whole clause and for
** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the
** subclauses points to the WhereClause object for the whole clause.
*/
struct WhereClause {
WhereInfo *pWInfo; /* WHERE clause processing context */
WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
u8 hasOr; /* True if any a[].eOperator is WO_OR */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
int nBase; /* Number of terms through the last non-Virtual */
WhereTerm *a; /* Each a[] describes a term of the WHERE clause */
#if defined(SQLITE_SMALL_STACK)
WhereTerm aStatic[1]; /* Initial static space for a[] */
#else
WhereTerm aStatic[8]; /* Initial static space for a[] */
#endif
};
/*
** A WhereTerm with eOperator==WO_OR has its u.pOrInfo pointer set to
** a dynamically allocated instance of the following structure.
*/
struct WhereOrInfo {
WhereClause wc; /* Decomposition into subterms */
Bitmask indexable; /* Bitmask of all indexable tables in the clause */
};
/*
** A WhereTerm with eOperator==WO_AND has its u.pAndInfo pointer set to
** a dynamically allocated instance of the following structure.
*/
struct WhereAndInfo {
WhereClause wc; /* The subexpression broken out */
};
/*
** An instance of the following structure keeps track of a mapping
** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
**
** The VDBE cursor numbers are small integers contained in
** SrcItem.iCursor and Expr.iTable fields. For any given WHERE
** clause, the cursor numbers might not begin with 0 and they might
** contain gaps in the numbering sequence. But we want to make maximum
** use of the bits in our bitmasks. This structure provides a mapping
** from the sparse cursor numbers into consecutive integers beginning
** with 0.
**
** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
** corresponds VDBE cursor number B. The A-th bit of a bitmask is 1<<A.
**
** For example, if the WHERE clause expression used these VDBE
** cursors: 4, 5, 8, 29, 57, 73. Then the WhereMaskSet structure
** would map those cursor numbers into bits 0 through 5.
**
** Note that the mapping is not necessarily ordered. In the example
** above, the mapping might go like this: 4->3, 5->1, 8->2, 29->0,
** 57->5, 73->4. Or one of 719 other combinations might be used. It
** does not really matter. What is important is that sparse cursor
** numbers all get mapped into bit numbers that begin with 0 and contain
** no gaps.
*/
struct WhereMaskSet {
int bVarSelect; /* Used by sqlite3WhereExprUsage() */
int n; /* Number of assigned cursor values */
int ix[BMS]; /* Cursor assigned to each bit */
};
/*
** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query.
*/
struct WhereLoopBuilder {
WhereInfo *pWInfo; /* Information about this WHERE */
WhereClause *pWC; /* WHERE clause terms */
WhereLoop *pNew; /* Template WhereLoop */
WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
#ifdef SQLITE_ENABLE_STAT4
UnpackedRecord *pRec; /* Probe for stat4 (if required) */
int nRecValid; /* Number of valid fields currently in pRec */
#endif
unsigned char bldFlags1; /* First set of SQLITE_BLDF_* flags */
unsigned char bldFlags2; /* Second set of SQLITE_BLDF_* flags */
unsigned int iPlanLimit; /* Search limiter */
};
/* Allowed values for WhereLoopBuider.bldFlags */
#define SQLITE_BLDF1_INDEXED 0x0001 /* An index is used */
#define SQLITE_BLDF1_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
#define SQLITE_BLDF2_2NDPASS 0x0004 /* Second builder pass needed */
/* The WhereLoopBuilder.iPlanLimit is used to limit the number of
** index+constraint combinations the query planner will consider for a
** particular query. If this parameter is unlimited, then certain
** pathological queries can spend excess time in the sqlite3WhereBegin()
** routine. The limit is high enough that is should not impact real-world
** queries.
**
** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is
** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM
** clause is processed, so that every table in a join is guaranteed to be
** able to propose a some index+constraint combinations even if the initial
** baseline limit was exhausted by prior tables of the join.
*/
#ifndef SQLITE_QUERY_PLANNER_LIMIT
# define SQLITE_QUERY_PLANNER_LIMIT 20000
#endif
#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR
# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000
#endif
/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop. An instance of
** this structure is returned by the first half and passed
** into the second half to give some continuity.
**
** An instance of this object holds the complete state of the query
** planner.
*/
struct WhereInfo {
Parse *pParse; /* Parsing and code generating context */
SrcList *pTabList; /* List of tables in the join */
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
ExprList *pResultSet; /* Result set of the query */
#if WHERETRACE_ENABLED
Expr *pWhere; /* The complete WHERE clause */
#endif
Select *pSelect; /* The entire SELECT statement containing WHERE */
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */
int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
u8 nLevel; /* Number of nested loop */
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */
unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
unsigned sorted :1; /* True if really sorted (not just grouped) */
unsigned bStarDone :1; /* True if check for star-query is complete */
unsigned bStarUsed :1; /* True if star-query heuristic is used */
LogEst nRowOut; /* Estimated number of output rows */
#ifdef WHERETRACE_ENABLED
LogEst rTotalCost; /* Total cost of the solution */
#endif
int iTop; /* The very beginning of the WHERE loop */
int iEndWhere; /* End of the WHERE clause itself */
WhereLoop *pLoops; /* List of all WhereLoop objects */
WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
WhereClause sWC; /* Decomposition of the WHERE clause */
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
WhereLevel a[FLEXARRAY]; /* Information about each nest loop in WHERE */
};
/*
** The size (in bytes) of a WhereInfo object that holds N WhereLevels.
*/
#define SZ_WHEREINFO(N) ROUND8(offsetof(WhereInfo,a)+(N)*sizeof(WhereLevel))
/*
** Private interfaces - callable only by other where.c routines.
**
** where.c:
*/
SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
#ifdef WHERETRACE_ENABLED
SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC);
SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm);
SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC);
#endif
SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm(
WhereClause *pWC, /* The WHERE clause to be searched */
int iCur, /* Cursor number of LHS */
int iColumn, /* Column number of LHS */
Bitmask notReady, /* RHS must not overlap with this mask */
u32 op, /* Mask of WO_xx values describing operator */
Index *pIdx /* Must be compatible with this index, if not NULL */
);
SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte);
SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte);
/* wherecode.c: */
#ifndef SQLITE_OMIT_EXPLAIN
SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
Parse *pParse, /* Parse context */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
);
SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter(
const Parse *pParse, /* Parse context */
const WhereInfo *pWInfo, /* WHERE clause */
const WhereLevel *pLevel /* Bloom filter on this level */
);
SQLITE_PRIVATE void sqlite3WhereAddExplainText(
Parse *pParse, /* Parse context */
int addr,
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
);
#else
# define sqlite3WhereExplainOneScan(u,v,w,x) 0
# define sqlite3WhereExplainBloomFilter(u,v,w) 0
# define sqlite3WhereAddExplainText(u,v,w,x,y)
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
SQLITE_PRIVATE void sqlite3WhereAddScanStatus(
Vdbe *v, /* Vdbe to add scanstatus entry to */
SrcList *pSrclist, /* FROM clause pLvl reads data from */
WhereLevel *pLvl, /* Level to add scanstatus() entry for */
}
}
}
}
*pzAff = zAff;
return regBase;
}
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
/*
** If the most recently coded instruction is a constant range constraint
** (a string literal) that originated from the LIKE optimization, then
** set P3 and P5 on the OP_String opcode so that the string will be cast
** to a BLOB at appropriate times.
**
** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range
** expression: "x>='ABC' AND x<'abd'". But this requires that the range
** scan loop run twice, once for strings and a second time for BLOBs.
** The OP_String opcodes on the second pass convert the upper and lower
** bound string constants to blobs. This routine makes the necessary changes
** to the OP_String opcodes for that to happen.
**
** Except, of course, if SQLITE_LIKE_DOESNT_MATCH_BLOBS is defined, then
** only the one pass through the string space is required, so this routine
** becomes a no-op.
*/
static void whereLikeOptimizationStringFixup(
Vdbe *v, /* prepared statement under construction */
WhereLevel *pLevel, /* The loop that contains the LIKE operator */
WhereTerm *pTerm /* The upper or lower bound just coded */
){
if( pTerm->wtFlags & TERM_LIKEOPT ){
VdbeOp *pOp;
assert( pLevel->iLikeRepCntr>0 );
pOp = sqlite3VdbeGetLastOp(v);
assert( pOp!=0 );
assert( pOp->opcode==OP_String8
|| pTerm->pWC->pWInfo->pParse->db->mallocFailed );
pOp->p3 = (int)(pLevel->iLikeRepCntr>>1); /* Register holding counter */
pOp->p5 = (u8)(pLevel->iLikeRepCntr&1); /* ASC or DESC */
}
}
#else
# define whereLikeOptimizationStringFixup(A,B,C)
#endif
#ifdef SQLITE_ENABLE_CURSOR_HINTS
/*
** Information is passed from codeCursorHint() down to individual nodes of
** the expression tree (by sqlite3WalkExpr()) using an instance of this
** structure.
*/
struct CCurHint {
int iTabCur; /* Cursor for the main table */
int iIdxCur; /* Cursor for the index, if pIdx!=0. Unused otherwise */
Index *pIdx; /* The index used to access the table */
};
/*
** This function is called for every node of an expression that is a candidate
** for a cursor hint on an index cursor. For TK_COLUMN nodes that reference
** the table CCurHint.iTabCur, verify that the same column can be
** accessed through the index. If it cannot, then set pWalker->eCode to 1.
*/
static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){
struct CCurHint *pHint = pWalker->u.pCCurHint;
assert( pHint->pIdx!=0 );
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pHint->iTabCur
&& sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn)<0
){
pWalker->eCode = 1;
}
return WRC_Continue;
}
/*
** Test whether or not expression pExpr, which was part of a WHERE clause,
** should be included in the cursor-hint for a table that is on the rhs
** of a LEFT JOIN. Set Walker.eCode to non-zero before returning if the
** expression is not suitable.
**
** An expression is unsuitable if it might evaluate to non NULL even if
** a TK_COLUMN node that does affect the value of the expression is set
** to NULL. For example:
**
** col IS NULL
** col IS NOT NULL
** coalesce(col, 1)
** CASE WHEN col THEN 0 ELSE 1 END
*/
static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_IS
|| pExpr->op==TK_ISNULL || pExpr->op==TK_ISNOT
|| pExpr->op==TK_NOTNULL || pExpr->op==TK_CASE
){
pWalker->eCode = 1;
}else if( pExpr->op==TK_FUNCTION ){
int d1;
char d2[4];
if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){
pWalker->eCode = 1;
}
}
return WRC_Continue;
}
/*
** This function is called on every node of an expression tree used as an
** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN
** that accesses any table other than the one identified by
** CCurHint.iTabCur, then do the following:
**
** 1) allocate a register and code an OP_Column instruction to read
** the specified column into the new register, and
**
** 2) transform the expression node to a TK_REGISTER node that reads
** from the newly populated register.
**
** Also, if the node is a TK_COLUMN that does access the table identified
** by pCCurHint.iTabCur, and an index is being used (which we will
** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into
** an access of the index rather than the original table.
*/
static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
int rc = WRC_Continue;
int reg;
struct CCurHint *pHint = pWalker->u.pCCurHint;
if( pExpr->op==TK_COLUMN ){
if( pExpr->iTable!=pHint->iTabCur ){
reg = ++pWalker->pParse->nMem; /* Register for column value */
reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg);
pExpr->op = TK_REGISTER;
pExpr->iTable = reg;
}else if( pHint->pIdx!=0 ){
pExpr->iTable = pHint->iIdxCur;
pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn);
assert( pExpr->iColumn>=0 );
}
}else if( pExpr->pAggInfo ){
rc = WRC_Prune;
reg = ++pWalker->pParse->nMem; /* Register for column value */
reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg);
pExpr->op = TK_REGISTER;
pExpr->iTable = reg;
}else if( pExpr->op==TK_TRUEFALSE ){
/* Do not walk disabled expressions. tag-20230504-1 */
return WRC_Prune;
}
return rc;
}
/*
** Insert an OP_CursorHint instruction if it is appropriate to do so.
*/
static void codeCursorHint(
SrcItem *pTabItem, /* FROM clause item */
WhereInfo *pWInfo, /* The where clause */
WhereLevel *pLevel, /* Which loop to provide hints for */
WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */
){
Parse *pParse = pWInfo->pParse;
sqlite3 *db = pParse->db;
Vdbe *v = pParse->pVdbe;
Expr *pExpr = 0;
WhereLoop *pLoop = pLevel->pWLoop;
int iCur;
WhereClause *pWC;
WhereTerm *pTerm;
int i, j;
struct CCurHint sHint;
Walker sWalker;
if( OptimizationDisabled(db, SQLITE_CursorHints) ) return;
iCur = pLevel->iTabCur;
assert( iCur==pWInfo->pTabList->a[pLevel->iFrom].iCursor );
sHint.iTabCur = iCur;
sHint.iIdxCur = pLevel->iIdxCur;
sHint.pIdx = pLoop->u.btree.pIndex;
memset(&sWalker, 0, sizeof(sWalker));
sWalker.pParse = pParse;
sWalker.u.pCCurHint = &sHint;
pWC = &pWInfo->sWC;
for(i=0; i<pWC->nBase; i++){
pTerm = &pWC->a[i];
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( pTerm->prereqAll & pLevel->notReady ) continue;
/* Any terms specified as part of the ON(...) clause for any LEFT
** JOIN for which the current table is not the rhs are omitted
** from the cursor-hint.
**
** If this table is the rhs of a LEFT JOIN, "IS" or "IS NULL" terms
** that were specified as part of the WHERE clause must be excluded.
** This is to address the following:
**
** SELECT ... t1 LEFT JOIN t2 ON (t1.a=t2.b) WHERE t2.c IS NULL;
**
** Say there is a single row in t2 that matches (t1.a=t2.b), but its
** t2.c values is not NULL. If the (t2.c IS NULL) constraint is
** pushed down to the cursor, this row is filtered out, causing
** SQLite to synthesize a row of NULL values. Which does match the
** WHERE clause, and so the query returns a row. Which is incorrect.
**
** For the same reason, WHERE terms such as:
**
** WHERE 1 = (t2.c IS NULL)
**
** are also excluded. See codeCursorHintIsOrFunction() for details.
*/
if( pTabItem->fg.jointype & JT_LEFT ){
Expr *pExpr = pTerm->pExpr;
if( !ExprHasProperty(pExpr, EP_OuterON)
|| pExpr->w.iJoin!=pTabItem->iCursor
){
sWalker.eCode = 0;
sWalker.xExprCallback = codeCursorHintIsOrFunction;
sqlite3WalkExpr(&sWalker, pTerm->pExpr);
if( sWalker.eCode ) continue;
}
}else{
if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) continue;
}
/* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize
** the cursor. These terms are not needed as hints for a pure range
** scan (that has no == terms) so omit them. */
if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){
for(j=0; j<pLoop->nLTerm && pLoop->aLTerm[j]!=pTerm; j++){}
if( j<pLoop->nLTerm ) continue;
}
/* No subqueries or non-deterministic functions allowed */
if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue;
/* For an index scan, make sure referenced columns are actually in
** the index. */
if( sHint.pIdx!=0 ){
sWalker.eCode = 0;
sWalker.xExprCallback = codeCursorHintCheckExpr;
sqlite3WalkExpr(&sWalker, pTerm->pExpr);
if( sWalker.eCode ) continue;
}
/* If we survive all prior tests, that means this term is worth hinting */
pExpr = sqlite3ExprAnd(pParse, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
}
if( pExpr!=0 ){
sWalker.xExprCallback = codeCursorHintFixExpr;
if( pParse->nErr==0 ) sqlite3WalkExpr(&sWalker, pExpr);
sqlite3VdbeAddOp4(v, OP_CursorHint,
(sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0,
(const char*)pExpr, P4_EXPR);
}
}
#else
# define codeCursorHint(A,B,C,D) /* No-op */
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
/*
** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains
** a rowid value just read from cursor iIdxCur, open on index pIdx. This
** function generates code to do a deferred seek of cursor iCur to the
** rowid stored in register iRowid.
**
** Normally, this is just:
**
** OP_DeferredSeek $iCur $iRowid
**
** Which causes a seek on $iCur to the row with rowid $iRowid.
**
** However, if the scan currently being coded is a branch of an OR-loop and
** the statement currently being coded is a SELECT, then additional information
** is added that might allow OP_Column to omit the seek and instead do its
** lookup on the index, thus avoiding an expensive seek operation. To
** enable this optimization, the P3 of OP_DeferredSeek is set to iIdxCur
** and P4 is set to an array of integers containing one entry for each column
** in the table. For each table column, if the column is the i'th
** column of the index, then the corresponding array entry is set to (i+1).
** If the column does not appear in the index at all, the array entry is set
** to 0. The OP_Column opcode can check this array to see if the column it
** wants is in the index and if it is, it will substitute the index cursor
** and column number and continue with those new values, rather than seeking
** the table cursor.
*/
static void codeDeferredSeek(
WhereInfo *pWInfo, /* Where clause context */
Index *pIdx, /* Index scan is using */
int iCur, /* Cursor for IPK b-tree */
int iIdxCur /* Index cursor */
){
Parse *pParse = pWInfo->pParse; /* Parse context */
Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */
assert( iIdxCur>0 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
pWInfo->bDeferredSeek = 1;
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
){
int i;
Table *pTab = pIdx->pTable;
u32 *ai = (u32*)sqlite3DbMallocZero(pParse->db, sizeof(u32)*(pTab->nCol+1));
if( ai ){
ai[0] = pTab->nCol;
for(i=0; i<pIdx->nColumn-1; i++){
int x1, x2;
assert( pIdx->aiColumn[i]<pTab->nCol );
x1 = pIdx->aiColumn[i];
x2 = sqlite3TableColumnToStorage(pTab, x1);
testcase( x1!=x2 );
if( x1>=0 ) ai[x2+1] = i+1;
}
sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
}
}
}
/*
** If the expression passed as the second argument is a vector, generate
** code to write the first nReg elements of the vector into an array
** of registers starting with iReg.
**
** If the expression is not a vector, then nReg must be passed 1. In
** this case, generate code to evaluate the expression and leave the
** result in register iReg.
*/
static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
assert( nReg>0 );
if( p && sqlite3ExprIsVector(p) ){
#ifndef SQLITE_OMIT_SUBQUERY
if( ExprUseXSelect(p) ){
Vdbe *v = pParse->pVdbe;
int iSelect;
assert( p->op==TK_SELECT );
iSelect = sqlite3CodeSubselect(pParse, p);
sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1);
}else
#endif
{
int i;
const ExprList *pList;
assert( ExprUseXList(p) );
pList = p->x.pList;
assert( nReg<=pList->nExpr );
for(i=0; i<nReg; i++){
sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i);
}
regRowid = sqlite3GetTempReg(pParse);
regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid);
sqlite3VdbeAddOp2(pParse->pVdbe, OP_MustBeInt, regRowid, addrNxt);
VdbeCoverage(pParse->pVdbe);
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, regRowid, 1);
VdbeCoverage(pParse->pVdbe);
}else{
u16 nEq = pLoop->u.btree.nEq;
int r1;
char *zStartAff;
assert( pLoop->wsFlags & WHERE_INDEXED );
assert( (pLoop->wsFlags & WHERE_COLUMN_IN)==0 );
r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff);
codeApplyAffinity(pParse, r1, nEq, zStartAff);
sqlite3DbFree(pParse->db, zStartAff);
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, r1, nEq);
VdbeCoverage(pParse->pVdbe);
}
pLevel->regFilter = 0;
pLevel->addrBrk = saved_addrBrk;
}
}
/*
** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
** operator. Return true if level pLoop is guaranteed to visit only one
** row for each key generated for the index.
*/
static int whereLoopIsOneRow(WhereLoop *pLoop){
if( pLoop->u.btree.pIndex->onError
&& pLoop->nSkip==0
&& pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
){
int ii;
for(ii=0; ii<pLoop->u.btree.nEq; ii++){
if( pLoop->aLTerm[ii]->eOperator & (WO_IS|WO_ISNULL) ){
return 0;
}
}
return 1;
}
return 0;
}
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
Parse *pParse, /* Parsing context */
Vdbe *v, /* Prepared statement under construction */
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
WhereLevel *pLevel, /* The current level pointer */
Bitmask notReady /* Which tables are currently available */
){
int j, k; /* Loop counters */
int iCur; /* The VDBE cursor for the table */
int addrNxt; /* Where to jump to continue with the next IN case */
int bRev; /* True if we need to scan in reverse order */
WhereLoop *pLoop; /* The WhereLoop object being coded */
WhereClause *pWC; /* Decomposition of the entire WHERE clause */
WhereTerm *pTerm; /* A WHERE clause term */
sqlite3 *db; /* Database connection */
SrcItem *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
int addrCont; /* Jump here to continue with next cycle */
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
int iReleaseReg = 0; /* Temp register to free before returning */
Index *pIdx = 0; /* Index used by loop (if any) */
int iLoop; /* Iteration of constraint generator loop */
pWC = &pWInfo->sWC;
db = pParse->db;
pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
VdbeModuleComment((v, "Begin WHERE-loop%d: %s",
iLevel, pTabItem->pSTab->zName));
#if WHERETRACE_ENABLED /* 0x4001 */
if( sqlite3WhereTrace & 0x1 ){
sqlite3DebugPrintf("Coding level %d of %d: notReady=%llx iFrom=%d\n",
iLevel, pWInfo->nLevel, (u64)notReady, pLevel->iFrom);
if( sqlite3WhereTrace & 0x1000 ){
sqlite3WhereLoopPrint(pLoop, pWC);
}
}
if( (sqlite3WhereTrace & 0x4001)==0x4001 ){
if( iLevel==0 ){
sqlite3DebugPrintf("WHERE clause being coded:\n");
sqlite3TreeViewExpr(0, pWInfo->pWhere, 0);
}
sqlite3DebugPrintf("All WHERE-clause terms before coding:\n");
sqlite3WhereClausePrint(pWC);
}
#endif
/* Create labels for the "break" and "continue" instructions
** for the current loop. Jump to addrBrk to break out of a loop.
** Jump to cont to go immediately to the next iteration of the
** loop.
**
** When there is an IN operator, we also have a "addrNxt" label that
** means to continue with the next IN value combination. When
** there are no IN operators in the constraints, the "addrNxt" label
** is the same as "addrBrk".
*/
addrBrk = pLevel->addrNxt = pLevel->addrBrk;
addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);
/* If this is the right table of a LEFT OUTER JOIN, allocate and
** initialize a memory cell that records if this table matches any
** row of the left table of the join.
*/
assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
|| pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
}
}else if( pLoop->wsFlags & WHERE_INDEXED ){
/* Case 4: Search using an index.
**
** The WHERE clause may contain zero or more equality
** terms ("==" or "IN" or "IS" 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 "==", "IN", or "IS" 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.
*/
static const u8 aStartOp[] = {
0,
0,
OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */
OP_Last, /* 3: (!start_constraints && startEq && bRev) */
OP_SeekGT, /* 4: (start_constraints && !startEq && !bRev) */
OP_SeekLT, /* 5: (start_constraints && !startEq && bRev) */
OP_SeekGE, /* 6: (start_constraints && startEq && !bRev) */
OP_SeekLE /* 7: (start_constraints && startEq && bRev) */
};
static const u8 aEndOp[] = {
OP_IdxGE, /* 0: (end_constraints && !bRev && !endEq) */
OP_IdxGT, /* 1: (end_constraints && !bRev && endEq) */
OP_IdxLE, /* 2: (end_constraints && bRev && !endEq) */
OP_IdxLT, /* 3: (end_constraints && bRev && endEq) */
};
u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */
u16 nBtm = pLoop->u.btree.nBtm; /* Length of BTM vector */
u16 nTop = pLoop->u.btree.nTop; /* Length of TOP vector */
int regBase; /* Base register holding constraint values */
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 nConstraint; /* Number of constraint terms */
int iIdxCur; /* The VDBE cursor for the index */
int nExtraReg = 0; /* Number of extra registers needed */
int op; /* Instruction opcode */
char *zStartAff; /* Affinity for start of range constraint */
char *zEndAff = 0; /* Affinity for end of range constraint */
u8 bSeekPastNull = 0; /* True to seek past initial nulls */
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
int omitTable; /* True if we use the index only */
int regBignull = 0; /* big-null flag register */
int addrSeekScan = 0; /* Opcode of the OP_SeekScan, if any */
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
assert( nEq>=pLoop->nSkip );
/* Find any inequality constraint terms for the start and end
** of the range.
*/
j = nEq;
if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
pRangeStart = pLoop->aLTerm[j++];
nExtraReg = MAX(nExtraReg, pLoop->u.btree.nBtm);
/* Like optimization range constraints always occur in pairs */
assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 ||
(pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 );
}
if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
pRangeEnd = pLoop->aLTerm[j++];
nExtraReg = MAX(nExtraReg, pLoop->u.btree.nTop);
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){
assert( pRangeStart!=0 ); /* LIKE opt constraints */
assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */
pLevel->iLikeRepCntr = (u32)++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 1, (int)pLevel->iLikeRepCntr);
VdbeComment((v, "LIKE loop counter"));
pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
/* iLikeRepCntr actually stores 2x the counter register number. The
** bottom bit indicates whether the search order is ASC or DESC. */
testcase( bRev );
testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
assert( (bRev & ~1)==0 );
pLevel->iLikeRepCntr <<=1;
pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
}
#endif
if( pRangeStart==0 ){
j = pIdx->aiColumn[nEq];
if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
bSeekPastNull = 1;
}
}
}
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
/* If the WHERE_BIGNULL_SORT flag is set, then index column nEq uses
** a non-default "big-null" sort (either ASC NULLS LAST or DESC NULLS
** FIRST). In both cases separate ordered scans are made of those
** index entries for which the column is null and for those for which
** it is not. For an ASC sort, the non-NULL entries are scanned first.
** For DESC, NULL entries are scanned first.
*/
if( (pLoop->wsFlags & (WHERE_TOP_LIMIT|WHERE_BTM_LIMIT))==0
&& (pLoop->wsFlags & WHERE_BIGNULL_SORT)!=0
){
assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 );
assert( pRangeEnd==0 && pRangeStart==0 );
testcase( pLoop->nSkip>0 );
nExtraReg = 1;
bSeekPastNull = 1;
pLevel->regBignull = regBignull = ++pParse->nMem;
if( pLevel->iLeftJoin ){
sqlite3VdbeAddOp2(v, OP_Integer, 0, regBignull);
}
pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse);
}
/* 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).
*/
if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
SWAP(u8, bSeekPastNull, bStopAtNull);
SWAP(u8, nBtm, nTop);
}
if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
/* In case OP_SeekScan is used, ensure that the index cursor does not
** point to a valid row for the first iteration of this loop. */
sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
}
/* Generate code to evaluate all constraint terms using == or IN
** and store the values of those terms in an array of registers
** starting at regBase.
*/
codeCursorHint(pTabItem, pWInfo, pLevel, pRangeEnd);
regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
if( zStartAff && nTop ){
zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]);
}
addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt);
testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 );
testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 );
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 ){
Expr *pRight = pRangeStart->pExpr->pRight;
codeExprOrVector(pParse, pRight, regBase+nEq, nBtm);
whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
if( (pRangeStart->wtFlags & TERM_VNULL)==0
&& sqlite3ExprCanBeNull(pRight)
){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
VdbeCoverage(v);
}
if( zStartAff ){
updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
}
nConstraint += nBtm;
testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
if( sqlite3ExprIsVector(pRight)==0 ){
disableTerm(pLevel, pRangeStart);
}else{
startEq = 1;
}
bSeekPastNull = 0;
}else if( bSeekPastNull ){
startEq = 0;
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
start_constraints = 1;
nConstraint++;
}else if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
start_constraints = 1;
nConstraint++;
}
codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){
/* The skip-scan logic inside the call to codeAllEqualityConstraints()
** above has already left the cursor sitting on the correct row,
** so no further seeking is needed */
}else{
if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
VdbeComment((v, "NULL-scan pass ctr"));
}
if( pLevel->regFilter ){
sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
regBase, nEq);
VdbeCoverage(v);
filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
}
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
assert( regBignull==0 );
/* TUNING: The OP_SeekScan opcode seeks to reduce the number
** of expensive seek operations by replacing a single seek with
** 1 or more step operations. The question is, how many steps
** should we try before giving up and going with a seek. The cost
** of a seek is proportional to the logarithm of the of the number
** of entries in the tree, so basing the number of steps to try
** on the estimated number of rows in the btree seems like a good
** guess. */
addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan,
(pIdx->aiRowLogEst[0]+9)/10);
if( pRangeStart || pRangeEnd ){
sqlite3VdbeChangeP5(v, 1);
sqlite3VdbeChangeP2(v, addrSeekScan, sqlite3VdbeCurrentAddr(v)+1);
addrSeekScan = 0;
}
VdbeCoverage(v);
}
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
VdbeCoverage(v);
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last );
VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT );
VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT );
assert( bSeekPastNull==0 || bStopAtNull==0 );
if( regBignull ){
assert( bSeekPastNull==1 || bStopAtNull==1 );
assert( bSeekPastNull==!bStopAtNull );
assert( bStopAtNull==startEq );
sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
op = aStartOp[(nConstraint>1)*4 + 2 + bRev];
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
nConstraint-startEq);
VdbeCoverage(v);
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last );
VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
assert( op==OP_Rewind || op==OP_Last || op==OP_SeekGE || op==OP_SeekLE);
}
}
/* Load the value for the inequality constraint at the end of the
** range (if any).
*/
nConstraint = nEq;
assert( pLevel->p2==0 );
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
assert( addrSeekScan==0 );
codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
&& sqlite3ExprCanBeNull(pRight)
){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
VdbeCoverage(v);
}
if( zEndAff ){
updateRangeAffinityStr(pRight, nTop, zEndAff);
codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
}else{
assert( pParse->db->mallocFailed );
}
nConstraint += nTop;
testcase( pRangeEnd->wtFlags & TERM_VIRTUAL );
if( sqlite3ExprIsVector(pRight)==0 ){
disableTerm(pLevel, pRangeEnd);
}else{
endEq = 1;
}
}else if( bStopAtNull ){
if( regBignull==0 ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
endEq = 0;
}
nConstraint++;
}
if( zStartAff ) sqlite3DbNNFreeNN(db, zStartAff);
if( zEndAff ) sqlite3DbNNFreeNN(db, zEndAff);
/* Top of the loop body */
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
/* Check if the index cursor is past the end of the range. */
if( nConstraint ){
if( regBignull ){
/* Except, skip the end-of-range check while doing the NULL-scan */
sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3);
VdbeComment((v, "If NULL-scan 2nd pass"));
VdbeCoverage(v);
}
op = aEndOp[bRev*2 + endEq];
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan);
}
if( regBignull ){
/* During a NULL-scan, check to see if we have reached the end of
** the NULLs */
assert( bSeekPastNull==!bStopAtNull );
assert( bSeekPastNull+bStopAtNull==1 );
assert( nConstraint+bSeekPastNull>0 );
sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2);
VdbeComment((v, "If NULL-scan 1st pass"));
VdbeCoverage(v);
op = aEndOp[bRev*2 + bSeekPastNull];
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
nConstraint+bSeekPastNull);
testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
}
if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){
sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq);
}
/* Seek the table cursor, if required */
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
&& (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0;
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
}else if( iCur!=iIdxCur ){
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
}
sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
}
if( pLevel->iLeftJoin==0 ){
/* If a partial index is driving the loop, try to eliminate WHERE clause
** terms from the query that must be true due to the WHERE clause of
** the partial index. This optimization does not work on an outer join,
** as shown by:
**
** 2019-11-02 ticket 623eff57e76d45f6 (LEFT JOIN)
** 2025-05-29 forum post 7dee41d32506c4ae (RIGHT JOIN)
*/
if( pIdx->pPartIdxWhere && pLevel->pRJ==0 ){
whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
}
}else{
testcase( pIdx->pPartIdxWhere );
/* The following assert() is not a requirement, merely an observation:
** The OR-optimization doesn't work for the right hand table of
** a LEFT JOIN: */
assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
}
/* Record the instruction used to terminate the loop. */
if( (pLoop->wsFlags & WHERE_ONEROW)
|| (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop))
){
pLevel->op = OP_Noop;
}else if( bRev ){
pLevel->op = OP_Prev;
}else{
pLevel->op = OP_Next;
}
pLevel->p1 = iIdxCur;
pLevel->p3 = (pLoop->wsFlags&WHERE_UNQ_WANTED)!=0 ? 1:0;
if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}else{
assert( pLevel->p5==0 );
}
if( omitTable ) pIdx = 0;
}else
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
if( pLoop->wsFlags & WHERE_MULTI_OR ){
/* Case 5: Two or more separately indexed terms connected by OR
**
** Added 2014-05-26: If the table is a WITHOUT ROWID table, then
** use an ephemeral index instead of a RowSet to record the primary
** keys of the rows we have already seen.
**
*/
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
Index *pCov = 0; /* Potential covering index (or NULL) */
int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
int regRowset = 0; /* Register for RowSet object */
int regRowid = 0; /* Register holding rowid */
int iLoopBody = sqlite3VdbeMakeLabel(pParse);/* Start of loop body */
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
Table *pTab = pTabItem->pSTab;
pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
assert( pTerm->eOperator & WO_OR );
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
pOrWc = &pTerm->u.pOrInfo->wc;
pLevel->op = OP_Return;
pLevel->p1 = regReturn;
/* Set up a new SrcList in pOrTab containing the table being scanned
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
*/
if( pWInfo->nLevel>1 ){
int nNotReady; /* The number of notReady tables */
SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1));
if( pOrTab==0 ) return notReady;
pOrTab->nAlloc = (u8)(nNotReady + 1);
pOrTab->nSrc = pOrTab->nAlloc;
memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
origSrc = pWInfo->pTabList->a;
for(k=1; k<=nNotReady; k++){
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
}
}else{
pOrTab = pWInfo->pTabList;
}
/* Initialize the rowset register to contain NULL. An SQL NULL is
** equivalent to an empty rowset. Or, create an ephemeral index
** capable of holding primary keys in the case of a WITHOUT ROWID.
**
** Also initialize regReturn to contain the address of the instruction
** immediately following the OP_Return at the bottom of the loop. This
** is required in a few obscure LEFT JOIN cases where control jumps
** over the top of the loop into the body of it. In this case the
** correct response for the end-of-loop code (the OP_Return) is to
** fall through to the next instruction, just as an OP_Next does if
** called on an uninitialized cursor.
*/
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
if( HasRowid(pTab) ){
regRowset = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
regRowset = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
}
regRowid = ++pParse->nMem;
}
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
/* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y
** Then for every term xN, evaluate as the subexpression: xN AND y
** That way, terms in y that are factored into the disjunction will
** be picked up by the recursive calls to sqlite3WhereBegin() below.
**
** Actually, each subexpression is converted to "xN AND w" where w is
** the "interesting" terms of z - terms that did not originate in the
** ON or USING clause of a LEFT JOIN, and terms that are usable as
** indices.
**
** This optimization also only applies if the (x1 OR x2 OR ...) term
** is not contained in the ON clause of a LEFT JOIN.
** See ticket http://sqlite.org/src/info/f2369304e4
**
** 2022-02-04: Do not push down slices of a row-value comparison.
** In other words, "w" or "y" may not be a slice of a vector. Otherwise,
** the initialization of the right-hand operand of the vector comparison
** might not occur, or might occur only in an OR branch that is not
** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1.
**
** 2022-03-03: Do not push down expressions that involve subqueries.
** The subquery might get coded as a subroutine. Any table-references
** in the subquery might be resolved to index-references for the index on
** the OR branch in which the subroutine is coded. But if the subroutine
** is invoked from a different OR branch that uses a different index, such
** index-references will not work. tag-20220303a
** https://sqlite.org/forum/forumpost/36937b197273d403
*/
if( pWC->nTerm>1 ){
int iTerm;
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
Expr *pExpr = pWC->a[iTerm].pExpr;
if( &pWC->a[iTerm] == pTerm ) continue;
testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
testcase( pWC->a[iTerm].wtFlags & TERM_CODED );
testcase( pWC->a[iTerm].wtFlags & TERM_SLICE );
if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){
continue;
}
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */
pExpr = sqlite3ExprDup(db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
}
if( pAndExpr ){
if( HasRowid(pTab) ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid);
jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0,
regRowid, iSet);
VdbeCoverage(v);
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
int nPk = pPk->nKeyCol;
int iPk;
int r;
/* Read the PK into an array of temp registers. */
r = sqlite3GetTempRange(pParse, nPk);
for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk];
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
}
/* Check if the temp table already contains this key. If so,
** the row has already been included in the result set and
** can be ignored (by jumping past the Gosub below). Otherwise,
** insert the key into the temp table and proceed with processing
** the row.
**
** Use some of the same optimizations as OP_RowSetTest: If iSet
** is zero, assume that the key cannot already be present in
** the temp table. And if iSet is -1, assume that there is no
** need to insert the key into the temp table, as it will never
** be tested for. */
if( iSet ){
jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk);
VdbeCoverage(v);
}
if( iSet>=0 ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid,
r, nPk);
if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
}
/* Release the array of temp registers */
sqlite3ReleaseTempRange(pParse, r, nPk);
}
}
/* Invoke the main loop body as a subroutine */
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
/* Jump here (skipping the main loop body subroutine) if the
** current sub-WHERE row is a duplicate from prior sub-WHEREs. */
if( jmp1 ) sqlite3VdbeJumpHere(v, jmp1);
/* The pSubWInfo->untestedTerms flag means that this OR term
** contained one or more AND term from a notReady table. The
** terms from the notReady table could not be tested and will
** need to be tested later.
*/
if( pSubWInfo->untestedTerms ) untestedTerms = 1;
/* If all of the OR-connected terms are optimized using the same
** index, and the index is opened using the same cursor number
** by each call to sqlite3WhereBegin() made by this loop, it may
** be possible to use that index as a covering index.
**
** If the call to sqlite3WhereBegin() above resulted in a scan that
** uses an index, and this is either the first OR-connected term
** processed or the index is the same as that used by all previous
** terms, set pCov to the candidate covering index. Otherwise, set
** pCov to NULL to indicate that no candidate covering index will
** be available.
*/
pSubLoop = pSubWInfo->a[0].pWLoop;
assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
&& (ii==0 || pSubLoop->u.btree.pIndex==pCov)
&& (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
){
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
pCov = pSubLoop->u.btree.pIndex;
}else{
pCov = 0;
}
if( sqlite3WhereUsesDeferredSeek(pSubWInfo) ){
pWInfo->bDeferredSeek = 1;
}
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
sqlite3ExprDelete(db, pDelete);
}
}
ExplainQueryPlanPop(pParse);
assert( pLevel->pWLoop==pLoop );
assert( (pLoop->wsFlags & WHERE_MULTI_OR)!=0 );
assert( (pLoop->wsFlags & WHERE_IN_ABLE)==0 );
pLevel->u.pCoveringIdx = pCov;
if( pCov ) pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
sqlite3ExprDelete(db, pAndExpr);
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeGoto(v, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
/* Set the P2 operand of the OP_Return opcode that will end the current
** loop to point to this spot, which is the top of the next containing
** loop. The byte-code formatter will use that P2 value as a hint to
** indent everything in between the this point and the final OP_Return.
** See tag-20220407a in vdbe.c and shell.c */
assert( pLevel->op==OP_Return );
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
{
/* Case 6: There is no usable index. We must do a complete
** scan of the entire table.
*/
static const u8 aStep[] = { OP_Next, OP_Prev };
static const u8 aStart[] = { OP_Rewind, OP_Last };
assert( bRev==0 || bRev==1 );
if( pTabItem->fg.isRecursive ){
/* Tables marked isRecursive have only a single row that is stored in
** a pseudo-cursor. No need to Rewind or Next such cursors. */
pLevel->op = OP_Noop;
}else{
codeCursorHint(pTabItem, pWInfo, pLevel, 0);
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev],iCur,pLevel->addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}
}
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
pLevel->addrVisit = sqlite3VdbeCurrentAddr(v);
#endif
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
**
** This loop may run between one and three times, depending on the
** constraints to be generated. The value of stack variable iLoop
** determines the constraints coded by each iteration, as follows:
**
** iLoop==1: Code only expressions that are entirely covered by pIdx.
** iLoop==2: Code remaining expressions that do not contain correlated
** sub-queries.
** iLoop==3: Code all remaining expressions.
**
** An effort is made to skip unnecessary iterations of the loop.
**
** This optimization of causing simple query restrictions to occur before
** more complex one is call the "push-down" optimization in MySQL. Here
** in SQLite, the name is "MySQL push-down", since there is also another
** totally unrelated optimization called "WHERE-clause push-down".
** Sometimes the qualifier is omitted, resulting in an ambiguity, so beware.
*/
iLoop = (pIdx ? 1 : 2);
do{
int iNext = 0; /* Next value for iLoop */
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
Expr *pE;
int skipLikeAddr = 0;
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
testcase( pWInfo->untestedTerms==0
&& (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
pWInfo->untestedTerms = 1;
continue;
}
pE = pTerm->pExpr;
assert( pE!=0 );
if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ){
if( !ExprHasProperty(pE,EP_OuterON|EP_InnerON) ){
/* Defer processing WHERE clause constraints until after outer
** join processing. tag-20220513a */
continue;
}else if( (pTabItem->fg.jointype & JT_LEFT)==JT_LEFT
&& !ExprHasProperty(pE,EP_OuterON) ){
for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); }
pNew->op = op;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew);
}
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
/*
** Analyze a term that consists of two or more OR-connected
** subterms. So in:
**
** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13)
** ^^^^^^^^^^^^^^^^^^^^
**
** This routine analyzes terms such as the middle term in the above example.
** A WhereOrTerm object is computed and attached to the term under
** analysis, regardless of the outcome of the analysis. Hence:
**
** WhereTerm.wtFlags |= TERM_ORINFO
** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object
**
** The term being analyzed must have two or more of OR-connected subterms.
** A single subterm might be a set of AND-connected sub-subterms.
** Examples of terms under analysis:
**
** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5
** (B) x=expr1 OR expr2=x OR x=expr3
** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
** (F) x>A OR (x=A AND y>=B)
**
** CASE 1:
**
** If all subterms are of the form T.C=expr for some single column of C and
** a single table T (as shown in example B above) then create a new virtual
** term that is an equivalent IN expression. In other words, if the term
** being analyzed is:
**
** x = expr1 OR expr2 = x OR x = expr3
**
** then create a new virtual term like this:
**
** x IN (expr1,expr2,expr3)
**
** CASE 2:
**
** If there are exactly two disjuncts and one side has x>A and the other side
** has x=A (for the same x and A) then add a new virtual conjunct term to the
** WHERE clause of the form "x>=A". Example:
**
** x>A OR (x=A AND y>B) adds: x>=A
**
** The added conjunct can sometimes be helpful in query planning.
**
** CASE 3:
**
** If all subterms are indexable by a single table T, then set
**
** WhereTerm.eOperator = WO_OR
** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T
**
** A subterm is "indexable" if it is of the form
** "T.C <op> <expr>" where C is any column of table T and
** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
** A subterm is also indexable if it is an AND of two or more
** subsubterms at least one of which is indexable. Indexable AND
** subterms have their eOperator set to WO_AND and they have
** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
**
** From another point of view, "indexable" means that the subterm could
** potentially be used with an index if an appropriate index exists.
** This analysis does not consider whether or not the index exists; that
** is decided elsewhere. This analysis only looks at whether subterms
** appropriate for indexing exist.
**
** All examples A through E above satisfy case 3. But if a term
** also satisfies case 1 (such as B) we know that the optimizer will
** always prefer case 1, so in that case we pretend that case 3 is not
** satisfied.
**
** It might be the case that multiple tables are indexable. For example,
** (E) above is indexable on tables P, Q, and R.
**
** Terms that satisfy case 3 are candidates for lookup by using
** separate indices to find rowids for each subterm and composing
** the union of all rowids using a RowSet object. This is similar
** to "bitmap indices" in other database engines.
**
** OTHERWISE:
**
** If none of cases 1, 2, or 3 apply, then leave the eOperator set to
** zero. This term is not useful for search.
*/
static void exprAnalyzeOrTerm(
SrcList *pSrc, /* the FROM clause */
WhereClause *pWC, /* the complete WHERE clause */
int idxTerm /* Index of the OR-term to be analyzed */
){
WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
Parse *pParse = pWInfo->pParse; /* Parser context */
sqlite3 *db = pParse->db; /* Database connection */
WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */
Expr *pExpr = pTerm->pExpr; /* The expression of the term */
int i; /* Loop counters */
WhereClause *pOrWc; /* Breakup of pTerm into subterms */
WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */
WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */
Bitmask chngToIN; /* Tables that might satisfy case 1 */
Bitmask indexable; /* Tables that are indexable, satisfying case 2 */
/*
** Break the OR clause into its separate subterms. The subterms are
** stored in a WhereClause structure containing within the WhereOrInfo
** object that is attached to the original OR clause term.
*/
assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 );
assert( pExpr->op==TK_OR );
pTerm->u.pOrInfo = pOrInfo = sqlite3DbMallocZero(db, sizeof(*pOrInfo));
if( pOrInfo==0 ) return;
pTerm->wtFlags |= TERM_ORINFO;
b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pOther->leftCursor);
}
indexable &= b;
if( (pOrTerm->eOperator & WO_EQ)==0 ){
chngToIN = 0;
}else{
chngToIN &= b;
}
}
}
/*
** Record the set of tables that satisfy case 3. The set might be
** empty.
*/
pOrInfo->indexable = indexable;
pTerm->eOperator = WO_OR;
pTerm->leftCursor = -1;
if( indexable ){
pWC->hasOr = 1;
}
/* For a two-way OR, attempt to implementation case 2.
*/
if( indexable && pOrWc->nTerm==2 ){
int iOne = 0;
WhereTerm *pOne;
while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){
int iTwo = 0;
WhereTerm *pTwo;
while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){
whereCombineDisjuncts(pSrc, pWC, pOne, pTwo);
}
}
}
/*
** chngToIN holds a set of tables that *might* satisfy case 1. But
** we have to do some additional checking to see if case 1 really
** is satisfied.
**
** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means
** that there is no possibility of transforming the OR clause into an
** IN operator because one or more terms in the OR clause contain
** something other than == on a column in the single table. The 1-bit
** case means that every term of the OR clause is of the form
** "table.column=expr" for some single table. The one bit that is set
** will correspond to the common table. We still need to check to make
** sure the same column is used on all terms. The 2-bit case is when
** the all terms are of the form "table1.column=table2.column". It
** might be possible to form an IN operator with either table1.column
** or table2.column as the LHS if either is common to every term of
** the OR clause.
**
** Note that terms of the form "table.column1=table.column2" (the
** same table on both sizes of the ==) cannot be optimized.
*/
if( chngToIN ){
int okToChngToIN = 0; /* True if the conversion to IN is valid */
int iColumn = -1; /* Column index on lhs of IN operator */
int iCursor = -1; /* Table cursor common to all terms */
int j = 0; /* Loop counter */
/* Search for a table and column that appears on one side or the
** other of the == operator in every subterm. That table and column
** will be recorded in iCursor and iColumn. There might not be any
** such table and column. Set okToChngToIN if an appropriate table
** and column is found but leave okToChngToIN false if not found.
*/
for(j=0; j<2 && !okToChngToIN; j++){
Expr *pLeft = 0;
pOrTerm = pOrWc->a;
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
assert( pOrTerm->eOperator & WO_EQ );
pOrTerm->wtFlags &= ~TERM_OK;
if( pOrTerm->leftCursor==iCursor ){
/* This is the 2-bit case and we are on the second iteration and
** current term is from the first iteration. So skip this term. */
assert( j==1 );
continue;
}
if( (chngToIN & sqlite3WhereGetMask(&pWInfo->sMaskSet,
pOrTerm->leftCursor))==0 ){
/* This term must be of the form t1.a==t2.b where t2 is in the
** chngToIN set but t1 is not. This term will be either preceded
** or followed by an inverted copy (t2.b==t1.a). Skip this term
** and use its inversion. */
testcase( pOrTerm->wtFlags & TERM_COPIED );
testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
continue;
}
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
iColumn = pOrTerm->u.x.leftColumn;
iCursor = pOrTerm->leftCursor;
pLeft = pOrTerm->pExpr->pLeft;
break;
}
if( i<0 ){
/* No candidate table+column was found. This can only occur
** on the second iteration */
assert( j==1 );
assert( IsPowerOfTwo(chngToIN) );
assert( chngToIN==sqlite3WhereGetMask(&pWInfo->sMaskSet, iCursor) );
break;
}
testcase( j==1 );
/* We have found a candidate table and column. Check to see if that
** table and column is common to every term in the OR clause */
okToChngToIN = 1;
for(; i>=0 && okToChngToIN; i--, pOrTerm++){
assert( pOrTerm->eOperator & WO_EQ );
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OK;
}else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR
&& sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
)){
okToChngToIN = 0;
}else{
assert( pSrc!=0 );
if( pExpr->op==TK_IS
&& pSrc->nSrc>=2
&& (pSrc->a[0].fg.jointype & JT_LTORJ)!=0
){
return 0; /* (4) */
}
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlite3ExprAffinity(pExpr->pRight);
if( aff1!=aff2
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
){
return 0; /* (5) */
}
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
if( !sqlite3IsBinary(pColl)
&& !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
){
return 0; /* (6) */
}
return 1;
}
/*
** Recursively walk the expressions of a SELECT statement and generate
** a bitmask indicating which tables are used in that expression
** tree.
*/
static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
Bitmask mask = 0;
while( pS ){
SrcList *pSrc = pS->pSrc;
mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pEList);
mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pGroupBy);
mask |= sqlite3WhereExprListUsage(pMaskSet, pS->pOrderBy);
mask |= sqlite3WhereExprUsage(pMaskSet, pS->pWhere);
mask |= sqlite3WhereExprUsage(pMaskSet, pS->pHaving);
if( ALWAYS(pSrc!=0) ){
int i;
for(i=0; i<pSrc->nSrc; i++){
if( pSrc->a[i].fg.isSubquery ){
mask |= exprSelectUsage(pMaskSet, pSrc->a[i].u4.pSubq->pSelect);
}
if( pSrc->a[i].fg.isUsing==0 ){
mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn);
}
if( pSrc->a[i].fg.isTabFunc ){
mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg);
}
}
}
pS = pS->pPrior;
}
return mask;
}
/*
** Expression pExpr is one operand of a comparison operator that might
** be useful for indexing. This routine checks to see if pExpr appears
** in any index. Return TRUE (1) if pExpr is an indexed term and return
** FALSE (0) if not. If TRUE is returned, also set aiCurCol[0] to the cursor
** number of the table that is indexed and aiCurCol[1] to the column number
** of the column that is indexed, or XN_EXPR (-2) if an expression is being
** indexed.
**
** If pExpr is a TK_COLUMN column reference, then this routine always returns
** true even if that particular column is not indexed, because the column
** might be added to an automatic index later.
*/
static SQLITE_NOINLINE int exprMightBeIndexed2(
SrcList *pFrom, /* The FROM clause */
int *aiCurCol, /* Write the referenced table cursor and column here */
Expr *pExpr, /* An operand of a comparison operator */
int j /* Start looking with the j-th pFrom entry */
){
Index *pIdx;
int i;
int iCur;
do{
iCur = pFrom->a[j].iCursor;
for(pIdx=pFrom->a[j].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->aColExpr==0 ) continue;
for(i=0; i<pIdx->nKeyCol; i++){
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
assert( pIdx->bHasExpr );
if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0
&& !sqlite3ExprIsConstant(0,pIdx->aColExpr->a[i].pExpr)
){
aiCurCol[0] = iCur;
aiCurCol[1] = XN_EXPR;
return 1;
}
}
}
}while( ++j < pFrom->nSrc );
return 0;
}
static int exprMightBeIndexed(
SrcList *pFrom, /* The FROM clause */
int *aiCurCol, /* Write the referenced table cursor & column here */
Expr *pExpr, /* An operand of a comparison operator */
int op /* The specific comparison operator */
){
int i;
/* If this expression is a vector to the left or right of a
** inequality constraint (>, <, >= or <=), perform the processing
** on the first element of the vector. */
assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE );
assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
assert( op<=TK_GE );
if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
assert( ExprUseXList(pExpr) );
pExpr = pExpr->x.pList->a[0].pExpr;
}
if( pExpr->op==TK_COLUMN ){
aiCurCol[0] = pExpr->iTable;
aiCurCol[1] = pExpr->iColumn;
return 1;
}
for(i=0; i<pFrom->nSrc; i++){
Index *pIdx;
for(pIdx=pFrom->a[i].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->aColExpr ){
return exprMightBeIndexed2(pFrom,aiCurCol,pExpr,i);
}
}
}
return 0;
}
/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in. The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
**
** If the expression is of the form "<expr> <op> X" it gets commuted
** to the standard form of "X <op> <expr>".
**
** If the expression is of the form "X <op> Y" where both X and Y are
** columns, then the original expression is unchanged and a new virtual
** term of the form "Y <op> X" is added to the WHERE clause and
** analyzed separately. The original term is marked with TERM_COPIED
** and the new term is marked with TERM_DYNAMIC (because it's pExpr
** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it
** is a commuted copy of a prior term.) The original term has nChild=1
** and the copy has idxParent set to the index of the original term.
*/
static void exprAnalyze(
SrcList *pSrc, /* the FROM clause */
WhereClause *pWC, /* the WHERE clause */
int idxTerm /* Index of the term to be analyzed */
){
WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
WhereTerm *pTerm; /* The term to be analyzed */
WhereMaskSet *pMaskSet; /* Set of table index masks */
/* The ORDER BY LIMIT optimization does not apply. Jump to the
** continuation of the inner-most loop. */
return pWInfo->iContinue;
}
pInner = &pWInfo->a[pWInfo->nLevel-1];
assert( pInner->addrNxt!=0 );
return pInner->pRJ ? pWInfo->iContinue : pInner->addrNxt;
}
/*
** While generating code for the min/max optimization, after handling
** the aggregate-step call to min() or max(), check to see if any
** additional looping is required. If the output order is such that
** we are certain that the correct answer has already been found, then
** code an OP_Goto to by pass subsequent processing.
**
** Any extra OP_Goto that is coded here is an optimization. The
** correct answer should be obtained regardless. This OP_Goto just
** makes the answer appear faster.
*/
SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe *v, WhereInfo *pWInfo){
WhereLevel *pInner;
int i;
if( !pWInfo->bOrderedInnerLoop ) return;
if( pWInfo->nOBSat==0 ) return;
for(i=pWInfo->nLevel-1; i>=0; i--){
pInner = &pWInfo->a[i];
if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)!=0 ){
sqlite3VdbeGoto(v, pInner->addrNxt);
return;
}
}
sqlite3VdbeGoto(v, pWInfo->iBreak);
}
/*
** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause.
*/
SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){
assert( pWInfo->iContinue!=0 );
return pWInfo->iContinue;
}
/*
** Return the VDBE address or label to jump to in order to break
** out of a WHERE loop.
*/
SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
return pWInfo->iBreak;
}
/*
** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to
** operate directly on the rowids returned by a WHERE clause. Return
** ONEPASS_SINGLE (1) if the statement can operation directly because only
** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass
** optimization can be used on multiple
**
** If the ONEPASS optimization is used (if this routine returns true)
** then also write the indices of open cursors used by ONEPASS
** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
** table and iaCur[1] gets the cursor used by an auxiliary index.
** Either value may be -1, indicating that cursor is not used.
** Any cursors returned will have been opened for writing.
**
** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is
** unable to use the ONEPASS optimization.
*/
SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2);
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){
sqlite3DebugPrintf("%s cursors: %d %d\n",
pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI",
aiCur[0], aiCur[1]);
}
#endif
return pWInfo->eOnePass;
}
/*
** Return TRUE if the WHERE loop uses the OP_DeferredSeek opcode to move
** the data cursor to the row selected by the index cursor.
*/
SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo *pWInfo){
return pWInfo->bDeferredSeek;
}
/*
** Move the content of pSrc into pDest
*/
static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
pDest->n = pSrc->n;
memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
}
/*
** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet.
**
** The new entry might overwrite an existing entry, or it might be
** appended, or it might be discarded. Do whatever is the right thing
** so that pSet keeps the N_OR_COST best entries seen so far.
*/
static int whereOrInsert(
WhereOrSet *pSet, /* The WhereOrSet to be updated */
Bitmask prereq, /* Prerequisites of the new entry */
LogEst rRun, /* Run-cost of the new entry */
LogEst nOut /* Number of outputs for the new entry */
){
u16 i;
WhereOrCost *p;
for(i=pSet->n, p=pSet->a; i>0; i--, p++){
if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
goto whereOrInsert_done;
}
if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){
return 0;
}
}
if( pSet->n<N_OR_COST ){
p = &pSet->a[pSet->n++];
p->nOut = nOut;
}else{
p = pSet->a;
for(i=1; i<pSet->n; i++){
if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i;
}
if( p->rRun<=rRun ) return 0;
}
whereOrInsert_done:
p->prereq = prereq;
p->rRun = rRun;
if( p->nOut>nOut ) p->nOut = nOut;
return 1;
}
/*
** Return the bitmask for the given cursor number. Return 0 if
** iCursor is not in the set.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){
int i;
assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 );
assert( iCursor>=-1 );
if( pMaskSet->ix[0]==iCursor ){
return 1;
}
for(i=1; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){
return MASKBIT(i);
}
}
return 0;
}
/* Allocate memory that is automatically freed when pWInfo is freed.
*/
SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte){
WhereMemBlock *pBlock;
pBlock = sqlite3DbMallocRawNN(pWInfo->pParse->db, nByte+sizeof(*pBlock));
if( pBlock ){
pBlock->pNext = pWInfo->pMemToFree;
pBlock->sz = nByte;
pWInfo->pMemToFree = pBlock;
pBlock++;
}
return (void*)pBlock;
}
SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte){
void *pNew = sqlite3WhereMalloc(pWInfo, nByte);
if( pNew && pOld ){
WhereMemBlock *pOldBlk = (WhereMemBlock*)pOld;
pOldBlk--;
assert( pOldBlk->sz<nByte );
memcpy(pNew, pOld, pOldBlk->sz);
}
return pNew;
}
/*
** Create a new mask for cursor iCursor.
**
** There is one cursor per table in the FROM clause. The number of
** tables in the FROM clause is limited by a test early in the
** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[]
** array will never overflow.
*/
static void createMask(WhereMaskSet *pMaskSet, int iCursor){
assert( pMaskSet->n < ArraySize(pMaskSet->ix) );
pMaskSet->ix[pMaskSet->n++] = iCursor;
}
/*
** If the right-hand branch of the expression is a TK_COLUMN, then return
** a pointer to the right-hand branch. Otherwise, return NULL.
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
p = sqlite3ExprSkipCollateAndLikely(p->pRight);
if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
return p;
}
return 0;
}
/*
** Term pTerm is guaranteed to be a WO_IN term. It may be a component term
** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)".
** This function checks to see if the term is compatible with an index
** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so,
** it returns a pointer to the name of the collation sequence (e.g. "BINARY"
** or "NOCASE") used by the comparison in pTerm. If it is not compatible
** with affinity idxaff, NULL is returned.
*/
static SQLITE_NOINLINE const char *indexInAffinityOk(
Parse *pParse,
WhereTerm *pTerm,
u8 idxaff
){
Expr *pX = pTerm->pExpr;
Expr inexpr;
assert( pTerm->eOperator & WO_IN );
if( sqlite3ExprIsVector(pX->pLeft) ){
int iField = pTerm->u.x.iField - 1;
inexpr.flags = 0;
inexpr.op = TK_EQ;
inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr;
assert( ExprUseXSelect(pX) );
inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr;
pX = &inexpr;
}
if( sqlite3IndexAffinityOk(pX, idxaff) ){
CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX);
return pRet ? pRet->zName : sqlite3StrBINARY;
}
return 0;
}
/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
*/
static WhereTerm *whereScanNext(WhereScan *pScan){
int iCur; /* The cursor on the LHS of the term */
i16 iColumn; /* The column on the LHS of the term. -1 for IPK */
Expr *pX; /* An expression being tested */
WhereClause *pWC; /* Shorthand for pScan->pWC */
WhereTerm *pTerm; /* The term being tested */
int k = pScan->k; /* Where to start scanning */
assert( pScan->iEquiv<=pScan->nEquiv );
pWC = pScan->pWC;
while(1){
iColumn = pScan->aiColumn[pScan->iEquiv-1];
iCur = pScan->aiCur[pScan->iEquiv-1];
assert( pWC!=0 );
assert( iCur>=0 );
do{
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 || pTerm->leftCursor<0 );
if( pTerm->leftCursor==iCur
&& pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_OuterON))
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aiCur)
&& (pX = whereRightSubexprIsColumn(pTerm->pExpr))!=0
){
int j;
for(j=0; j<pScan->nEquiv; j++){
if( pScan->aiCur[j]==pX->iTable
&& pScan->aiColumn[j]==pX->iColumn ){
break;
}
}
if( j==pScan->nEquiv ){
pScan->aiCur[j] = pX->iTable;
pScan->aiColumn[j] = pX->iColumn;
pScan->nEquiv++;
}
}
if( (pTerm->eOperator & pScan->opMask)!=0 ){
/* Verify the affinity and collating sequence match */
if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
const char *zCollName;
Parse *pParse = pWC->pWInfo->pParse;
pX = pTerm->pExpr;
if( (pTerm->eOperator & WO_IN) ){
zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff);
if( !zCollName ) continue;
}else{
CollSeq *pColl;
if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
continue;
}
assert(pX->pLeft);
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
zCollName = pColl ? pColl->zName : sqlite3StrBINARY;
}
pTab = pTabList->a[0].pSTab;
/* If any of the expressions is an IPK column on table iBase, then return
** true. Note: The (p->iTable==iBase) part of this test may be false if the
** current SELECT is a correlated sub-query.
*/
for(i=0; i<pDistinct->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
if( NEVER(p==0) ) continue;
if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue;
if( p->iTable==iBase && p->iColumn<0 ) return 1;
}
/* Loop through all indices on the table, checking each to see if it makes
** the DISTINCT qualifier redundant. It does so if:
**
** 1. The index is itself UNIQUE, and
**
** 2. All of the columns in the index are either part of the pDistinct
** list, or else the WHERE clause contains a term of the form "col=X",
** where X is a constant value. The collation sequences of the
** comparison and select-list expressions must match those of the index.
**
** 3. All of those index columns for which the WHERE clause does not
** contain a "col=X" term are subject to a NOT NULL constraint.
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( !IsUniqueIndex(pIdx) ) continue;
if( pIdx->pPartIdxWhere ) continue;
for(i=0; i<pIdx->nKeyCol; i++){
if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
if( indexColumnNotNull(pIdx, i)==0 ) break;
}
}
if( i==pIdx->nKeyCol ){
/* This index implies that the DISTINCT qualifier is redundant. */
return 1;
}
}
return 0;
}
/*
** Estimate the logarithm of the input value to base 2.
*/
static LogEst estLog(LogEst N){
return N<=10 ? 0 : sqlite3LogEst(N) - 33;
}
/*
** Convert OP_Column opcodes to OP_Copy in previously generated code.
**
** This routine runs over generated VDBE code and translates OP_Column
** opcodes into OP_Copy when the table is being accessed via co-routine
** instead of via table lookup.
**
** If the iAutoidxCur is not zero, then any OP_Rowid instructions on
** cursor iTabCur are transformed into OP_Sequence opcode for the
** iAutoidxCur cursor, in order to generate unique rowids for the
** automatic index being generated.
*/
static void translateColumnToCopy(
Parse *pParse, /* Parsing context */
int iStart, /* Translate from this opcode to the end */
int iTabCur, /* OP_Column/OP_Rowid references to this table */
int iRegister, /* The first column is in this register */
int iAutoidxCur /* If non-zero, cursor of autoindex being generated */
){
Vdbe *v = pParse->pVdbe;
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
if( pParse->db->mallocFailed ) return;
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("CHECKING for column-to-copy on cursor %d for %d..%d\n",
iTabCur, iStart, iEnd);
}
#endif
for(; iStart<iEnd; iStart++, pOp++){
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("TRANSLATE OP_Column to OP_Copy at %d\n", iStart);
}
#endif
pOp->opcode = OP_Copy;
pOp->p1 = pOp->p2 + iRegister;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */
}else if( pOp->opcode==OP_Rowid ){
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("TRANSLATE OP_Rowid to OP_Sequence at %d\n", iStart);
}
#endif
pOp->opcode = OP_Sequence;
pOp->p1 = iAutoidxCur;
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
pOp->p3 = 0;
}
#endif
}
}
}
/*
** Two routines for printing the content of an sqlite3_index_info
** structure. Used for testing and debugging only. If neither
** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
** are no-ops.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
static void whereTraceIndexInfoInputs(
sqlite3_index_info *p, /* The IndexInfo object */
Table *pTab /* The TABLE that is the virtual table */
){
int i;
if( (sqlite3WhereTrace & 0x10)==0 ) return;
sqlite3DebugPrintf("sqlite3_index_info inputs for %s:\n", pTab->zName);
for(i=0; i<p->nConstraint; i++){
sqlite3DebugPrintf(
" constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
i,
p->aConstraint[i].iColumn,
p->aConstraint[i].iTermOffset,
p->aConstraint[i].op,
p->aConstraint[i].usable,
sqlite3_vtab_collation(p,i));
}
for(i=0; i<p->nOrderBy; i++){
sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n",
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
/*
** Argument pIdx represents an automatic index that the current statement
** will create and populate. Add an OP_Explain with text of the form:
**
** CREATE AUTOMATIC INDEX ON <table>(<cols>) [WHERE <expr>]
**
** This is only required if sqlite3_stmt_scanstatus() is enabled, to
** associate an SQLITE_SCANSTAT_NCYCLE and SQLITE_SCANSTAT_NLOOP
** values with. In order to avoid breaking legacy code and test cases,
** the OP_Explain is not added if this is an EXPLAIN QUERY PLAN command.
*/
static void explainAutomaticIndex(
Parse *pParse,
Index *pIdx, /* Automatic index to explain */
int bPartial, /* True if pIdx is a partial index */
int *pAddrExplain /* OUT: Address of OP_Explain */
){
if( IS_STMT_SCANSTATUS(pParse->db) && pParse->explain!=2 ){
Table *pTab = pIdx->pTable;
const char *zSep = "";
char *zText = 0;
int ii = 0;
sqlite3_str *pStr = sqlite3_str_new(pParse->db);
sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName);
assert( pIdx->nColumn>1 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID || !HasRowid(pTab) );
for(ii=0; ii<(pIdx->nColumn-1); ii++){
const char *zName = 0;
int iCol = pIdx->aiColumn[ii];
zName = pTab->aCol[iCol].zCnName;
sqlite3_str_appendf(pStr, "%s%s", zSep, zName);
zSep = ", ";
}
zText = sqlite3_str_finish(pStr);
if( zText==0 ){
sqlite3OomFault(pParse->db);
}else{
*pAddrExplain = sqlite3VdbeExplain(
pParse, 0, "%s)%s", zText, (bPartial ? " WHERE <expr>" : "")
);
sqlite3_free(zText);
}
}
}
#else
# define explainAutomaticIndex(a,b,c,d)
#endif
/*
** Generate code to construct the Index object for an automatic index
** and to set up the WhereLevel object pLevel so that the code generator
** makes use of the automatic index.
*/
static SQLITE_NOINLINE void constructAutomaticIndex(
Parse *pParse, /* The parsing context */
WhereClause *pWC, /* The WHERE clause */
const Bitmask notReady, /* Mask of cursors that are not available */
WhereLevel *pLevel /* Write new index here */
){
int nKeyCol; /* Number of columns in the constructed index */
WhereTerm *pTerm; /* A single term of the WHERE clause */
WhereTerm *pWCEnd; /* End of pWC->a[] */
Index *pIdx; /* Object describing the transient index */
Vdbe *v; /* Prepared statement under construction */
int addrInit; /* Address of the initialization bypass jump */
Table *pTable; /* The table being indexed */
int addrTop; /* Top of the index fill loop */
int regRecord; /* Register holding an index record */
int n; /* Column counter */
int i; /* Loop counter */
int mxBitCol; /* Maximum column in pSrc->colUsed */
CollSeq *pColl; /* Collating sequence to on a column */
WhereLoop *pLoop; /* The Loop object */
char *zNotUsed; /* Extra space on the end of pIdx */
Bitmask idxCols; /* Bitmap of columns used for indexing */
Bitmask extraCols; /* Bitmap of additional columns */
u8 sentWarning = 0; /* True if a warning has been issued */
u8 useBloomFilter = 0; /* True to also add a Bloom filter */
Expr *pPartial = 0; /* Partial Index Expression */
int iContinue = 0; /* Jump here to skip excluded rows */
SrcList *pTabList; /* The complete FROM clause */
SrcItem *pSrc; /* The FROM clause term to get the next index */
int addrCounter = 0; /* Address where integer counter is initialized */
int regBase; /* Array of registers where record is assembled */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int addrExp = 0; /* Address of OP_Explain */
#endif
/* Generate code to skip over the creation and initialization of the
** transient index on 2nd and subsequent iterations of the loop. */
v = pParse->pVdbe;
assert( v!=0 );
addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
/* Count the number of columns that will be added to the index
** and used to match WHERE clause constraints */
nKeyCol = 0;
pTabList = pWC->pWInfo->pTabList;
pSrc = &pTabList->a[pLevel->iFrom];
pTable = pSrc->pSTab;
pWCEnd = &pWC->a[pWC->nTerm];
pLoop = pLevel->pWLoop;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
/* Make the automatic index a partial index if there are terms in the
** WHERE clause (or the ON clause of a LEFT join) that constrain which
** rows of the target table (pSrc) that can be used. */
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom, 0)
){
pPartial = sqlite3ExprAnd(pParse, pPartial,
sqlite3ExprDup(pParse->db, pExpr, 0));
}
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol;
Bitmask cMask;
){
int i;
WhereTerm *pTerm;
Parse *pParse;
if( jointype & JT_LTORJ ) return 0;
pParse = pWC->pWInfo->pParse;
while( pWhere->op==TK_AND ){
if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
}
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
&& !sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, -1)
&& (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
}
}
return 0;
}
/*
** pIdx is an index containing expressions. Check it see if any of the
** expressions in the index match the pExpr expression.
*/
static int exprIsCoveredByIndex(
const Expr *pExpr,
const Index *pIdx,
int iTabCur
){
int i;
for(i=0; i<pIdx->nColumn; i++){
if( pIdx->aiColumn[i]==XN_EXPR
&& sqlite3ExprCompare(0, pExpr, pIdx->aColExpr->a[i].pExpr, iTabCur)==0
){
return 1;
}
}
return 0;
}
/*
** Structure passed to the whereIsCoveringIndex Walker callback.
*/
typedef struct CoveringIndexCheck CoveringIndexCheck;
struct CoveringIndexCheck {
Index *pIdx; /* The index */
int iTabCur; /* Cursor number for the corresponding table */
u8 bExpr; /* Uses an indexed expression */
u8 bUnidx; /* Uses an unindexed column not within an indexed expr */
};
/*
** Information passed in is pWalk->u.pCovIdxCk. Call it pCk.
**
** If the Expr node references the table with cursor pCk->iTabCur, then
** make sure that column is covered by the index pCk->pIdx. We know that
** all columns less than 63 (really BMS-1) are covered, so we don't need
** to check them. But we do need to check any column at 63 or greater.
**
** If the index does not cover the column, then set pWalk->eCode to
** non-zero and return WRC_Abort to stop the search.
**
** If this node does not disprove that the index can be a covering index,
** then just return WRC_Continue, to continue the search.
**
** If pCk->pIdx contains indexed expressions and one of those expressions
** matches pExpr, then prune the search.
*/
static int whereIsCoveringIndexWalkCallback(Walker *pWalk, Expr *pExpr){
int i; /* Loop counter */
const Index *pIdx; /* The index of interest */
const i16 *aiColumn; /* Columns contained in the index */
u16 nColumn; /* Number of columns in the index */
CoveringIndexCheck *pCk; /* Info about this search */
pCk = pWalk->u.pCovIdxCk;
pIdx = pCk->pIdx;
if( (pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN) ){
/* if( pExpr->iColumn<(BMS-1) && pIdx->bHasExpr==0 ) return WRC_Continue;*/
if( pExpr->iTable!=pCk->iTabCur ) return WRC_Continue;
pIdx = pWalk->u.pCovIdxCk->pIdx;
aiColumn = pIdx->aiColumn;
nColumn = pIdx->nColumn;
for(i=0; i<nColumn; i++){
if( aiColumn[i]==pExpr->iColumn ) return WRC_Continue;
}
pCk->bUnidx = 1;
return WRC_Abort;
}else if( pIdx->bHasExpr
&& exprIsCoveredByIndex(pExpr, pIdx, pWalk->u.pCovIdxCk->iTabCur) ){
pCk->bExpr = 1;
return WRC_Prune;
}
return WRC_Continue;
}
/*
** pIdx is an index that covers all of the low-number columns used by
** pWInfo->pSelect (columns from 0 through 62) or an index that has
** expressions terms. Hence, we cannot determine whether or not it is
** a covering index by using the colUsed bitmasks. We have to do a search
** to see if the index is covering. This routine does that search.
**
** The return value is one of these:
**
** 0 The index is definitely not a covering index
**
** WHERE_IDX_ONLY The index is definitely a covering index
**
** WHERE_EXPRIDX The index is likely a covering index, but it is
** difficult to determine precisely because of the
** expressions that are indexed. Score it as a
** covering index, but still keep the main table open
** just in case we need it.
}else if( m==0
&& (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700))
){
WHERETRACE(0x200,
("-> %s is a covering index according to bitmasks\n",
pProbe->zName, m==0 ? "is" : "is not"));
pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
}
}
/* Full scan via index */
if( b
|| !HasRowid(pTab)
|| pProbe->pPartIdxWhere!=0
|| pSrc->fg.isIndexedBy
|| ( m==0
&& pProbe->bUnordered==0
&& (pProbe->szIdxRow<pTab->szTabRow)
&& (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
&& sqlite3GlobalConfig.bUseCis
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
)
){
pNew->iSortIdx = b ? iSortIdx : 0;
/* The cost of visiting the index rows is N*K, where K is
** between 1.1 and 3.0, depending on the relative sizes of the
** index and table rows. */
pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
if( m!=0 ){
/* If this is a non-covering index scan, add in the cost of
** doing table lookups. The cost will be 3x the number of
** lookups. Take into account WHERE clause terms that can be
** satisfied using just the index, and that do not require a
** table lookup. */
LogEst nLookup = rSize + 16; /* Base cost: N*3 */
int ii;
int iCur = pSrc->iCursor;
WhereClause *pWC2 = &pWInfo->sWC;
for(ii=0; ii<pWC2->nTerm; ii++){
WhereTerm *pTerm = &pWC2->a[ii];
if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
break;
}
/* pTerm can be evaluated using just the index. So reduce
** the expected number of table lookups accordingly */
if( pTerm->truthProb<=0 ){
nLookup += pTerm->truthProb;
}else{
nLookup--;
if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19;
}
}
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
}
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
if( (pSrc->fg.jointype & JT_RIGHT)!=0 && pProbe->aColExpr ){
/* Do not do an SCAN of a index-on-expression in a RIGHT JOIN
** because the cursor used to access the index might not be
** positioned to the correct row during the right-join no-match
** loop. */
}else{
rc = whereLoopInsert(pBuilder, pNew);
}
pNew->nOut = rSize;
if( rc ) break;
}
}
pBuilder->bldFlags1 = 0;
rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
if( pBuilder->bldFlags1==SQLITE_BLDF1_INDEXED ){
/* If a non-unique index is used, or if a prefix of the key for
** unique index is used (making the index functionally non-unique)
** then the sqlite_stat1 data becomes important for scoring the
** plan */
pTab->tabFlags |= TF_MaybeReanalyze;
}
#ifdef SQLITE_ENABLE_STAT4
sqlite3Stat4ProbeFree(pBuilder->pRec);
pBuilder->nRecValid = 0;
pBuilder->pRec = 0;
#endif
}
return rc;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return true if pTerm is a virtual table LIMIT or OFFSET term.
*/
static int isLimitTerm(WhereTerm *pTerm){
assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 );
return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT
&& pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
}
/*
** Return true if the first nCons constraints in the pUsage array are
** marked as in-use (have argvIndex>0). False otherwise.
*/
static int allConstraintsUsed(
struct sqlite3_index_constraint_usage *aUsage,
int nCons
){
int ii;
for(ii=0; ii<nCons; ii++){
if( aUsage[ii].argvIndex<=0 ) return 0;
}
return 1;
}
/*
** Argument pIdxInfo is already populated with all constraints that may
** be used by the virtual table identified by pBuilder->pNew->iTab. This
** function marks a subset of those constraints usable, invokes the
** xBestIndex method and adds the returned plan to pBuilder.
**
assert( pWInfo->nLevel>0 );
}
return notReady;
}
/*
** Check to see if there are any SEARCH loops that might benefit from
** using a Bloom filter. Consider a Bloom filter if:
**
** (1) The SEARCH happens more than N times where N is the number
** of rows in the table that is being considered for the Bloom
** filter.
** (2) Some searches are expected to find zero rows. (This is determined
** by the WHERE_SELFCULL flag on the term.)
** (3) Bloom-filter processing is not disabled. (Checked by the
** caller.)
** (4) The size of the table being searched is known by ANALYZE.
**
** This block of code merely checks to see if a Bloom filter would be
** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the
** WhereLoop. The implementation of the Bloom filter comes further
** down where the code for each WhereLoop is generated.
*/
static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
const WhereInfo *pWInfo
){
int i;
LogEst nSearch = 0;
assert( pWInfo->nLevel>=2 );
assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) );
for(i=0; i<pWInfo->nLevel; i++){
WhereLoop *pLoop = pWInfo->a[i].pWLoop;
const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ);
SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab];
Table *pTab = pItem->pSTab;
if( (pTab->tabFlags & TF_HasStat1)==0 ) break;
pTab->tabFlags |= TF_MaybeReanalyze;
if( i>=1
&& (pLoop->wsFlags & reqFlags)==reqFlags
/* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */
&& ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0)
){
if( nSearch > pTab->nRowLogEst ){
testcase( pItem->fg.jointype & JT_LEFT );
pLoop->wsFlags |= WHERE_BLOOMFILTER;
pLoop->wsFlags &= ~WHERE_IDX_ONLY;
WHERETRACE(0xffffffff, (
"-> use Bloom-filter on loop %c because there are ~%.1e "
"lookups into %s which has only ~%.1e rows\n",
pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
(double)sqlite3LogEstToInt(pTab->nRowLogEst)));
}
}
nSearch += pLoop->nOut;
}
}
/*
** The index pIdx is used by a query and contains one or more expressions.
** In other words pIdx is an index on an expression. iIdxCur is the cursor
** number for the index and iDataCur is the cursor number for the corresponding
** table.
**
** This routine adds IndexedExpr entries to the Parse->pIdxEpr field for
** each of the expressions in the index so that the expression code generator
** will know to replace occurrences of the indexed expression with
** references to the corresponding column of the index.
*/
static SQLITE_NOINLINE void whereAddIndexedExpr(
Parse *pParse, /* Add IndexedExpr entries to pParse->pIdxEpr */
Index *pIdx, /* The index-on-expression that contains the expressions */
int iIdxCur, /* Cursor number for pIdx */
SrcItem *pTabItem /* The FROM clause entry for the table */
){
int i;
IndexedExpr *p;
Table *pTab;
assert( pIdx->bHasExpr );
pTab = pIdx->pTable;
for(i=0; i<pIdx->nColumn; i++){
Expr *pExpr;
int j = pIdx->aiColumn[i];
if( j==XN_EXPR ){
pExpr = pIdx->aColExpr->a[i].pExpr;
}else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
}else{
continue;
}
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
if( p==0 ) break;
p->pIENext = pParse->pIdxEpr;
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x200 ){
sqlite3DebugPrintf("New pParse->pIdxEpr term {%d,%d}\n", iIdxCur, i);
if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(pExpr);
}
#endif
p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
p->iDataCur = pTabItem->iCursor;
p->iIdxCur = iIdxCur;
p->iIdxCol = i;
p->bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){
p->aff = pIdx->zColAff[i];
}
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
p->zIdxName = pIdx->zName;
#endif
pParse->pIdxEpr = p;
if( p->pIENext==0 ){
void *pArg = (void*)&pParse->pIdxEpr;
sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pArg);
}
}
}
/*
** Set the reverse-scan order mask to one for all tables in the query
** with the exception of MATERIALIZED common table expressions that have
** their own internal ORDER BY clauses.
**
** This implements the PRAGMA reverse_unordered_selects=ON setting.
** (Also SQLITE_DBCONFIG_REVERSE_SCANORDER).
*/
static SQLITE_NOINLINE void whereReverseScanOrder(WhereInfo *pWInfo){
int ii;
for(ii=0; ii<pWInfo->pTabList->nSrc; ii++){
SrcItem *pItem = &pWInfo->pTabList->a[ii];
if( !pItem->fg.isCte
|| pItem->u2.pCteUse->eM10d!=M10d_Yes
|| NEVER(pItem->fg.isSubquery==0)
|| pItem->u4.pSubq->pSelect->pOrderBy==0
){
pWInfo->revMask |= MASKBIT(ii);
}
}
}
/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an opaque structure that contains
** information needed to terminate the loop. Later, the calling routine
** should invoke sqlite3WhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.
**
** If an error occurs, this routine returns NULL.
**
** The basic idea is to do a nested loop, one loop for each table in
** the FROM clause of a select. (INSERT and UPDATE statements are the
** same as a SELECT with only a single table in the FROM clause.) For
** example, if the SQL is this:
**
** SELECT * FROM t1, t2, t3 WHERE ...;
**
** Then the code generated is conceptually like the following:
**
** foreach row1 in t1 do \ Code generated
** foreach row2 in t2 do |-- by sqlite3WhereBegin()
** foreach row3 in t3 do /
** ...
** end \ Code generated
** end |-- by sqlite3WhereEnd()
** end /
**
** Note that the loops might not be nested in the order in which they
** appear in the FROM clause if a different order is better able to make
** use of indices. Note also that when the IN operator appears in
** the WHERE clause, it might result in additional nested loops for
** scanning through all values on the right-hand side of the IN.
**
** There are Btree cursors associated with each table. t1 uses cursor
** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor.
** And so forth. This routine generates code to open those VDBE cursors
** and sqlite3WhereEnd() generates the code to close them.
**
** The code that sqlite3WhereBegin() generates leaves the cursors named
** in pTabList pointing at their appropriate entries. The [...] code
** can use OP_Column and OP_Rowid opcodes on these cursors to extract
** data from the various tables of the loop.
**
** If the WHERE clause is empty, the foreach loops must each scan their
** entire tables. Thus a three-way join is an O(N^3) operation. But if
** the tables have indices and there are terms in the WHERE clause that
** refer to those indices, a complete table scan can be avoided and the
** code will run much faster. Most of the work of this routine is checking
** to see if there are indices that can be used to speed up the loop.
**
** Terms of the WHERE clause are also used to limit which rows actually
** make it to the "..." in the middle of the loop. After each "foreach",
** terms of the WHERE clause that use only terms in that loop and outer
** loops are evaluated and if false a jump is made around all subsequent
** inner loops (or around the "..." if the test occurs within the inner-
** most loop)
**
** OUTER JOINS
**
** An outer join of tables t1 and t2 is conceptually coded as follows:
**
** foreach row1 in t1 do
** flag = 0
** foreach row2 in t2 do
** start:
** ...
** flag = 1
** end
** if flag==0 then
** move the row2 cursor to a null row
** goto start
** fi
** end
**
** ORDER BY CLAUSE PROCESSING
**
** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause
** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement
** if there is one. If there is no ORDER BY clause or if this routine
** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
**
** The iIdxCur parameter is the cursor number of an index. If
** WHERE_OR_SUBCLAUSE is set, iIdxCur is the cursor number of an index
** to use for OR clause processing. The WHERE clause should use this
** specific cursor. If WHERE_ONEPASS_DESIRED is set, then iIdxCur is
** the first cursor in an array of cursors for all indices. iIdxCur should
** be used to compute the appropriate cursor depending on which index is
** used.
*/
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */
Select *pSelect, /* The entire SELECT statement */
u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number
** If WHERE_USE_LIMIT, then the limit amount */
){
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
int nTabList; /* Number of elements in pTabList */
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
Bitmask notReady; /* Cursors that are not yet positioned */
WhereLoopBuilder sWLB; /* The WhereLoop builder */
WhereMaskSet *pMaskSet; /* The expression mask set */
WhereLevel *pLevel; /* A single level in pWInfo->a[] */
WhereLoop *pLoop; /* Pointer to a single WhereLoop object */
int ii; /* Loop counter */
sqlite3 *db; /* Database connection */
int rc; /* Return code */
u8 bFordelete = 0; /* OPFLAG_FORDELETE or zero, as appropriate */
assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || (
(wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
&& (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
));
/* Only one of WHERE_OR_SUBCLAUSE or WHERE_USE_LIMIT */
assert( (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
|| (wctrlFlags & WHERE_USE_LIMIT)==0 );
/* Variable initialization */
db = pParse->db;
memset(&sWLB, 0, sizeof(sWLB));
/* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
if( pOrderBy && pOrderBy->nExpr>=BMS ){
pOrderBy = 0;
wctrlFlags &= ~WHERE_WANT_DISTINCT;
wctrlFlags |= WHERE_KEEP_ALL_JOINS; /* Disable omit-noop-join opt */
}
/* The number of tables in the FROM clause is limited by the number of
** bits in a Bitmask
*/
testcase( pTabList->nSrc==BMS );
if( pTabList->nSrc>BMS ){
sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
return 0;
}
/* This function normally generates a nested loop for all tables in
** pTabList. But if the WHERE_OR_SUBCLAUSE flag is set, then we should
** only generate code for the first table in pTabList and assume that
** any cursors associated with subsequent tables are uninitialized.
*/
nTabList = (wctrlFlags & WHERE_OR_SUBCLAUSE) ? 1 : pTabList->nSrc;
/* Allocate and initialize the WhereInfo structure that will become the
** return value. A single allocation is used to store the WhereInfo
** struct, the contents of WhereInfo.a[], the WhereClause structure
** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
** field (type Bitmask) it must be aligned on an 8-byte boundary on
** some architectures. Hence the ROUND8() below.
*/
nByteWInfo = SZ_WHEREINFO(nTabList);
pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
if( db->mallocFailed ){
sqlite3DbFree(db, pWInfo);
pWInfo = 0;
goto whereBeginError;
}
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->pOrderBy = pOrderBy;
#if WHERETRACE_ENABLED
pWInfo->pWhere = pWhere;
#endif
pWInfo->pResultSet = pResultSet;
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
pWInfo->nLevel = nTabList;
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse);
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->iLimit = iAuxArg;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
pWInfo->pSelect = pSelect;
memset(&pWInfo->nOBSat, 0,
offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
pMaskSet = &pWInfo->sMaskSet;
pMaskSet->n = 0;
pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be
** a valid cursor number, to avoid an initial
** test for pMaskSet->n==0 in sqlite3WhereGetMask() */
sWLB.pWInfo = pWInfo;
sWLB.pWC = &pWInfo->sWC;
sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
whereLoopInit(sWLB.pNew);
#ifdef SQLITE_DEBUG
sWLB.pNew->cId = '*';
#endif
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator.
*/
sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo);
sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND);
/* Special case: No FROM clause
*/
if( nTabList==0 ){
if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0
&& OptimizationEnabled(db, SQLITE_DistinctOpt)
){
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}
if( ALWAYS(pWInfo->pSelect)
&& (pWInfo->pSelect->selFlags & SF_MultiValue)==0
){
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
}
}else{
/* Assign a bit from the bitmask to every term in the FROM clause.
**
** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
**
** The rule of the previous sentence ensures that if X is the bitmask for
** a table T, then X-1 is the bitmask for all other tables to the left of T.
** Knowing the bitmask for all tables to the left of a left join is
** important. Ticket #3015.
**
** Note that bitmasks are created for all pTabList->nSrc tables in
** pTabList, not just the first nTabList tables. nTabList is normally
** equal to pTabList->nSrc but might be shortened to 1 if the
** WHERE_OR_SUBCLAUSE flag is set.
*/
ii = 0;
do{
createMask(pMaskSet, pTabList->a[ii].iCursor);
sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
}while( (++ii)<pTabList->nSrc );
#ifdef SQLITE_DEBUG
{
Bitmask mx = 0;
for(ii=0; ii<pTabList->nSrc; ii++){
Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor);
assert( m>=mx );
mx = m;
}
}
#endif
sqlite3VdbeAddOp3(v, OP_Column, pLevel->iIdxCur, j, r1+j);
}
pParse->nMem += n+1;
op = pLevel->op==OP_Prev ? OP_SeekLT : OP_SeekGT;
addrSeek = sqlite3VdbeAddOp4Int(v, op, pLevel->iIdxCur, 0, r1, n);
VdbeCoverageIf(v, op==OP_SeekLT);
VdbeCoverageIf(v, op==OP_SeekGT);
sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
}
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){
/* If the EXISTS-to-JOIN optimization was applied, then the EXISTS
** loop(s) will be the inner-most loops of the join. There might be
** multiple EXISTS loops, but they will all be nested, and the join
** order will not have been changed by the query planner. If the
** inner-most EXISTS loop sees a single successful row, it should
** break out of *all* EXISTS loops. But only the inner-most of the
** nested EXISTS loops should do this breakout. */
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
while( nOuter<i ){
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
nOuter++;
}
testcase( nOuter>0 );
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
VdbeComment((v, "EXISTS break"));
}
/* The common case: Advance to the next row */
if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont);
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
sqlite3VdbeChangeP5(v, pLevel->p5);
VdbeCoverage(v);
VdbeCoverageIf(v, pLevel->op==OP_Next);
VdbeCoverageIf(v, pLevel->op==OP_Prev);
VdbeCoverageIf(v, pLevel->op==OP_VNext);
if( pLevel->regBignull ){
sqlite3VdbeResolveLabel(v, pLevel->addrBignull);
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1);
VdbeCoverage(v);
}
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
#endif
}else if( pLevel->addrCont ){
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
|| pParse->db->mallocFailed );
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
int bEarlyOut =
(pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
&& (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
if( pLevel->iLeftJoin ){
/* For LEFT JOIN queries, cursor pIn->iCur may not have been
** opened yet. This occurs for WHERE clauses such as
** "a = ? AND b IN (...)", where the index is on (a, b). If
** the RHS of the (a=?) is NULL, then the "b IN (...)" may
** never have been coded, but the body of the loop run to
** return the null-row. So, if the cursor is not open yet,
** jump over the OP_Next or OP_Prev instruction about to
** be coded. */
sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur,
sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut);
VdbeCoverage(v);
}
if( bEarlyOut ){
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
VdbeCoverage(v);
/* Retarget the OP_IsNull against the left operand of IN so
** it jumps past the OP_IfNoHope. This is because the
** OP_IsNull also bypasses the OP_Affinity opcode that is
** required by OP_IfNoHope. */
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
}
}
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
VdbeCoverage(v);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
}
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
}
sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
if( pLevel->pRJ ){
sqlite3VdbeAddOp3(v, OP_Return, pLevel->pRJ->regReturn, 0, 1);
VdbeCoverage(v);
}
if( pLevel->addrSkip ){
sqlite3VdbeGoto(v, pLevel->addrSkip);
VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
sqlite3VdbeJumpHere(v, pLevel->addrSkip);
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
}
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
if( pLevel->addrLikeRep ){
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1),
pLevel->addrLikeRep);
VdbeCoverage(v);
}
#endif
if( pLevel->iLeftJoin ){
int ws = pLoop->wsFlags;
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
if( (ws & WHERE_IDX_ONLY)==0 ){
SrcItem *pSrc = &pTabList->a[pLevel->iFrom];
assert( pLevel->iTabCur==pSrc->iCursor );
if( pSrc->fg.viaCoroutine ){
int m, n;
assert( pSrc->fg.isSubquery );
n = pSrc->u4.pSubq->regResult;
assert( pSrc->pSTab!=0 );
m = pSrc->pSTab->nCol;
sqlite3VdbeAddOp3(v, OP_Null, 0, n, n+m-1);
}
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
continue;
}
/* For a co-routine, change all OP_Column references to the table of
** the co-routine into OP_Copy of result contained in a register.
** OP_Rowid becomes OP_Null.
*/
if( pTabItem->fg.viaCoroutine ){
testcase( pParse->db->mallocFailed );
assert( pTabItem->fg.isSubquery );
assert( pTabItem->u4.pSubq->regResult>=0 );
translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
pTabItem->u4.pSubq->regResult, 0);
continue;
}
/* If this scan uses an index, make VDBE code substitutions to read data
** from the index instead of from the table where possible. In some cases
** this optimization prevents the table from ever being read, which can
** yield a significant performance boost.
**
** Calls to the code generator in between sqlite3WhereBegin and
** sqlite3WhereEnd will have created code that references the table
** directly. This loop scans all that code looking for opcodes
** that reference the table and converts them into opcodes that
** reference the index.
*/
if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
pIdx = pLoop->u.btree.pIndex;
}else if( pLoop->wsFlags & WHERE_MULTI_OR ){
pIdx = pLevel->u.pCoveringIdx;
}
if( pIdx
&& !db->mallocFailed
){
if( pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable) ){
last = iEnd;
}else{
last = pWInfo->iEndWhere;
}
if( pIdx->bHasExpr ){
IndexedExpr *p = pParse->pIdxEpr;
while( p ){
if( p->iIdxCur==pLevel->iIdxCur ){
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x200 ){
sqlite3DebugPrintf("Disable pParse->pIdxEpr term {%d,%d}\n",
p->iIdxCur, p->iIdxCol);
if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(p->pExpr);
}
#endif
p->iDataCur = -1;
p->iIdxCur = -1;
}
p = p->pIENext;
}
}
k = pLevel->addrBody + 1;
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ){
printf("TRANSLATE cursor %d->%d in opcode range %d..%d\n",
pLevel->iTabCur, pLevel->iIdxCur, k, last-1);
}
/* Proof that the "+1" on the k value above is safe */
pOp = sqlite3VdbeGetOp(v, k - 1);
assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur );
assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
pOp = sqlite3VdbeGetOp(v, k);
pLastOp = pOp + (last - k);
assert( pOp<=pLastOp );
do{
if( pOp->p1!=pLevel->iTabCur ){
/* no-op */
}else if( pOp->opcode==OP_Column
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|| pOp->opcode==OP_Offset
#endif
){
int x = pOp->p2;
assert( pIdx->pTable==pTab );
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
if( pOp->opcode==OP_Offset ){
/* Do not need to translate the column number */
}else
#endif
if( !HasRowid(pTab) ){
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
x = pPk->aiColumn[x];
assert( x>=0 );
}else{
testcase( x!=sqlite3StorageColumnToTable(pTab,x) );
x = sqlite3StorageColumnToTable(pTab,x);
}
x = sqlite3TableColumnToIndex(pIdx, x);
if( x>=0 ){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
}else if( pLoop->wsFlags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
if( pLoop->wsFlags & WHERE_IDX_ONLY ){
/* An error. pLoop is supposed to be a covering index loop,
** and yet the VM code refers to a column of the table that
** is not part of the index. */
sqlite3ErrorMsg(pParse, "internal query planner error");
pParse->rc = SQLITE_INTERNAL;
}else{
/* The WHERE_EXPRIDX flag is set by the planner when it is likely
** that pLoop is a covering index loop, but it is not possible
** to be 100% sure. In this case, any OP_Explain opcode
** corresponding to this loop describes the index as a "COVERING
** INDEX". But, pOp proves that pLoop is not actually a covering
** index loop. So clear the WHERE_EXPRIDX flag and rewrite the
** text that accompanies the OP_Explain opcode, if any. */
pLoop->wsFlags &= ~WHERE_EXPRIDX;
sqlite3WhereAddExplainText(pParse,
pLevel->addrBody-1,
pTabList,
pLevel,
pWInfo->wctrlFlags
** at the top of this file.
*/
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
if( p->pWin
&& p->pPrior==0
&& ALWAYS((p->selFlags & SF_WinRewrite)==0)
&& ALWAYS(!IN_RENAME_OBJECT)
){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3 *db = pParse->db;
Select *pSub = 0; /* The subquery */
SrcList *pSrc = p->pSrc;
Expr *pWhere = p->pWhere;
ExprList *pGroupBy = p->pGroupBy;
Expr *pHaving = p->pHaving;
ExprList *pSort = 0;
ExprList *pSublist = 0; /* Expression list for sub-query */
Window *pMWin = p->pWin; /* Main window object */
Window *pWin; /* Window object iterator */
Table *pTab;
Walker w;
u32 selFlags = p->selFlags;
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ){
return sqlite3ErrorToParser(db, SQLITE_NOMEM);
}
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w, p);
if( (p->selFlags & SF_Aggregate)==0 ){
w.xExprCallback = disallowAggregatesInOrderByCb;
w.xSelectCallback = 0;
sqlite3WalkExprList(&w, p->pOrderBy);
}
p->pSrc = 0;
p->pWhere = 0;
p->pGroupBy = 0;
p->pHaving = 0;
p->selFlags &= ~(u32)SF_Aggregate;
p->selFlags |= SF_WinRewrite;
/* Create the ORDER BY clause for the sub-select. This is the concatenation
** of the window PARTITION and ORDER BY clauses. Then, if this makes it
** redundant, remove the ORDER BY from the parent SELECT. */
pSort = exprListAppendList(pParse, 0, pMWin->pPartition, 1);
pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1);
if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){
int nSave = pSort->nExpr;
pSort->nExpr = p->pOrderBy->nExpr;
if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){
sqlite3ExprListDelete(db, p->pOrderBy);
p->pOrderBy = 0;
}
pSort->nExpr = nSave;
}
/* Assign a cursor number for the ephemeral table used to buffer rows.
** The OpenEphemeral instruction is coded later, after it is known how
** many columns the table will have. */
pMWin->iEphCsr = pParse->nTab++;
pParse->nTab += 3;
selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, pTab, &pSublist);
selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, pTab, &pSublist);
pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0);
/* Append the PARTITION BY and ORDER BY expressions to the to the
** sub-select expression list. They are required to figure out where
** boundaries for partitions and sets of peer rows lie. */
pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition, 0);
pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy, 0);
/* Append the arguments passed to each window function to the
** sub-select expression list. Also allocate two registers for each
** window function - one for the accumulator, another for interim
** results. */
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
ExprList *pArgs;
assert( ExprUseXList(pWin->pOwner) );
assert( pWin->pWFunc!=0 );
pArgs = pWin->pOwner->x.pList;
if( pWin->pWFunc->funcFlags & SQLITE_SUBTYPE ){
selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pWin->bExprArgs = 1;
}else{
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pSublist = exprListAppendList(pParse, pSublist, pArgs, 0);
}
if( pWin->pFilter ){
Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0);
pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter);
}
pWin->regAccum = ++pParse->nMem;
pWin->regResult = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
}
/* If there is no ORDER BY or PARTITION BY clause, and the window
** function accepts zero arguments, and there are no other columns
** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible
** that pSublist is still NULL here. Add a constant expression here to
** keep everything legal in this case.
*/
if( pSublist==0 ){
pSublist = sqlite3ExprListAppend(pParse, 0,
sqlite3Expr(db, TK_INTEGER, "0")
);
}
pSub = sqlite3SelectNew(
pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
);
TREETRACE(0x40,pParse,pSub,
("New window-function subquery in FROM clause of (%u/%p)\n",
p->selId, p));
p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
/*
** Possibly link window pWin into the list at pSel->pWin (window functions
** to be processed as part of SELECT statement pSel). The window is linked
** in if either (a) there are no other windows already linked to this
** SELECT, or (b) the windows already linked use a compatible window frame.
*/
SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin){
if( pSel ){
if( 0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0) ){
pWin->pNextWin = pSel->pWin;
if( pSel->pWin ){
pSel->pWin->ppThis = &pWin->pNextWin;
}
pSel->pWin = pWin;
pWin->ppThis = &pSel->pWin;
}else{
if( sqlite3ExprListCompare(pWin->pPartition, pSel->pWin->pPartition,-1) ){
pSel->selFlags |= SF_MultiPart;
}
}
}
}
/*
** Return 0 if the two window objects are identical, 1 if they are
** different, or 2 if it cannot be determined if the objects are identical
** or not. Identical window objects can be processed in a single scan.
*/
SQLITE_PRIVATE int sqlite3WindowCompare(
const Parse *pParse,
const Window *p1,
const Window *p2,
int bFilter
){
int res;
if( NEVER(p1==0) || NEVER(p2==0) ) return 1;
if( p1->eFrmType!=p2->eFrmType ) return 1;
if( p1->eStart!=p2->eStart ) return 1;
if( p1->eEnd!=p2->eEnd ) return 1;
if( p1->eExclude!=p2->eExclude ) return 1;
if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1;
if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1;
if( (res = sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1)) ){
return res;
}
if( (res = sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1)) ){
return res;
}
if( bFilter ){
if( (res = sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1)) ){
return res;
}
}
return 0;
}
/*
** This is called by code in select.c before it calls sqlite3WhereBegin()
** to begin iterating through the sub-query results. It is used to allocate
** and initialize registers and cursors used by sqlite3WindowCodeStep().
*/
SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){
Window *pWin;
int nEphExpr;
Window *pMWin;
Vdbe *v;
assert( pSelect->pSrc->a[0].fg.isSubquery );
nEphExpr = pSelect->pSrc->a[0].u4.pSubq->pSelect->pEList->nExpr;
pMWin = pSelect->pWin;
v = sqlite3GetVdbe(pParse);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr);
sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr);
sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr);
/* Allocate registers to use for PARTITION BY values, if any. Initialize
** said registers to NULL. */
if( pMWin->pPartition ){
int nExpr = pMWin->pPartition->nExpr;
pMWin->regPart = pParse->nMem+1;
pParse->nMem += nExpr;
sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nExpr-1);
}
pMWin->regOne = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regOne);
if( pMWin->eExclude ){
pMWin->regStartRowid = ++pParse->nMem;
pMWin->regEndRowid = ++pParse->nMem;
pMWin->csrApp = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid);
sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid);
sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->csrApp, pMWin->iEphCsr);
return;
}
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
FuncDef *p = pWin->pWFunc;
if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){
/* The inline versions of min() and max() require a single ephemeral
** table and 3 registers. The registers are used as follows:
**
** regApp+0: slot to copy min()/max() argument to for MakeRecord
** regApp+1: integer value used to ensure keys are unique
** regApp+2: output of MakeRecord
*/
ExprList *pList;
KeyInfo *pKeyInfo;
assert( ExprUseXList(pWin->pOwner) );
pList = pWin->pOwner->x.pList;
pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
pWin->csrApp = pParse->nTab++;
pWin->regApp = pParse->nMem+1;
pParse->nMem += 3;
if( pKeyInfo && pWin->pWFunc->zName[1]=='i' ){
assert( pKeyInfo->aSortFlags[0]==0 );
pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC;
/*
** Return the number of arguments passed to the window-function associated
** with the object passed as the only argument to this function.
*/
static int windowArgCount(Window *pWin){
const ExprList *pList;
assert( ExprUseXList(pWin->pOwner) );
pList = pWin->pOwner->x.pList;
return (pList ? pList->nExpr : 0);
}
typedef struct WindowCodeArg WindowCodeArg;
typedef struct WindowCsrAndReg WindowCsrAndReg;
/*
** See comments above struct WindowCodeArg.
*/
struct WindowCsrAndReg {
int csr; /* Cursor number */
int reg; /* First in array of peer values */
};
/*
** A single instance of this structure is allocated on the stack by
** sqlite3WindowCodeStep() and a pointer to it passed to the various helper
** routines. This is to reduce the number of arguments required by each
** helper function.
**
** regArg:
** Each window function requires an accumulator register (just as an
** ordinary aggregate function does). This variable is set to the first
** in an array of accumulator registers - one for each window function
** in the WindowCodeArg.pMWin list.
**
** eDelete:
** The window functions implementation sometimes caches the input rows
** that it processes in a temporary table. If it is not zero, this
** variable indicates when rows may be removed from the temp table (in
** order to reduce memory requirements - it would always be safe just
** to leave them there). Possible values for eDelete are:
**
** WINDOW_RETURN_ROW:
** An input row can be discarded after it is returned to the caller.
**
** WINDOW_AGGINVERSE:
** An input row can be discarded after the window functions xInverse()
** callbacks have been invoked in it.
**
** WINDOW_AGGSTEP:
** An input row can be discarded after the window functions xStep()
** callbacks have been invoked in it.
**
** start,current,end
** Consider a window-frame similar to the following:
**
** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING)
**
** The windows functions implementation caches the input rows in a temp
** table, sorted by "a, b" (it actually populates the cache lazily, and
** aggressively removes rows once they are no longer required, but that's
** a mere detail). It keeps three cursors open on the temp table. One
** (current) that points to the next row to return to the query engine
** once its window function values have been calculated. Another (end)
** points to the next row to call the xStep() method of each window function
** on (so that it is 2 groups ahead of current). And a third (start) that
** points to the next row to call the xInverse() method of each window
** function on.
**
** Each cursor (start, current and end) consists of a VDBE cursor
** (WindowCsrAndReg.csr) and an array of registers (starting at
** WindowCodeArg.reg) that always contains a copy of the peer values
** read from the corresponding cursor.
**
** Depending on the window-frame in question, all three cursors may not
** be required. In this case both WindowCodeArg.csr and reg are set to
** 0.
*/
struct WindowCodeArg {
Parse *pParse; /* Parse context */
Window *pMWin; /* First in list of functions being processed */
Vdbe *pVdbe; /* VDBE object */
int addrGosub; /* OP_Gosub to this address to return one row */
int regGosub; /* Register used with OP_Gosub(addrGosub) */
int regArg; /* First in array of accumulator registers */
int eDelete; /* See above */
int regRowid;
WindowCsrAndReg start;
WindowCsrAndReg current;
WindowCsrAndReg end;
};
/*
** Generate VM code to read the window frames peer values from cursor csr into
** an array of registers starting at reg.
*/
static void windowReadPeerValues(
WindowCodeArg *p,
int csr,
int reg
){
Window *pMWin = p->pMWin;
ExprList *pOrderBy = pMWin->pOrderBy;
if( pOrderBy ){
Vdbe *v = sqlite3GetVdbe(p->pParse);
ExprList *pPart = pMWin->pPartition;
int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0);
int i;
for(i=0; i<pOrderBy->nExpr; i++){
sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i);
}
}
}
/*
** Generate VM code to invoke either xStep() (if bInverse is 0) or
** xInverse (if bInverse is non-zero) for each window function in the
** linked list starting at pMWin. Or, for built-in window functions
** that do not use the standard function API, generate the required
** inline VM code.
**
** If argument csr is greater than or equal to 0, then argument reg is
** the first register in an array of registers guaranteed to be large
** enough to hold the array of arguments for each function. In this case
** the arguments are extracted from the current row of csr into the
** array of registers before invoking OP_AggStep or OP_AggInverse
**
** Or, if csr is less than zero, then the array of registers at reg is
** already populated with all columns from the current row of the sub-query.
**
** If argument regPartSize is non-zero, then it is a register containing the
** number of rows in the current partition.
*/
static void windowAggStep(
WindowCodeArg *p,
Window *pMWin, /* Linked list of window functions */
int csr, /* Read arguments from this cursor */
int bInverse, /* True to invoke xInverse instead of xStep */
int reg /* Array of registers */
){
Parse *pParse = p->pParse;
Vdbe *v = sqlite3GetVdbe(pParse);
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
FuncDef *pFunc = pWin->pWFunc;
int regArg;
int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin);
int i;
int addrIf = 0;
assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
/* All OVER clauses in the same window function aggregate step must
** be the same. */
assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)!=1 );
for(i=0; i<nArg; i++){
if( i!=1 || pFunc->zName!=nth_valueName ){
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
}else{
sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+i, reg+i);
}
}
regArg = reg;
if( pWin->pFilter ){
int regTmp;
assert( ExprUseXList(pWin->pOwner) );
assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
regTmp = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regTmp);
}
if( pMWin->regStartRowid==0
&& (pFunc->funcFlags & SQLITE_FUNC_MINMAX)
&& (pWin->eStart!=TK_UNBOUNDED)
){
int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg);
VdbeCoverage(v);
if( bInverse==0 ){
sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1, 1);
sqlite3VdbeAddOp2(v, OP_SCopy, regArg, pWin->regApp);
sqlite3VdbeAddOp3(v, OP_MakeRecord, pWin->regApp, 2, pWin->regApp+2);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pWin->csrApp, pWin->regApp+2);
}else{
sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1);
VdbeCoverageNeverTaken(v);
sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp);
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
}
sqlite3VdbeJumpHere(v, addrIsNull);
}else if( pWin->regApp ){
assert( pWin->pFilter==0 );
/*
** regOld and regNew are each the first register in an array of size
** pOrderBy->nExpr. This function generates code to compare the two
** arrays of registers using the collation sequences and other comparison
** parameters specified by pOrderBy.
**
** If the two arrays are not equal, the contents of regNew is copied to
** regOld and control falls through. Otherwise, if the contents of the arrays
** are equal, an OP_Goto is executed. The address of the OP_Goto is returned.
*/
static void windowIfNewPeer(
Parse *pParse,
ExprList *pOrderBy,
int regNew, /* First in array of new values */
int regOld, /* First in array of old values */
int addr /* Jump here */
){
Vdbe *v = sqlite3GetVdbe(pParse);
if( pOrderBy ){
int nVal = pOrderBy->nExpr;
KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0);
sqlite3VdbeAddOp3(v, OP_Compare, regOld, regNew, nVal);
sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
sqlite3VdbeAddOp3(v, OP_Jump,
sqlite3VdbeCurrentAddr(v)+1, addr, sqlite3VdbeCurrentAddr(v)+1
);
VdbeCoverageEqNe(v);
sqlite3VdbeAddOp3(v, OP_Copy, regNew, regOld, nVal-1);
}else{
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
}
}
/*
** This function is called as part of generating VM programs for RANGE
** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for
** the ORDER BY term in the window, and that argument op is OP_Ge, it generates
** code equivalent to:
**
** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl;
**
** The value of parameter op may also be OP_Gt or OP_Le. In these cases the
** operator in the above pseudo-code is replaced with ">" or "<=", respectively.
**
** If the sort-order for the ORDER BY term in the window is DESC, then the
** comparison is reversed. Instead of adding regVal to csr1.peerVal, it is
** subtracted. And the comparison operator is inverted to - ">=" becomes "<=",
** ">" becomes "<", and so on. So, with DESC sort order, if the argument op
** is OP_Ge, the generated code is equivalent to:
**
** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
** a numeric type (real or integer), then the result of the addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
WindowCodeArg *p,
int op, /* OP_Ge, OP_Gt, or OP_Le */
int csr1, /* Cursor number for cursor 1 */
int regVal, /* Register containing non-negative number */
int csr2, /* Cursor number for cursor 2 */
int lbl /* Jump destination if condition is true */
){
Parse *pParse = p->pParse;
Vdbe *v = sqlite3GetVdbe(pParse);
ExprList *pOrderBy = p->pMWin->pOrderBy; /* ORDER BY clause for window */
int reg1 = sqlite3GetTempReg(pParse); /* Reg. for csr1.peerVal+regVal */
int reg2 = sqlite3GetTempReg(pParse); /* Reg. for csr2.peerVal */
int regString = ++pParse->nMem; /* Reg. for constant value '' */
int arith = OP_Add; /* OP_Add or OP_Subtract */
int addrGe; /* Jump destination */
int addrDone = sqlite3VdbeMakeLabel(pParse); /* Address past OP_Ge */
CollSeq *pColl;
/* Read the peer-value from each cursor into a register */
windowReadPeerValues(p, csr1, reg1);
windowReadPeerValues(p, csr2, reg2);
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( pOrderBy && pOrderBy->nExpr==1 );
if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_DESC ){
switch( op ){
case OP_Ge: op = OP_Le; break;
case OP_Gt: op = OP_Lt; break;
default: assert( op==OP_Le ); op = OP_Ge; break;
}
arith = OP_Subtract;
}
VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
reg1, (arith==OP_Add ? "+" : "-"), regVal,
((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
));
/* If the BIGNULL flag is set for the ORDER BY, then it is required to
** consider NULL values to be larger than all other values, instead of
** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
** (and adding that capability causes a performance regression), so
** instead if the BIGNULL flag is set then cases where either reg1 or
** reg2 are NULL are handled separately in the following block. The code
** generated is equivalent to:
**
** if( reg1 IS NULL ){
** if( op==OP_Ge ) goto lbl;
** if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl;
** if( op==OP_Le && reg2 IS NULL ) goto lbl;
** }else if( reg2 IS NULL ){
** if( op==OP_Le ) goto lbl;
** }
**
** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is
** not taken, control jumps over the comparison operator coded below this
** block. */
if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_BIGNULL ){
/* This block runs if reg1 contains a NULL. */
int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v);
switch( op ){
case OP_Ge:
sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl);
break;
case OP_Gt:
sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl);
VdbeCoverage(v);
break;
case OP_Le:
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl);
VdbeCoverage(v);
break;
default: assert( op==OP_Lt ); /* no-op */ break;
}
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
/* This block runs if reg1 is not NULL, but reg2 is. */
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_IsNull, reg2,
(op==OP_Gt || op==OP_Ge) ? addrDone : lbl);
VdbeCoverage(v);
}
/* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
** This block adds (or subtracts for DESC) the numeric value in regVal
** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
** then leave reg1 as it is. In pseudo-code, this is implemented as:
**
** if( reg1>='' ) goto addrGe;
** reg1 = reg1 +/- regVal
** addrGe:
**
** Since all strings and blobs are greater-than-or-equal-to an empty string,
** the add/subtract is skipped for these, as required. If reg1 is a NULL,
** then the arithmetic is performed, but since adding or subtracting from
** NULL is always NULL anyway, this case is handled as required too. */
sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
VdbeCoverage(v);
if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
sqlite3VdbeJumpHere(v, addrGe);
/* Compare registers reg2 and reg1, taking the jump if required. Note that
** control skips over this test if the BIGNULL flag is set and either
** reg1 or reg2 contain a NULL value. */
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
sqlite3VdbeResolveLabel(v, addrDone);
assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt);
testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le);
testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt);
sqlite3ReleaseTempReg(pParse, reg1);
sqlite3ReleaseTempReg(pParse, reg2);
VdbeModuleComment((v, "CodeRangeTest: end"));
}
/*
** Helper function for sqlite3WindowCodeStep(). Each call to this function
** generates VM code for a single RETURN_ROW, AGGSTEP or AGGINVERSE
** operation. Refer to the header comment for sqlite3WindowCodeStep() for
** details.
*/
static int windowCodeOp(
WindowCodeArg *p, /* Context object */
int op, /* WINDOW_RETURN_ROW, AGGSTEP or AGGINVERSE */
int regCountdown, /* Register for OP_IfPos countdown */
int jumpOnEof /* Jump here if stepped cursor reaches EOF */
){
int csr, reg;
Parse *pParse = p->pParse;
Window *pMWin = p->pMWin;
int ret = 0;
Vdbe *v = p->pVdbe;
int addrContinue = 0;
int bPeer = (pMWin->eFrmType!=TK_ROWS);
int lblDone = sqlite3VdbeMakeLabel(pParse);
int addrNextRange = 0;
/* Special case - WINDOW_AGGINVERSE is always a no-op if the frame
** starts with UNBOUNDED PRECEDING. */
if( op==WINDOW_AGGINVERSE && pMWin->eStart==TK_UNBOUNDED ){
assert( regCountdown==0 && jumpOnEof==0 );
return 0;
}
if( regCountdown>0 ){
if( pMWin->eFrmType==TK_RANGE ){
addrNextRange = sqlite3VdbeCurrentAddr(v);
assert( op==WINDOW_AGGINVERSE || op==WINDOW_AGGSTEP );
if( op==WINDOW_AGGINVERSE ){
if( pMWin->eStart==TK_FOLLOWING ){
windowCodeRangeTest(
p, OP_Le, p->current.csr, regCountdown, p->start.csr, lblDone
);
}else{
windowCodeRangeTest(
p, OP_Ge, p->start.csr, regCountdown, p->current.csr, lblDone
);
}
}else{
windowCodeRangeTest(
p, OP_Gt, p->end.csr, regCountdown, p->current.csr, lblDone
);
}
}else{
sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, lblDone, 1);
VdbeCoverage(v);
}
}
if( op==WINDOW_RETURN_ROW && pMWin->regStartRowid==0 ){
windowAggFinal(p, 0);
}
addrContinue = sqlite3VdbeCurrentAddr(v);
/* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the
** start cursor does not advance past the end cursor within the
** temporary table. It otherwise might, if (a>b). Also ensure that,
** if the input cursor is still finding new rows, that the end
** cursor does not go past it to EOF. */
if( pMWin->eStart==pMWin->eEnd && regCountdown
&& pMWin->eFrmType==TK_RANGE
){
int regRowid1 = sqlite3GetTempReg(pParse);
int regRowid2 = sqlite3GetTempReg(pParse);
if( op==WINDOW_AGGINVERSE ){
sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
VdbeCoverage(v);
}else if( p->regRowid ){
sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1);
sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1);
VdbeCoverageNeverNull(v);
}
sqlite3ReleaseTempReg(pParse, regRowid1);
sqlite3ReleaseTempReg(pParse, regRowid2);
assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
}
switch( op ){
case WINDOW_RETURN_ROW:
csr = p->current.csr;
reg = p->current.reg;
windowReturnOneRow(p);
break;
case WINDOW_AGGINVERSE:
csr = p->start.csr;
reg = p->start.reg;
if( pMWin->regStartRowid ){
assert( pMWin->regEndRowid );
sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regStartRowid, 1);
}else{
windowAggStep(p, pMWin, csr, 1, p->regArg);
}
break;
default:
assert( op==WINDOW_AGGSTEP );
csr = p->end.csr;
reg = p->end.reg;
if( pMWin->regStartRowid ){
assert( pMWin->regEndRowid );
sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regEndRowid, 1);
}else{
windowAggStep(p, pMWin, csr, 0, p->regArg);
}
break;
}
if( op==p->eDelete ){
sqlite3VdbeAddOp1(v, OP_Delete, csr);
sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
}
if( jumpOnEof ){
sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
ret = sqlite3VdbeAddOp0(v, OP_Goto);
/*
** Return a copy of the linked list of Window objects passed as the
** second argument.
*/
SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p){
Window *pWin;
Window *pRet = 0;
Window **pp = &pRet;
for(pWin=p; pWin; pWin=pWin->pNextWin){
*pp = sqlite3WindowDup(db, 0, pWin);
if( *pp==0 ) break;
pp = &((*pp)->pNextWin);
}
return pRet;
}
/*
** Return true if it can be determined at compile time that expression
** pExpr evaluates to a value that, when cast to an integer, is greater
** than zero. False otherwise.
**
** If an OOM error occurs, this function sets the Parse.db.mallocFailed
** flag and returns zero.
*/
static int windowExprGtZero(Parse *pParse, Expr *pExpr){
int ret = 0;
sqlite3 *db = pParse->db;
sqlite3_value *pVal = 0;
sqlite3ValueFromExpr(db, pExpr, db->enc, SQLITE_AFF_NUMERIC, &pVal);
if( pVal && sqlite3_value_int(pVal)>0 ){
ret = 1;
}
sqlite3ValueFree(pVal);
return ret;
}
/*
** sqlite3WhereBegin() has already been called for the SELECT statement
** passed as the second argument when this function is invoked. It generates
** code to populate the Window.regResult register for each window function
** and invoke the sub-routine at instruction addrGosub once for each row.
** sqlite3WhereEnd() is always called before returning.
**
** This function handles several different types of window frames, which
** require slightly different processing. The following pseudo code is
** used to implement window frames of the form:
**
** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
**
** Other window frame types use variants of the following:
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
**
** if( first row of partition ){
** // Rewind three cursors, all open on the eph table.
** Rewind(csrEnd);
** Rewind(csrStart);
** Rewind(csrCurrent);
**
** regEnd = <expr2> // FOLLOWING expression
** regStart = <expr1> // PRECEDING expression
** }else{
** // First time this branch is taken, the eph table contains two
** // rows. The first row in the partition, which all three cursors
** // currently point to, and the following row.
** AGGSTEP
** if( (regEnd--)<=0 ){
** RETURN_ROW
** if( (regStart--)<=0 ){
** AGGINVERSE
** }
** }
** }
** }
** flush:
** AGGSTEP
** while( 1 ){
** RETURN ROW
** if( csrCurrent is EOF ) break;
** if( (regStart--)<=0 ){
** AggInverse(csrStart)
** Next(csrStart)
** }
** }
**
** The pseudo-code above uses the following shorthand:
**
** AGGSTEP: invoke the aggregate xStep() function for each window function
** with arguments read from the current row of cursor csrEnd, then
** step cursor csrEnd forward one row (i.e. sqlite3BtreeNext()).
**
** RETURN_ROW: return a row to the caller based on the contents of the
** current row of csrCurrent and the current state of all
** aggregates. Then step cursor csrCurrent forward one row.
**
** AGGINVERSE: invoke the aggregate xInverse() function for each window
** functions with arguments read from the current row of cursor
** csrStart. Then step csrStart forward one row.
**
** There are two other ROWS window frames that are handled significantly
** differently from the above - "BETWEEN <expr> PRECEDING AND <expr> PRECEDING"
** and "BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING". These are special
** cases because they change the order in which the three cursors (csrStart,
** csrCurrent and csrEnd) iterate through the ephemeral table. Cases that
** use UNBOUNDED or CURRENT ROW are much simpler variations on one of these
** three.
**
** ROWS BETWEEN <expr1> PRECEDING AND <expr2> PRECEDING
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
** if( first row of partition ){
** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
** regEnd = <expr2>
** regStart = <expr1>
** }else{
** if( (regEnd--)<=0 ){
** AGGSTEP
** }
** RETURN_ROW
** if( (regStart--)<=0 ){
** AGGINVERSE
** }
** }
** }
** flush:
** if( (regEnd--)<=0 ){
** AGGSTEP
** }
** RETURN_ROW
**
**
** ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
** if( first row of partition ){
** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
** regEnd = <expr2>
** regStart = regEnd - <expr1>
** }else{
** AGGSTEP
** if( (regEnd--)<=0 ){
** RETURN_ROW
** }
** if( (regStart--)<=0 ){
** AGGINVERSE
** }
** }
** }
** flush:
** AGGSTEP
** while( 1 ){
** if( (regEnd--)<=0 ){
** RETURN_ROW
** if( eof ) break;
** }
** if( (regStart--)<=0 ){
** AGGINVERSE
** if( eof ) break
** }
** RETURN_ROW
** }
** while( !eof csrCurrent ){
** RETURN_ROW
** }
**
** Also requiring special handling are the cases:
**
** ROWS BETWEEN <expr1> PRECEDING AND <expr2> PRECEDING
** ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
**
** when (expr1 < expr2). This is detected at runtime, not by this function.
** To handle this case, the pseudo-code programs depicted above are modified
** slightly to be:
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
** if( first row of partition ){
** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
** regEnd = <expr2>
** regStart = <expr1>
** if( regEnd < regStart ){
** RETURN_ROW
** delete eph table contents
** continue
** }
** ...
**
** The new "continue" statement in the above jumps to the next iteration
** of the outer loop - the one started by sqlite3WhereBegin().
**
** The various GROUPS cases are implemented using the same patterns as
** ROWS. The VM code is modified slightly so that:
**
** 1. The else branch in the main loop is only taken if the row just
** added to the ephemeral table is the start of a new group. In
** other words, it becomes:
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
** if( first row of partition ){
** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
** regEnd = <expr2>
** regStart = <expr1>
** }else if( new group ){
** ...
** }
** }
**
** 2. Instead of processing a single row, each RETURN_ROW, AGGSTEP or
** AGGINVERSE step processes the current row of the relevant cursor and
** all subsequent rows belonging to the same group.
**
** RANGE window frames are a little different again. As for GROUPS, the
** main loop runs once per group only. And RETURN_ROW, AGGSTEP and AGGINVERSE
** deal in groups instead of rows. As for ROWS and GROUPS, there are three
** basic cases:
**
** RANGE BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
** if( first row of partition ){
** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
** regEnd = <expr2>
** regStart = <expr1>
** }else{
** AGGSTEP
** while( (csrCurrent.key + regEnd) < csrEnd.key ){
** RETURN_ROW
** while( csrStart.key + regStart) < csrCurrent.key ){
** AGGINVERSE
** }
** }
** }
** }
** flush:
** AGGSTEP
** while( 1 ){
** RETURN ROW
** if( csrCurrent is EOF ) break;
** while( csrStart.key + regStart) < csrCurrent.key ){
** AGGINVERSE
** }
** }
** }
**
** In the above notation, "csr.key" means the current value of the ORDER BY
** expression (there is only ever 1 for a RANGE that uses an <expr> FOLLOWING
** or <expr PRECEDING) read from cursor csr.
**
** RANGE BETWEEN <expr1> PRECEDING AND <expr2> PRECEDING
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
** if( first row of partition ){
** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
** regEnd = <expr2>
** regStart = <expr1>
** }else{
** while( (csrEnd.key + regEnd) <= csrCurrent.key ){
** AGGSTEP
** }
** while( (csrStart.key + regStart) < csrCurrent.key ){
** AGGINVERSE
** }
** RETURN_ROW
** }
** }
** flush:
** while( (csrEnd.key + regEnd) <= csrCurrent.key ){
** AGGSTEP
** }
** while( (csrStart.key + regStart) < csrCurrent.key ){
** AGGINVERSE
** }
** RETURN_ROW
**
** RANGE BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING
**
** ... loop started by sqlite3WhereBegin() ...
** if( new partition ){
** Gosub flush
** }
** Insert new row into eph table.
** if( first row of partition ){
** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent)
** regEnd = <expr2>
** regStart = <expr1>
** }else{
** AGGSTEP
** while( (csrCurrent.key + regEnd) < csrEnd.key ){
** while( (csrCurrent.key + regStart) > csrStart.key ){
** AGGINVERSE
** }
** RETURN_ROW
** }
** }
** }
** flush:
** AGGSTEP
** while( 1 ){
** while( (csrCurrent.key + regStart) > csrStart.key ){
** AGGINVERSE
** if( eof ) break "while( 1 )" loop.
** }
** RETURN_ROW
s.pVdbe = v;
s.regGosub = regGosub;
s.addrGosub = addrGosub;
s.current.csr = pMWin->iEphCsr;
csrWrite = s.current.csr+1;
s.start.csr = s.current.csr+2;
s.end.csr = s.current.csr+3;
/* Figure out when rows may be deleted from the ephemeral table. There
** are four options - they may never be deleted (eDelete==0), they may
** be deleted as soon as they are no longer part of the window frame
** (eDelete==WINDOW_AGGINVERSE), they may be deleted as after the row
** has been returned to the caller (WINDOW_RETURN_ROW), or they may
** be deleted after they enter the frame (WINDOW_AGGSTEP). */
switch( pMWin->eStart ){
case TK_FOLLOWING:
if( pMWin->eFrmType!=TK_RANGE
&& windowExprGtZero(pParse, pMWin->pStart)
){
s.eDelete = WINDOW_RETURN_ROW;
}
break;
case TK_UNBOUNDED:
if( windowCacheFrame(pMWin)==0 ){
if( pMWin->eEnd==TK_PRECEDING ){
if( pMWin->eFrmType!=TK_RANGE
&& windowExprGtZero(pParse, pMWin->pEnd)
){
s.eDelete = WINDOW_AGGSTEP;
}
}else{
s.eDelete = WINDOW_RETURN_ROW;
}
}
break;
default:
s.eDelete = WINDOW_AGGINVERSE;
break;
}
/* Allocate registers for the array of values from the sub-query, the
** same values in record form, and the rowid used to insert said record
** into the ephemeral table. */
regNew = pParse->nMem+1;
pParse->nMem += nInput;
regRecord = ++pParse->nMem;
s.regRowid = ++pParse->nMem;
/* If the window frame contains an "<expr> PRECEDING" or "<expr> FOLLOWING"
** clause, allocate registers to store the results of evaluating each
** <expr>. */
if( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ){
regStart = ++pParse->nMem;
}
if( pMWin->eEnd==TK_PRECEDING || pMWin->eEnd==TK_FOLLOWING ){
regEnd = ++pParse->nMem;
}
/* If this is not a "ROWS BETWEEN ..." frame, then allocate arrays of
** registers to store copies of the ORDER BY expressions (peer values)
** for the main loop, and for each cursor (start, current and end). */
if( pMWin->eFrmType!=TK_ROWS ){
int nPeer = (pOrderBy ? pOrderBy->nExpr : 0);
regNewPeer = regNew + pMWin->nBufferCol;
if( pMWin->pPartition ) regNewPeer += pMWin->pPartition->nExpr;
regPeer = pParse->nMem+1; pParse->nMem += nPeer;
s.start.reg = pParse->nMem+1; pParse->nMem += nPeer;
s.current.reg = pParse->nMem+1; pParse->nMem += nPeer;
s.end.reg = pParse->nMem+1; pParse->nMem += nPeer;
}
/* Load the column values for the row returned by the sub-select
** into an array of registers starting at regNew. Assemble them into
** a record in register regRecord. */
for(iInput=0; iInput<nInput; iInput++){
sqlite3VdbeAddOp3(v, OP_Column, csrInput, iInput, regNew+iInput);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regNew, nInput, regRecord);
/* An input row has just been read into an array of registers starting
** at regNew. If the window has a PARTITION clause, this block generates
** VM code to check if the input row is the start of a new partition.
** If so, it does an OP_Gosub to an address to be filled in later. The
** address of the OP_Gosub is stored in local variable addrGosubFlush. */
if( pMWin->pPartition ){
int addr;
ExprList *pPart = pMWin->pPartition;
int nPart = pPart->nExpr;
int regNewPart = regNew + pMWin->nBufferCol;
KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0);
regFlushPart = ++pParse->nMem;
addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart, nPart);
sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2);
VdbeCoverageEqNe(v);
addrGosubFlush = sqlite3VdbeAddOp1(v, OP_Gosub, regFlushPart);
VdbeComment((v, "call flush_partition"));
sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1);
}
/* Insert the new row into the ephemeral table */
sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, s.regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, s.regRowid);
addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, s.regRowid);
VdbeCoverageNeverNull(v);
/* This block is run for the first row of each partition */
s.regArg = windowInitAccum(pParse, pMWin);
if( regStart ){
sqlite3ExprCode(pParse, pMWin->pStart, regStart);
windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0));
}
if( regEnd ){
sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0));
}
if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){
int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le);
for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
FuncDef *pNext, *p;
p = sqliteHashData(i);
do{
functionDestroy(db, p);
pNext = p->pNext;
sqlite3DbFree(db, p);
p = pNext;
}while( p );
}
sqlite3HashClear(&db->aFunc);
for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
CollSeq *pColl = (CollSeq *)sqliteHashData(i);
/* Invoke any destructors registered for collation sequence user data. */
for(j=0; j<3; j++){
if( pColl[j].xDel ){
pColl[j].xDel(pColl[j].pUser);
}
}
sqlite3DbFree(db, pColl);
}
sqlite3HashClear(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
Module *pMod = (Module *)sqliteHashData(i);
sqlite3VtabEponymousTableClear(db, pMod);
sqlite3VtabModuleUnref(db, pMod);
}
sqlite3HashClear(&db->aModule);
#endif
sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
sqlite3ValueFree(db->pErr);
sqlite3CloseExtensions(db);
db->eOpenState = SQLITE_STATE_ERROR;
/* The temp-database schema is allocated differently from the other schema
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
** So it needs to be freed here. Todo: Why not roll the temp schema into
** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
sqlite3DbFree(db, db->aDb[1].pSchema);
if( db->xAutovacDestr ){
db->xAutovacDestr(db->pAutovacPagesArg);
}
sqlite3_mutex_leave(db->mutex);
db->eOpenState = SQLITE_STATE_CLOSED;
sqlite3_mutex_free(db->mutex);
assert( sqlite3LookasideUsed(db,0)==0 );
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
sqlite3_free(db);
}
/*
** Rollback all database files. If tripCode is not SQLITE_OK, then
** any write cursors are invalidated ("tripped" - as in "tripping a circuit
** breaker") and made to return tripCode if there are any further
** attempts to use that cursor. Read cursors remain open and valid
** but are "saved" in case the table pages are moved around.
*/
SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
int i;
int inTrans = 0;
int schemaChange;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3BeginBenignMalloc();
/* Obtain all b-tree mutexes before making any calls to BtreeRollback().
** This is important in case the transaction being rolled back has
** modified the database schema. If the b-tree mutexes are not taken
** here, then another shared-cache connection might sneak in between
** the database rollback and schema reset, which can cause false
** corruption reports in some cases. */
sqlite3BtreeEnterAll(db);
schemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0 && db->init.busy==0;
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
if( p ){
if( sqlite3BtreeTxnState(p)==SQLITE_TXN_WRITE ){
inTrans = 1;
}
sqlite3BtreeRollback(p, tripCode, !schemaChange);
}
}
sqlite3VtabRollback(db);
sqlite3EndBenignMalloc();
if( schemaChange ){
sqlite3ExpirePreparedStatements(db, 0);
sqlite3ResetAllSchemasOfConnection(db);
}
sqlite3BtreeLeaveAll(db);
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly);
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
db->xRollbackCallback(db->pRollbackArg);
}
}
/*
** Return a static string containing the name corresponding to the error code
** specified in the argument.
*/
#if defined(SQLITE_NEED_ERR_NAME)
SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
const char *zName = 0;
int i, origRc = rc;
for(i=0; i<2 && zName==0; i++, rc &= 0xff){
switch( rc ){
case SQLITE_OK: zName = "SQLITE_OK"; break;
case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break;
*/
#ifndef _FTSINT_H
#define _FTSINT_H
/*
** Activate assert() only if SQLITE_TEST is enabled.
*/
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stddef.h> */
/* #include <stdio.h> */
/* #include <string.h> */
/* #include <stdarg.h> */
/* FTS3/FTS4 require virtual tables */
#ifdef SQLITE_OMIT_VIRTUALTABLE
# undef SQLITE_ENABLE_FTS3
# undef SQLITE_ENABLE_FTS4
#endif
/*
** FTS4 is really an extension for FTS3. It is enabled using the
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
*/
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
# define SQLITE_ENABLE_FTS3
#endif
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/* If not building as part of the core, include sqlite3ext.h. */
#ifndef SQLITE_CORE
/* # include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT3
#endif
/* #include "sqlite3.h" */
/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
/************** Begin file fts3_tokenizer.h **********************************/
/*
** 2006 July 10
**
** The author disclaims copyright to this source code.
**
*************************************************************************
** Defines the interface to tokenizers used by fulltext-search. There
** are three basic components:
**
** sqlite3_tokenizer_module is a singleton defining the tokenizer
** interface functions. This is essentially the class structure for
** tokenizers.
**
** sqlite3_tokenizer is used to define a particular tokenizer, perhaps
** including customization information defined at creation time.
**
** sqlite3_tokenizer_cursor is generated by a tokenizer to generate
** tokens from a particular input.
*/
#ifndef _FTS3_TOKENIZER_H_
#define _FTS3_TOKENIZER_H_
/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time.
** If tokenizers are to be allowed to call sqlite3_*() functions, then
** we will need a way to register the API consistently.
*/
/* #include "sqlite3.h" */
/*
** Structures used by the tokenizer interface. When a new tokenizer
** implementation is registered, the caller provides a pointer to
** an sqlite3_tokenizer_module containing pointers to the callback
** functions that make up an implementation.
**
** When an fts3 table is created, it passes any arguments passed to
** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the
** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer
** implementation. The xCreate() function in turn returns an
** sqlite3_tokenizer structure representing the specific tokenizer to
** be used for the fts3 table (customized by the tokenizer clause arguments).
**
** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen()
** method is called. It returns an sqlite3_tokenizer_cursor object
** that may be used to tokenize a specific input buffer based on
** the tokenization rules supplied by a specific sqlite3_tokenizer
** object.
*/
typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module;
typedef struct sqlite3_tokenizer sqlite3_tokenizer;
typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor;
struct sqlite3_tokenizer_module {
/*
** Structure version. Should always be set to 0 or 1.
*/
int iVersion;
/*
** Create a new tokenizer. The values in the argv[] array are the
** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL
** TABLE statement that created the fts3 table. For example, if
** the following SQL is executed:
**
** CREATE .. USING fts3( ... , tokenizer <tokenizer-name> arg1 arg2)
**
** then argc is set to 2, and the argv[] array contains pointers
** to the strings "arg1" and "arg2".
**
** This method should return either SQLITE_OK (0), or an SQLite error
** code. If SQLITE_OK is returned, then *ppTokenizer should be set
** to point at the newly created tokenizer structure. The generic
** sqlite3_tokenizer.pModule variable should not be initialized by
** this callback. The caller will do so.
*/
int (*xCreate)(
int argc, /* Size of argv array */
const char *const*argv, /* Tokenizer argument strings */
sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
);
/*
** Destroy an existing tokenizer. The fts3 module calls this method
** exactly once for each successful call to xCreate().
*/
int (*xDestroy)(sqlite3_tokenizer *pTokenizer);
/*
** Create a tokenizer cursor to tokenize an input buffer. The caller
** is responsible for ensuring that the input buffer remains valid
** until the cursor is closed (using the xClose() method).
*/
int (*xOpen)(
sqlite3_tokenizer *pTokenizer, /* Tokenizer object */
const char *pInput, int nBytes, /* Input buffer */
sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */
);
/*
** Destroy an existing tokenizer cursor. The fts3 module calls this
** method exactly once for each successful call to xOpen().
*/
int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
/*
** Retrieve the next token from the tokenizer cursor pCursor. This
** method should either return SQLITE_OK and set the values of the
** "OUT" variables identified below, or SQLITE_DONE to indicate that
** the end of the buffer has been reached, or an SQLite error code.
**
** *ppToken should be set to point at a buffer containing the
** normalized version of the token (i.e. after any case-folding and/or
** stemming has been performed). *pnBytes should be set to the length
** of this buffer in bytes. The input text that generated the token is
** identified by the byte offsets returned in *piStartOffset and
** *piEndOffset. *piStartOffset should be set to the index of the first
** byte of the token in the input buffer. *piEndOffset should be set
** to the index of the first byte just past the end of the token in
** the input buffer.
**
** The buffer *ppToken is set to point at is managed by the tokenizer
** implementation. It is only required to be valid until the next call
** to xNext() or xClose().
*/
/* TODO(shess) current implementation requires pInput to be
** nul-terminated. This should either be fixed, or pInput/nBytes
** should be converted to zInput.
*/
int (*xNext)(
sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */
const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */
int *piStartOffset, /* OUT: Byte offset of token in input buffer */
int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */
int *piPosition /* OUT: Number of tokens returned before this one */
);
/***********************************************************************
** Methods below this point are only available if iVersion>=1.
*/
/*
** Configure the language id of a tokenizer cursor.
*/
int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid);
};
struct sqlite3_tokenizer {
const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */
/* Tokenizer implementations will typically add additional fields */
};
struct sqlite3_tokenizer_cursor {
sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */
/* Tokenizer implementations will typically add additional fields */
};
int fts3_global_term_cnt(int iTerm, int iCol);
int fts3_term_cnt(int iTerm, int iCol);
#endif /* _FTS3_TOKENIZER_H_ */
/************** End of fts3_tokenizer.h **************************************/
/************** Continuing where we left off in fts3Int.h ********************/
/************** Include fts3_hash.h in the middle of fts3Int.h ***************/
/************** Begin file fts3_hash.h ***************************************/
/*
** 2001 September 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This is the header file for the generic hash-table implementation
** used in SQLite. We've modified it slightly to serve as a standalone
** hash table implementation for the full-text indexing module.
**
*/
#ifndef _FTS3_HASH_H_
#define _FTS3_HASH_H_
/* Forward declarations of structures. */
typedef struct Fts3Hash Fts3Hash;
typedef struct Fts3HashElem Fts3HashElem;
/* A complete hash table is an instance of the following structure.
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly. Change this structure only by using the routines below.
** However, many of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
*/
struct Fts3Hash {
char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */
char copyKey; /* True if copy of key made on insert */
int count; /* Number of entries in this table */
Fts3HashElem *first; /* The first element of the array */
int htsize; /* Number of buckets in the hash table */
struct _fts3ht { /* the hash table */
int count; /* Number of entries with this hash */
Fts3HashElem *chain; /* Pointer to first entry with this hash */
} *ht;
};
/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
int iSavepoint;
/*
** The following array of hash tables is used to buffer pending index
** updates during transactions. All pending updates buffered at any one
** time must share a common language-id (see the FTS4 langid= feature).
** The current language id is stored in variable iPrevLangid.
**
** A single FTS4 table may have multiple full-text indexes. For each index
** there is an entry in the aIndex[] array. Index 0 is an index of all the
** terms that appear in the document set. Each subsequent index in aIndex[]
** is an index of prefixes of a specific length.
**
** Variable nPendingData contains an estimate the memory consumed by the
** pending data structures, including hash table overhead, but not including
** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash
** tables are flushed to disk. Variable iPrevDocid is the docid of the most
** recently inserted record.
*/
int nIndex; /* Size of aIndex[] */
struct Fts3Index {
int nPrefix; /* Prefix length (0 for main terms index) */
Fts3Hash hPending; /* Pending terms table for this index */
} *aIndex;
int nMaxPendingData; /* Max pending data before flush to disk */
int nPendingData; /* Current bytes of pending data */
sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */
int iPrevLangid; /* Langid of recently inserted document */
int bPrevDelete; /* True if last operation was a delete */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
/* State variables used for validating that the transaction control
** methods of the virtual table are called at appropriate times. These
** values do not contribute to FTS functionality; they are used for
** verifying the operation of the SQLite core.
*/
int inTransaction; /* True after xBegin but before xCommit/xRollback */
int mxSavepoint; /* Largest valid xSavepoint integer */
#endif
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/* True to disable the incremental doclist optimization. This is controlled
** by special insert command 'test-no-incr-doclist'. */
int bNoIncrDoclist;
/* Number of segments in a level */
int nMergeCount;
#endif
};
/* Macro to find the number of segments to merge */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# define MergeCount(P) ((P)->nMergeCount)
#else
# define MergeCount(P) FTS3_MERGE_COUNT
#endif
/*
** When the core wants to read from the virtual table, it creates a
** virtual table cursor (an instance of the following structure) using
** the xOpen method. Cursors are destroyed using the xClose method.
*/
struct Fts3Cursor {
sqlite3_vtab_cursor base; /* Base class used by SQLite core */
i16 eSearch; /* Search strategy (see below) */
u8 isEof; /* True if at End Of Results */
u8 isRequireSeek; /* True if must seek pStmt to %_content row */
u8 bSeekStmt; /* True if pStmt is a seek */
sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
Fts3Expr *pExpr; /* Parsed MATCH query string */
int iLangid; /* Language being queried for */
int nPhrase; /* Number of matchable phrases in query */
Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */
sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
char *pNextId; /* Pointer into the body of aDoclist */
char *aDoclist; /* List of docids for full-text queries */
int nDoclist; /* Size of buffer at aDoclist */
u8 bDesc; /* True to sort in descending order */
int eEvalmode; /* An FTS3_EVAL_XX constant */
int nRowAvg; /* Average size of database rows, in pages */
sqlite3_int64 nDoc; /* Documents in table */
i64 iMinDocid; /* Minimum docid to return */
i64 iMaxDocid; /* Maximum docid to return */
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */
};
#define FTS3_EVAL_FILTER 0
#define FTS3_EVAL_NEXT 1
#define FTS3_EVAL_MATCHINFO 2
/*
** The Fts3Cursor.eSearch member is always set to one of the following.
** Actually, Fts3Cursor.eSearch can be greater than or equal to
** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
** of the column to be searched. For example, in
**
** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
**
** Because the LHS of the MATCH operator is 2nd column "b",
** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a,
** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1"
** indicating that all columns should be searched,
** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4.
*/
#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
/*
** The lower 16-bits of the sqlite3_index_info.idxNum value set by
** the xBestIndex() method contains the Fts3Cursor.eSearch value described
** above. The upper 16-bits contain a combination of the following
** bits, used to describe extra constraints on full-text searches.
*/
#define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */
#define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */
#define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */
struct Fts3Doclist {
char *aAll; /* Array containing doclist (or NULL) */
int nAll; /* Size of a[] in bytes */
char *pNextDocid; /* Pointer to next docid */
sqlite3_int64 iDocid; /* Current docid (if pList!=0) */
int bFreeList; /* True if pList should be sqlite3_free()d */
char *pList; /* Pointer to position list following iDocid */
int nList; /* Length of position list */
int nCost; /* Cost of running iterator */
int bLookup; /* True if a lookup of a single entry. */
/* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */
char *zTerm; /* Pointer to term buffer */
int nTerm; /* Size of zTerm in bytes */
char *aDoclist; /* Pointer to doclist buffer */
int nDoclist; /* Size of aDoclist[] in bytes */
};
SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
#define fts3GetVarint32(p, piVal) ( \
(*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
)
/* fts3.c */
SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...);
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *);
SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*);
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*);
SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *);
SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut);
/* fts3_tokenizer.c */
SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
sqlite3_tokenizer **, char **
);
SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char);
/* fts3_snippet.c */
SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*);
SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
const char *, const char *, int, int
);
SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
SQLITE_PRIVATE void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p);
/* fts3_expr.c */
SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
char **, int, int, int, const char *, int, Fts3Expr **, char **
);
SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *);
#ifdef SQLITE_TEST
SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*);
SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db);
#endif
SQLITE_PRIVATE void *sqlite3Fts3MallocZero(i64 nByte);
SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int,
sqlite3_tokenizer_cursor **
);
/* fts3_aux.c */
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db);
SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
SQLITE_PRIVATE int sqlite3Fts3MsrCancel(Fts3Cursor*, Fts3Expr*);
/* fts3_tokenize_vtab.c */
SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*));
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
#ifndef SQLITE_DISABLE_FTS3_UNICODE
SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int);
SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int);
SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
#endif
SQLITE_PRIVATE int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*);
SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk);
#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */
/************** End of fts3Int.h *********************************************/
/************** Continuing where we left off in fts3.c ***********************/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE)
# define SQLITE_CORE 1
#endif
/* #include "fts3.h" */
#ifndef SQLITE_CORE
/* # include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
#endif
typedef struct Fts3HashWrapper Fts3HashWrapper;
struct Fts3HashWrapper {
Fts3Hash hash; /* Hash table */
int nRef; /* Number of pointers to this object */
};
static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
/*
}
if( bDocid ){
switch( pCons->op ){
case SQLITE_INDEX_CONSTRAINT_GE:
case SQLITE_INDEX_CONSTRAINT_GT:
iDocidGe = i;
break;
case SQLITE_INDEX_CONSTRAINT_LE:
case SQLITE_INDEX_CONSTRAINT_LT:
iDocidLe = i;
break;
}
}
}
/* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */
if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo);
iIdx = 1;
if( iCons>=0 ){
pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
pInfo->aConstraintUsage[iCons].omit = 1;
}
if( iLangidCons>=0 ){
pInfo->idxNum |= FTS3_HAVE_LANGID;
pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
}
if( iDocidGe>=0 ){
pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
}
if( iDocidLe>=0 ){
pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
}
/* Regardless of the strategy selected, FTS can deliver rows in rowid (or
** docid) order. Both ascending and descending are possible.
*/
if( pInfo->nOrderBy==1 ){
struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0];
if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){
if( pOrder->desc ){
pInfo->idxStr = "DESC";
}else{
pInfo->idxStr = "ASC";
}
pInfo->orderByConsumed = 1;
}
}
assert( p->pSegments==0 );
return SQLITE_OK;
}
/*
** Implementation of xOpen method.
*/
static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
sqlite3_vtab_cursor *pCsr; /* Allocated cursor */
UNUSED_PARAMETER(pVTab);
/* Allocate a buffer large enough for an Fts3Cursor structure. If the
** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
** if the allocation fails, return SQLITE_NOMEM.
*/
*ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));
if( !pCsr ){
return SQLITE_NOMEM;
}
memset(pCsr, 0, sizeof(Fts3Cursor));
return SQLITE_OK;
}
/*
** Finalize the statement handle at pCsr->pStmt.
**
** Or, if that statement handle is one created by fts3CursorSeekStmt(),
** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement
** pointer there instead of finalizing it.
*/
static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
if( pCsr->bSeekStmt ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
if( p->pSeekStmt==0 ){
p->pSeekStmt = pCsr->pStmt;
sqlite3_reset(pCsr->pStmt);
pCsr->pStmt = 0;
}
pCsr->bSeekStmt = 0;
}
sqlite3_finalize(pCsr->pStmt);
}
/*
** Free all resources currently held by the cursor passed as the only
** argument.
*/
static void fts3ClearCursor(Fts3Cursor *pCsr){
fts3CursorFinalizeStmt(pCsr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
}
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
fts3ClearCursor(pCsr);
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then
** compose and prepare an SQL statement of the form:
**
** "SELECT <columns> FROM %_content WHERE rowid = ?"
**
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
** it. If an error occurs, return an SQLite error code.
*/
static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
int rc = SQLITE_OK;
if( pCsr->pStmt==0 ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
char *zSql;
if( p->pSeekStmt ){
pCsr->pStmt = p->pSeekStmt;
p->pSeekStmt = 0;
}else{
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
p->bLock++;
rc = sqlite3_prepare_v3(
p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
);
p->bLock--;
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
}
return rc;
}
/*
** Position the pCsr->pStmt statement so that it is on the row
** of the %_content table that contains the last match. Return
** SQLITE_OK on success.
*/
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
int rc = SQLITE_OK;
if( pCsr->isRequireSeek ){
rc = fts3CursorSeekStmt(pCsr);
if( rc==SQLITE_OK ){
Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
pTab->bLock++;
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
pTab->bLock--;
return SQLITE_OK;
}else{
pTab->bLock--;
rc = sqlite3_reset(pCsr->pStmt);
int rc = SQLITE_OK; /* Error code */
sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
int rc2; /* Result of sqlite3_reset() */
/* If iLevel is less than 0 and this is not a scan, include a seg-reader
** for the pending-terms. If this is a scan, then this call must be being
** made by an fts4aux module, not an FTS table. In this case calling
** Fts3SegReaderPending might segfault, as the data structures used by
** fts4aux are not completely populated. So it's easiest to filter these
** calls out here. */
if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){
Fts3SegReader *pSeg = 0;
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
if( rc==SQLITE_OK && pSeg ){
rc = fts3SegReaderCursorAppend(pCsr, pSeg);
}
}
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
if( rc==SQLITE_OK ){
rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt);
}
while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
Fts3SegReader *pSeg = 0;
/* Read the values returned by the SELECT into local variables. */
sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1);
sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2);
sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3);
int nRoot = sqlite3_column_bytes(pStmt, 4);
char const *zRoot = sqlite3_column_blob(pStmt, 4);
/* If zTerm is not NULL, and this segment is not stored entirely on its
** root node, the range of leaves scanned can be reduced. Do this. */
if( iStartBlock && zTerm && zRoot ){
sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
if( rc!=SQLITE_OK ) goto finished;
if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
}
rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
(isPrefix==0 && isScan==0),
iStartBlock, iLeavesEndBlock,
iEndBlock, zRoot, nRoot, &pSeg
);
if( rc!=SQLITE_OK ) goto finished;
rc = fts3SegReaderCursorAppend(pCsr, pSeg);
}
}
finished:
rc2 = sqlite3_reset(pStmt);
if( rc==SQLITE_DONE ) rc = rc2;
return rc;
}
/*
** Set up a cursor object for iterating through a full-text index or a
** single level therein.
*/
SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
Fts3Table *p, /* FTS3 table handle */
int iLangid, /* Language-id to search */
int iIndex, /* Index to search (from 0 to p->nIndex-1) */
int iLevel, /* Level of segments to scan */
const char *zTerm, /* Term to query for */
int nTerm, /* Size of zTerm in bytes */
int isPrefix, /* True for a prefix search */
int isScan, /* True to scan from zTerm to EOF */
Fts3MultiSegReader *pCsr /* Cursor object to populate */
){
assert( iIndex>=0 && iIndex<p->nIndex );
assert( iLevel==FTS3_SEGCURSOR_ALL
|| iLevel==FTS3_SEGCURSOR_PENDING
|| iLevel>=0
);
assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 );
assert( isPrefix==0 || isScan==0 );
memset(pCsr, 0, sizeof(Fts3MultiSegReader));
return fts3SegReaderCursor(
p, iLangid, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr
);
}
/*
** In addition to its current configuration, have the Fts3MultiSegReader
** passed as the 4th argument also scan the doclist for term zTerm/nTerm.
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3SegReaderCursorAddZero(
Fts3Table *p, /* FTS virtual table handle */
int iLangid,
const char *zTerm, /* Term to scan doclist of */
int nTerm, /* Number of bytes in zTerm */
Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
){
return fts3SegReaderCursor(p,
iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr
);
}
/*
** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
** if isPrefix is true, to scan the doclist for all terms for which
** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
** an SQLite error code.
**
** It is the responsibility of the caller to free this object by eventually
** passing it to fts3SegReaderCursorFree()
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
** Output parameter *ppSegcsr is set to 0 if an error occurs.
*/
static int fts3TermSegReaderCursor(
Fts3Cursor *pCsr, /* Virtual table cursor handle */
const char *zTerm, /* Term to query for */
int nTerm, /* Size of zTerm in bytes */
int isPrefix, /* True for a prefix search */
Fts3MultiSegReader **ppSegcsr /* OUT: Allocated seg-reader cursor */
){
Fts3MultiSegReader *pSegcsr; /* Object to allocate and return */
int rc = SQLITE_NOMEM; /* Return code */
pSegcsr = sqlite3_malloc(sizeof(Fts3MultiSegReader));
if( pSegcsr ){
int i;
int bFound = 0; /* True once an index has been found */
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
if( isPrefix ){
for(i=1; bFound==0 && i<p->nIndex; i++){
if( p->aIndex[i].nPrefix==nTerm ){
bFound = 1;
rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr
);
pSegcsr->bLookup = 1;
}
}
for(i=1; bFound==0 && i<p->nIndex; i++){
if( p->aIndex[i].nPrefix==nTerm+1 ){
bFound = 1;
rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
);
if( rc==SQLITE_OK ){
rc = fts3SegReaderCursorAddZero(
p, pCsr->iLangid, zTerm, nTerm, pSegcsr
);
}
}
}
}
if( bFound==0 ){
rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
);
pSegcsr->bLookup = !isPrefix;
}
}
*ppSegcsr = pSegcsr;
return rc;
}
/*
** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor().
*/
static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
sqlite3Fts3SegReaderFinish(pSegcsr);
sqlite3_free(pSegcsr);
}
/*
** This function retrieves the doclist for the specified term (or term
** prefix) from the database.
*/
static int fts3TermSelect(
Fts3Table *p, /* Virtual table handle */
Fts3PhraseToken *pTok, /* Token to query for */
int iColumn, /* Column to query (or -ve for all columns) */
int *pnOut, /* OUT: Size of buffer at *ppOut */
char **ppOut /* OUT: Malloced result buffer */
){
int rc; /* Return code */
Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */
TermSelect tsc; /* Object for pair-wise doclist merging */
Fts3SegFilter filter; /* Segment term filter configuration */
pSegcsr = pTok->pSegcsr;
memset(&tsc, 0, sizeof(TermSelect));
filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS
| (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0)
| (pTok->bFirst ? FTS3_SEGMENT_FIRST : 0)
| (iColumn<p->nColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0);
filter.iCol = iColumn;
filter.zTerm = pTok->z;
filter.nTerm = pTok->n;
rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
while( SQLITE_OK==rc
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
){
rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
}
if( rc==SQLITE_OK ){
rc = fts3TermSelectFinishMerge(p, &tsc);
}
if( rc==SQLITE_OK ){
*ppOut = tsc.aaOutput[0];
*pnOut = tsc.anOutput[0];
}else{
int i;
for(i=0; i<SizeofArray(tsc.aaOutput); i++){
sqlite3_free(tsc.aaOutput[i]);
}
}
fts3SegReaderCursorFree(pSegcsr);
pTok->pSegcsr = 0;
return rc;
}
/*
** This function counts the total number of docids in the doclist stored
** in buffer aList[], size nList bytes.
**
** If the isPoslist argument is true, then it is assumed that the doclist
** contains a position-list following each docid. Otherwise, it is assumed
** that the doclist is simply a list of docids stored as delta encoded
** varints.
*/
static int fts3DoclistCountDocids(char *aList, int nList){
int nDoc = 0; /* Return value */
if( aList ){
char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */
char *p = aList; /* Cursor */
while( p<aEnd ){
nDoc++;
while( (*p++)&0x80 ); /* Skip docid varint */
fts3PoslistCopy(0, &p); /* Skip over position list */
}
}
return nDoc;
}
/*
** Advance the cursor to the next row in the %_content table that
** matches the search criteria. For a MATCH search, this will be
** the next row that matches. For a full-table scan, this will be
** simply the next row in the %_content table. For a docid lookup,
** this routine simply sets the EOF flag.
**
** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
** even if we reach end-of-file. The fts3EofMethod() will be called
** subsequently to determine whether or not an EOF was hit.
*/
static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
int rc;
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
Fts3Table *pTab = (Fts3Table*)pCursor->pVtab;
pTab->bLock++;
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
pCsr->isEof = 1;
rc = sqlite3_reset(pCsr->pStmt);
}else{
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
rc = SQLITE_OK;
}
pTab->bLock--;
}else{
rc = fts3EvalNext((Fts3Cursor *)pCursor);
}
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
return rc;
}
/*
** If the numeric type of argument pVal is "integer", then return it
** converted to a 64-bit signed integer. Otherwise, return a copy of
** the second parameter, iDefault.
*/
static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
if( pVal ){
int eType = sqlite3_value_numeric_type(pVal);
if( eType==SQLITE_INTEGER ){
return sqlite3_value_int64(pVal);
}
}
return iDefault;
}
/*
** This is the xFilter interface for the virtual table. See
** the virtual table xFilter method documentation for additional
** information.
**
** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against
** the %_content table.
**
** If idxNum==FTS3_DOCID_SEARCH then do a docid lookup for a single entry
** in the %_content table.
**
** If idxNum>=FTS3_FULLTEXT_SEARCH then use the full text index. The
** column on the left-hand side of the MATCH operator is column
** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand
** side of the MATCH operator.
*/
static int fts3FilterMethod(
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
int idxNum, /* Strategy index */
const char *idxStr, /* Unused */
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
int rc = SQLITE_OK;
char *zSql; /* SQL statement used to access %_content */
int eSearch;
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */
sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */
sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */
sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */
int iIdx;
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(nVal);
if( p->bLock ){
return SQLITE_ERROR;
}
eSearch = (idxNum & 0x0000FFFF);
assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
assert( p->pSegments==0 );
/* Collect arguments into local variables */
iIdx = 0;
if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++];
if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++];
if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++];
if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++];
assert( iIdx==nVal );
/* In case the cursor has been used before, clear it now. */
fts3ClearCursor(pCsr);
/* Set the lower and upper bounds on docids to return */
pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64);
if( idxStr ){
pCsr->bDesc = (idxStr[0]=='D');
}else{
pCsr->bDesc = p->bDescIdx;
}
pCsr->eSearch = (i16)eSearch;
if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){
int iCol = eSearch-FTS3_FULLTEXT_SEARCH;
const char *zQuery = (const char *)sqlite3_value_text(pCons);
if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){
return SQLITE_NOMEM;
}
pCsr->iLangid = 0;
if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid);
assert( p->base.zErrMsg==0 );
rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
&p->base.zErrMsg
);
if( rc!=SQLITE_OK ){
return rc;
}
rc = fts3EvalStart(pCsr);
sqlite3Fts3SegmentsClose(p);
if( rc!=SQLITE_OK ) return rc;
pCsr->pNextId = pCsr->aDoclist;
pCsr->iPrevId = 0;
}
/* Compile a SELECT statement for this cursor. For a full-table-scan, the
** statement loops through all rows of the %_content table. For a
** full-text query or docid lookup, the statement retrieves a single
** row by docid.
*/
if( eSearch==FTS3_FULLSCAN_SEARCH ){
if( pDocidGe || pDocidLe ){
zSql = sqlite3_mprintf(
"SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s",
p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid,
(pCsr->bDesc ? "DESC" : "ASC")
);
}else{
zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s",
p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
);
}
if( zSql ){
p->bLock++;
rc = sqlite3_prepare_v3(
p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
);
p->bLock--;
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
}
}else if( eSearch==FTS3_DOCID_SEARCH ){
rc = fts3CursorSeekStmt(pCsr);
if( rc==SQLITE_OK ){
rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
}
}
if( rc!=SQLITE_OK ) return rc;
return fts3NextMethod(pCursor);
}
/*
** This is the xEof method of the virtual table. SQLite calls this
** routine to find out if it has reached the end of a result set.
*/
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
if( pCsr->isEof ){
fts3ClearCursor(pCsr);
pCsr->isEof = 1;
}
return pCsr->isEof;
}
/*
** This is the xRowid method. The SQLite core calls this routine to
** retrieve the rowid for the current row of the result set. fts3
** exposes %_content.docid as the rowid for the virtual table. The
** rowid should be written to *pRowid.
*/
static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
*pRowid = pCsr->iPrevId;
return SQLITE_OK;
}
/*
** This is the xColumn method, called by SQLite to request a value from
** the row that the supplied cursor currently points to.
**
** If:
**
** (iCol < p->nColumn) -> The value of the iCol'th user column.
** (iCol == p->nColumn) -> Magic column with the same name as the table.
** (iCol == p->nColumn+1) -> Docid column
** (iCol == p->nColumn+2) -> Langid column
*/
static int fts3ColumnMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
int rc = SQLITE_OK; /* Return Code */
Fts3Cursor *pCsr = (Fts3Cursor *) pCursor;
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
/* The column value supplied by SQLite must be in range. */
assert( iCol>=0 && iCol<=p->nColumn+2 );
switch( iCol-p->nColumn ){
case 0:
/* The special 'table-name' column */
sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
break;
case 1:
/* The docid column */
sqlite3_result_int64(pCtx, pCsr->iPrevId);
break;
case 2:
if( pCsr->pExpr ){
sqlite3_result_int64(pCtx, pCsr->iLangid);
break;
}else if( p->zLanguageid==0 ){
sqlite3_result_int(pCtx, 0);
break;
}else{
iCol = p->nColumn;
/* no break */ deliberate_fall_through
}
default:
/* A user column. Or, if this is a full-table scan, possibly the
** language-id column. Seek the cursor. */
rc = fts3CursorSeek(0, pCsr);
if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
}
break;
}
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
return rc;
}
/*
** This function is the implementation of the xUpdate callback used by
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
** inserted, updated or deleted.
*/
static int fts3UpdateMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
int nArg, /* Size of argument array */
sqlite3_value **apVal, /* Array of arguments */
sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
){
return sqlite3Fts3UpdateMethod(pVtab, nArg, apVal, pRowid);
}
/*
** Implementation of xSync() method. Flush the contents of the pending-terms
** hash-table to the database.
*/
static int fts3SyncMethod(sqlite3_vtab *pVtab){
/* Following an incremental-merge operation, assuming that the input
** segments are not completely consumed (the usual case), they are updated
** in place to remove the entries that have already been merged. This
** involves updating the leaf block that contains the smallest unmerged
** entry and each block (if any) between the leaf and the root node. So
** if the height of the input segment b-trees is N, and input segments
** are merged eight at a time, updating the input segments at the end
** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually
** small - often between 0 and 2. So the overhead of the incremental
** merge is somewhere between 8 and 24 blocks. To avoid this overhead
** dwarfing the actual productive work accomplished, the incremental merge
** is only attempted if it will write at least 64 leaf blocks. Hence
** nMinMerge.
**
** Of course, updating the input segments also involves deleting a bunch
** of blocks from the segments table. But this is not considered overhead
** as it would also be required by a crisis-merge that used the same input
** segments.
*/
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
Fts3Table *p = (Fts3Table*)pVtab;
int rc;
i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK
&& p->nLeafAdd>(nMinMerge/16)
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
sqlite3Fts3PendingTermsClear(p);
assert( p->inTransaction!=0 );
TESTONLY( p->inTransaction = 0 );
TESTONLY( p->mxSavepoint = -1; );
return SQLITE_OK;
}
/*
** When called, *ppPoslist must point to the byte immediately following the
** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
** moves *ppPoslist so that it instead points to the first byte of the
** same position list.
*/
static void fts3ReversePoslist(char *pStart, char **ppPoslist){
char *p = &(*ppPoslist)[-2];
char c = 0;
/* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */
while( p>pStart && (c=*p--)==0 );
/* Search backwards for a varint with value zero (the end of the previous
** poslist). This is an 0x00 byte preceded by some byte that does not
** have the 0x80 bit set. */
while( p>pStart && (*p & 0x80) | c ){
c = *p--;
}
assert( p==pStart || c==0 );
/* At this point p points to that preceding byte without the 0x80 bit
** set. So to find the start of the poslist, skip forward 2 bytes then
** over a varint.
**
** Normally. The other case is that p==pStart and the poslist to return
** is the first in the doclist. In this case do not skip forward 2 bytes.
** The second part of the if condition (c==0 && *ppPoslist>&p[2])
** is required for cases where the first byte of a doclist and the
** doclist is empty. For example, if the first docid is 10, a doclist
** that begins with:
**
** 0x0A 0x00 <next docid delta varint>
*/
if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; }
while( *p++&0x80 );
*ppPoslist = p;
}
/*
** Helper function used by the implementation of the overloaded snippet(),
** offsets() and optimize() SQL functions.
**
** If the value passed as the third argument is a blob of size
** sizeof(Fts3Cursor*), then the blob contents are copied to the
** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error
** message is written to context pContext and SQLITE_ERROR returned. The
** string passed via zFunc is used as part of the error message.
*/
static int fts3FunctionArg(
sqlite3_context *pContext, /* SQL function call context */
const char *zFunc, /* Function name */
sqlite3_value *pVal, /* argv[0] passed to function */
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
){
int rc;
*ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
if( (*ppCsr)!=0 ){
rc = SQLITE_OK;
}else{
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
sqlite3_result_error(pContext, zErr, -1);
sqlite3_free(zErr);
rc = SQLITE_ERROR;
}
return rc;
}
/*
** Implementation of the snippet() function for FTS3
*/
static void fts3SnippetFunc(
sqlite3_context *pContext, /* SQLite function call context */
int nVal, /* Size of apVal[] array */
sqlite3_value **apVal /* Array of arguments */
){
Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
const char *zStart = "<b>";
const char *zEnd = "</b>";
const char *zEllipsis = "<b>...</b>";
int iCol = -1;
int nToken = 15; /* Default number of tokens in snippet */
/* There must be at least one argument passed to this function (otherwise
** the non-overloaded version would have been called instead of this one).
*/
assert( nVal>=1 );
if( nVal>6 ){
sqlite3_result_error(pContext,
"wrong number of arguments to function snippet()", -1);
return;
}
if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;
switch( nVal ){
case 6: nToken = sqlite3_value_int(apVal[5]);
/* no break */ deliberate_fall_through
case 5: iCol = sqlite3_value_int(apVal[4]);
/* no break */ deliberate_fall_through
case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
/* no break */ deliberate_fall_through
case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
/* no break */ deliberate_fall_through
case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
}
if( !zEllipsis || !zEnd || !zStart ){
sqlite3_result_error_nomem(pContext);
}else if( nToken==0 ){
sqlite3_result_text(pContext, "", -1, SQLITE_STATIC);
}else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
}
}
/*
** Implementation of the offsets() function for FTS3
#ifndef SQLITE_DISABLE_FTS3_UNICODE
|| sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode)
#endif
#ifdef SQLITE_ENABLE_ICU
|| (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu))
#endif
){
rc = SQLITE_NOMEM;
}
}
#ifdef SQLITE_TEST
if( rc==SQLITE_OK ){
rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash);
}
#endif
/* Create the virtual table wrapper around the hash-table and overload
** the four scalar functions. If this is successful, register the
** module with sqlite.
*/
if( SQLITE_OK==rc
&& SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer"))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
){
pHash->nRef++;
rc = sqlite3_create_module_v2(
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
);
if( rc==SQLITE_OK ){
pHash->nRef++;
rc = sqlite3_create_module_v2(
db, "fts4", &fts3Module, (void *)pHash, hashDestroy
);
}
if( rc==SQLITE_OK ){
pHash->nRef++;
rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy);
}
return rc;
}
/* An error has occurred. Delete the hash table and return the error code. */
assert( rc!=SQLITE_OK );
if( pHash ){
sqlite3Fts3HashClear(&pHash->hash);
sqlite3_free(pHash);
}
return rc;
}
/*
** Allocate an Fts3MultiSegReader for each token in the expression headed
** by pExpr.
**
** An Fts3SegReader object is a cursor that can seek or scan a range of
** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
** Fts3SegReader objects internally to provide an interface to seek or scan
** within the union of all segments of a b-tree. Hence the name.
**
** If the allocated Fts3MultiSegReader just seeks to a single entry in a
** segment b-tree (if the term is not a prefix or it is a prefix for which
** there exists prefix b-tree of the right length) then it may be traversed
** and merged incrementally. Otherwise, it has to be merged into an in-memory
** doclist and then traversed.
*/
static void fts3EvalAllocateReaders(
Fts3Cursor *pCsr, /* FTS cursor handle */
Fts3Expr *pExpr, /* Allocate readers for this expression */
int *pnToken, /* OUT: Total number of tokens in phrase. */
int *pnOr, /* OUT: Total number of OR nodes in expr. */
int *pRc /* IN/OUT: Error code */
){
if( pExpr && SQLITE_OK==*pRc ){
if( pExpr->eType==FTSQUERY_PHRASE ){
int i;
int nToken = pExpr->pPhrase->nToken;
*pnToken += nToken;
for(i=0; i<nToken; i++){
Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
int rc = fts3TermSegReaderCursor(pCsr,
pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
);
if( rc!=SQLITE_OK ){
*pRc = rc;
return;
}
}
assert( pExpr->pPhrase->iDoclistToken==0 );
pExpr->pPhrase->iDoclistToken = -1;
}else{
*pnOr += (pExpr->eType==FTSQUERY_OR);
fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc);
fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc);
}
}
}
/*
** Arguments pList/nList contain the doclist for token iToken of phrase p.
** It is merged into the main doclist stored in p->doclist.aAll/nAll.
**
** This function assumes that pList points to a buffer allocated using
** sqlite3_malloc(). This function takes responsibility for eventually
** freeing the buffer.
**
** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs.
*/
static int fts3EvalPhraseMergeToken(
Fts3Table *pTab, /* FTS Table pointer */
Fts3Phrase *p, /* Phrase to merge pList/nList into */
int iToken, /* Token pList/nList corresponds to */
char *pList, /* Pointer to doclist */
int nList /* Number of bytes in pList */
){
int rc = SQLITE_OK;
assert( iToken!=p->iDoclistToken );
if( pList==0 ){
sqlite3_free(p->doclist.aAll);
p->doclist.aAll = 0;
p->doclist.nAll = 0;
}
else if( p->iDoclistToken<0 ){
p->doclist.aAll = pList;
p->doclist.nAll = nList;
}
if( *pRc==SQLITE_OK
&& pExpr->eType==FTSQUERY_NEAR
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
sqlite3_int64 nTmp = 0; /* Bytes of temp space */
char *aTmp; /* Temp space for PoslistNearMerge() */
/* Allocate temporary working space. */
for(p=pExpr; p->pLeft; p=p->pLeft){
assert( p->pRight->pPhrase->doclist.nList>0 );
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
aTmp = sqlite3_malloc64(nTmp*2 + FTS3_VARINT_MAX);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
}else{
char *aPoslist = p->pPhrase->doclist.pList;
int nToken = p->pPhrase->nToken;
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
Fts3Phrase *pPhrase = p->pRight->pPhrase;
int nNear = p->nNear;
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
nToken = pExpr->pRight->pPhrase->nToken;
for(p=pExpr->pLeft; p && res; p=p->pLeft){
int nNear;
Fts3Phrase *pPhrase;
assert( p->pParent && p->pParent->pLeft==p );
nNear = p->pParent->nNear;
pPhrase = (
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
);
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
}
sqlite3_free(aTmp);
}
return res;
}
/*
** This function is a helper function for sqlite3Fts3EvalTestDeferred().
** Assuming no error occurs or has occurred, It returns non-zero if the
** expression passed as the second argument matches the row that pCsr
** currently points to, or zero if it does not.
**
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
** If an error occurs during execution of this function, *pRc is set to
** the appropriate SQLite error code. In this case the returned value is
** undefined.
*/
static int fts3EvalTestExpr(
Fts3Cursor *pCsr, /* FTS cursor handle */
Fts3Expr *pExpr, /* Expr to test. May or may not be root. */
int *pRc /* IN/OUT: Error code */
){
int bHit = 1; /* Return value */
if( *pRc==SQLITE_OK ){
switch( pExpr->eType ){
case FTSQUERY_NEAR:
case FTSQUERY_AND:
bHit = (
fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
&& fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
&& fts3EvalNearTest(pExpr, pRc)
);
/* If the NEAR expression does not match any rows, zero the doclist for
** all phrases involved in the NEAR. This is because the snippet(),
** offsets() and matchinfo() functions are not supposed to recognize
** any instances of phrases that are part of unmatched NEAR queries.
** For example if this expression:
**
** ... MATCH 'a OR (b NEAR c)'
**
** is matched against a row containing:
**
** 'a b d e'
**
** then any snippet() should ony highlight the "a" term, not the "b"
** (as "b" is part of a non-matching NEAR clause).
*/
if( bHit==0
&& pExpr->eType==FTSQUERY_NEAR
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
for(p=pExpr; p->pPhrase==0; p=p->pLeft){
if( p->pRight->iDocid==pCsr->iPrevId ){
fts3EvalInvalidatePoslist(p->pRight->pPhrase);
}
}
if( p->iDocid==pCsr->iPrevId ){
fts3EvalInvalidatePoslist(p->pPhrase);
}
}
break;
case FTSQUERY_OR: {
int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc);
int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc);
bHit = bHit1 || bHit2;
break;
}
case FTSQUERY_NOT:
bHit = (
fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc)
&& !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc)
);
break;
default: {
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( pCsr->pDeferred && (pExpr->bDeferred || (
pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList
))){
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pExpr->bDeferred ){
fts3EvalInvalidatePoslist(pPhrase);
}
*pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
bHit = (pPhrase->doclist.pList!=0);
pExpr->iDocid = pCsr->iPrevId;
}else
#endif
{
bHit = (
pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId
&& pExpr->pPhrase->doclist.nList>0
);
}
break;
}
}
}
return bHit;
}
/*
** This function is called as the second part of each xNext operation when
** iterating through the results of a full-text query. At this point the
** cursor points to a row that matches the query expression, with the
** following caveats:
**
** * Up until this point, "NEAR" operators in the expression have been
** treated as "AND".
**
** * Deferred tokens have not yet been considered.
**
** If *pRc is not SQLITE_OK when this function is called, it immediately
** returns 0. Otherwise, it tests whether or not after considering NEAR
** operators and deferred tokens the current row is still a match for the
** expression. It returns 1 if both of the following are true:
**
** 1. *pRc is SQLITE_OK when this function returns, and
**
** 2. After scanning the current FTS table row for the deferred tokens,
** it is determined that the row does *not* match the query.
**
** Or, if no error occurs and it seems the current row does match the FTS
** query, return 0.
*/
SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){
int rc = *pRc;
int bMiss = 0;
if( rc==SQLITE_OK ){
/* If there are one or more deferred tokens, load the current row into
** memory and scan it to determine the position list for each deferred
** token. Then, see if this row is really a match, considering deferred
** tokens and NEAR operators (neither of which were taken into account
** earlier, by fts3EvalNextRow()).
*/
if( pCsr->pDeferred ){
rc = fts3CursorSeek(0, pCsr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts3CacheDeferredDoclists(pCsr);
}
}
bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc));
/* Free the position-lists accumulated for each deferred token above. */
sqlite3Fts3FreeDeferredDoclists(pCsr);
*pRc = rc;
}
return (rc==SQLITE_OK && bMiss);
}
/*
** Advance to the next document that matches the FTS expression in
** Fts3Cursor.pExpr.
*/
static int fts3EvalNext(Fts3Cursor *pCsr){
int rc = SQLITE_OK; /* Return Code */
Fts3Expr *pExpr = pCsr->pExpr;
assert( pCsr->isEof==0 );
if( pExpr==0 ){
pCsr->isEof = 1;
}else{
do {
if( pCsr->isRequireSeek==0 ){
sqlite3_reset(pCsr->pStmt);
}
assert( sqlite3_data_count(pCsr->pStmt)==0 );
fts3EvalNextRow(pCsr, pExpr, &rc);
pCsr->isEof = pExpr->bEof;
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
pCsr->iPrevId = pExpr->iDocid;
}while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) );
}
/* Check if the cursor is past the end of the docid range specified
** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */
if( rc==SQLITE_OK && (
(pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid)
|| (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid)
)){
pCsr->isEof = 1;
}
return rc;
}
/*
** Restart iteration for expression pExpr so that the next call to
** fts3EvalNext() visits the first row. Do not allow incremental
** loading or merging of phrase doclists for this iteration.
**
** If *pRc is other than SQLITE_OK when this function is called, it is
** a no-op. If an error occurs within this function, *pRc is set to an
** SQLite error code before returning.
*/
static void fts3EvalRestart(
Fts3Cursor *pCsr,
Fts3Expr *pExpr,
int *pRc
){
if( pExpr && *pRc==SQLITE_OK ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pPhrase ){
fts3EvalInvalidatePoslist(pPhrase);
if( pPhrase->bIncr ){
int i;
for(i=0; i<pPhrase->nToken; i++){
Fts3PhraseToken *pToken = &pPhrase->aToken[i];
assert( pToken->pDeferred==0 );
if( pToken->pSegcsr ){
sqlite3Fts3MsrIncrRestart(pToken->pSegcsr);
}
}
*pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
}
pPhrase->doclist.pNextDocid = 0;
pPhrase->doclist.iDocid = 0;
pPhrase->pOrPoslist = 0;
}
pExpr->iDocid = 0;
pExpr->bEof = 0;
pExpr->bStart = 0;
fts3EvalRestart(pCsr, pExpr->pLeft, pRc);
fts3EvalRestart(pCsr, pExpr->pRight, pRc);
}
}
/*
** Expression node pExpr is an MSR phrase. This function restarts pExpr
** so that it is a regular phrase query, not an MSR. SQLITE_OK is returned
** if successful, or an SQLite error code otherwise.
*/
SQLITE_PRIVATE int sqlite3Fts3MsrCancel(Fts3Cursor *pCsr, Fts3Expr *pExpr){
int rc = SQLITE_OK;
if( pExpr->bEof==0 ){
i64 iDocid = pExpr->iDocid;
fts3EvalRestart(pCsr, pExpr, &rc);
while( rc==SQLITE_OK && pExpr->iDocid!=iDocid ){
fts3EvalNextRow(pCsr, pExpr, &rc);
if( pExpr->bEof ) rc = FTS_CORRUPT_VTAB;
}
}
return rc;
}
/*
** After allocating the Fts3Expr.aMI[] array for each phrase in the
** expression rooted at pExpr, the cursor iterates through all rows matched
** by pExpr, calling this function for each row. This function increments
** the values in Fts3Expr.aMI[] according to the position-list currently
** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
** expression nodes.
*/
static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){
if( pExpr ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pPhrase && pPhrase->doclist.pList ){
int iCol = 0;
char *p = pPhrase->doclist.pList;
do{
u8 c = 0;
int iCnt = 0;
while( 0xFE & (*p | c) ){
if( (c&0x80)==0 ) iCnt++;
c = *p++ & 0x80;
}
/* aMI[iCol*3 + 1] = Number of occurrences
** aMI[iCol*3 + 2] = Number of rows containing at least one instance
*/
pExpr->aMI[iCol*3 + 1] += iCnt;
pExpr->aMI[iCol*3 + 2] += (iCnt>0);
if( *p==0x00 ) break;
p++;
p += fts3GetVarint32(p, &iCol);
}while( iCol<nCol );
}
fts3EvalUpdateCounts(pExpr->pLeft, nCol);
fts3EvalUpdateCounts(pExpr->pRight, nCol);
}
}
/*
** This is an sqlite3Fts3ExprIterate() callback. If the Fts3Expr.aMI[] array
** has not yet been allocated, allocate and zero it. Otherwise, just zero
** it.
*/
static int fts3AllocateMSI(Fts3Expr *pExpr, int iPhrase, void *pCtx){
Fts3Table *pTab = (Fts3Table*)pCtx;
UNUSED_PARAMETER(iPhrase);
if( pExpr->aMI==0 ){
pExpr->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32));
if( pExpr->aMI==0 ) return SQLITE_NOMEM;
}
memset(pExpr->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
return SQLITE_OK;
}
/*
** Expression pExpr must be of type FTSQUERY_PHRASE.
**
** If it is not already allocated and populated, this function allocates and
** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part
** of a NEAR expression, then it also allocates and populates the same array
** for all other phrases that are part of the NEAR expression.
**
if( rc==SQLITE_OK && pCsr->isEof==0 ){
fts3EvalUpdateCounts(pRoot, pTab->nColumn);
}
}
pCsr->isEof = 0;
pCsr->iPrevId = iPrevId;
if( bEof ){
pRoot->bEof = bEof;
}else{
/* Caution: pRoot may iterate through docids in ascending or descending
** order. For this reason, even though it seems more defensive, the
** do loop can not be written:
**
** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
*/
fts3EvalRestart(pCsr, pRoot, &rc);
do {
fts3EvalNextRow(pCsr, pRoot, &rc);
assert_fts3_nc( pRoot->bEof==0 );
if( pRoot->bEof ) rc = FTS_CORRUPT_VTAB;
}while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
}
}
return rc;
}
/*
** This function is used by the matchinfo() module to query a phrase
** expression node for the following information:
**
** 1. The total number of occurrences of the phrase in each column of
** the FTS table (considering all rows), and
**
** 2. For each column, the number of rows in the table for which the
** column contains at least one instance of the phrase.
**
** If no error occurs, SQLITE_OK is returned and the values for each column
** written into the array aiOut as follows:
**
** aiOut[iCol*3 + 1] = Number of occurrences
** aiOut[iCol*3 + 2] = Number of rows containing at least one instance
**
** Caveats:
**
** * If a phrase consists entirely of deferred tokens, then all output
** values are set to the number of documents in the table. In other
** words we assume that very common tokens occur exactly once in each
** column of each row of the table.
**
** * If a phrase contains some deferred tokens (and some non-deferred
** tokens), count the potential occurrence identified by considering
** the non-deferred tokens instead of actual phrase occurrences.
**
** * If the phrase is part of a NEAR expression, then only phrase instances
** that meet the NEAR constraint are included in the counts.
*/
SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
Fts3Cursor *pCsr, /* FTS cursor handle */
Fts3Expr *pExpr, /* Phrase expression */
u32 *aiOut /* Array to write results into (see above) */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc = SQLITE_OK;
int iCol;
if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){
assert( pCsr->nDoc>0 );
for(iCol=0; iCol<pTab->nColumn; iCol++){
aiOut[iCol*3 + 1] = (u32)pCsr->nDoc;
aiOut[iCol*3 + 2] = (u32)pCsr->nDoc;
}
}else{
rc = fts3EvalGatherStats(pCsr, pExpr);
if( rc==SQLITE_OK ){
assert( pExpr->aMI );
for(iCol=0; iCol<pTab->nColumn; iCol++){
aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1];
aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2];
}
}
}
return rc;
}
/*
** The expression pExpr passed as the second argument to this function
** must be of type FTSQUERY_PHRASE.
**
** The returned value is either NULL or a pointer to a buffer containing
** a position-list indicating the occurrences of the phrase in column iCol
** of the current row.
**
** More specifically, the returned buffer contains 1 varint for each
** occurrence of the phrase in the column, stored using the normal (delta+2)
** compression and is terminated by either an 0x01 or 0x00 byte. For example,
** if the requested column contains "a b X c d X X" and the position-list
** for 'X' is requested, the buffer returned may contain:
**
** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00
**
** This function works regardless of whether or not the phrase is deferred,
** incremental, or neither.
*/
SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
Fts3Cursor *pCsr, /* FTS3 cursor object */
Fts3Expr *pExpr, /* Phrase to return doclist for */
int iCol, /* Column to return position list for */
char **ppOut /* OUT: Pointer to position list */
){
Fts3Phrase *pPhrase = pExpr->pPhrase;
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
char *pIter;
int iThis;
sqlite3_int64 iDocid;
/* If this phrase is applies specifically to some column other than
** column iCol, return a NULL pointer. */
*ppOut = 0;
assert( iCol>=0 && iCol<pTab->nColumn );
if( (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) ){
return SQLITE_OK;
}
iDocid = pExpr->iDocid;
pIter = pPhrase->doclist.pList;
if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
int rc = SQLITE_OK;
int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
int bOr = 0;
u8 bTreeEof = 0;
Fts3Expr *p; /* Used to iterate from pExpr to root */
Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */
Fts3Expr *pRun; /* Closest non-deferred ancestor of pNear */
int bMatch;
/* Check if this phrase descends from an OR expression node. If not,
** return NULL. Otherwise, the entry that corresponds to docid
** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
** tree that the node is part of has been marked as EOF, but the node
** itself is not EOF, then it may point to an earlier entry. */
pNear = pExpr;
for(p=pExpr->pParent; p; p=p->pParent){
if( p->eType==FTSQUERY_OR ) bOr = 1;
if( p->eType==FTSQUERY_NEAR ) pNear = p;
if( p->bEof ) bTreeEof = 1;
}
if( bOr==0 ) return SQLITE_OK;
pRun = pNear;
while( pRun->bDeferred ){
assert( pRun->pParent );
pRun = pRun->pParent;
}
/* This is the descendent of an OR node. In this case we cannot use
** an incremental phrase. Load the entire doclist for the phrase
** into memory in this case. */
if( pPhrase->bIncr ){
int bEofSave = pRun->bEof;
fts3EvalRestart(pCsr, pRun, &rc);
while( rc==SQLITE_OK && !pRun->bEof ){
fts3EvalNextRow(pCsr, pRun, &rc);
if( bEofSave==0 && pRun->iDocid==iDocid ) break;
}
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
if( rc==SQLITE_OK && pRun->bEof!=bEofSave ){
/*
** Return SQLITE_CORRUPT_VTAB.
*/
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3Fts3Corrupt(){
return SQLITE_CORRUPT_VTAB;
}
#endif
#if !defined(SQLITE_CORE)
/*
** Initialize API pointer table, if required.
*/
#ifdef _WIN32
__declspec(dllexport)
#endif
SQLITE_API int sqlite3_fts3_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
SQLITE_EXTENSION_INIT2(pApi)
return sqlite3Fts3Init(db);
}
#endif
#endif
/************** End of fts3.c ************************************************/
/************** Begin file fts3_aux.c ****************************************/
/*
** 2011 Jan 27
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
*/
/* #include "fts3Int.h" */
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/* #include <string.h> */
/* #include <assert.h> */
typedef struct Fts3auxTable Fts3auxTable;
typedef struct Fts3auxCursor Fts3auxCursor;
struct Fts3auxTable {
sqlite3_vtab base; /* Base class used by SQLite core */
Fts3Table *pFts3Tab;
};
struct Fts3auxCursor {
sqlite3_vtab_cursor base; /* Base class used by SQLite core */
Fts3MultiSegReader csr; /* Must be right after "base" */
Fts3SegFilter filter;
char *zStop;
int nStop; /* Byte-length of string zStop */
int iLangid; /* Language id to query */
int isEof; /* True if cursor is at EOF */
sqlite3_int64 iRowid; /* Current rowid */
int iCol; /* Current value of 'col' column */
int nStat; /* Size of aStat[] array */
struct Fts3auxColstats {
sqlite3_int64 nDoc; /* 'documents' values for current csr row */
sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */
} *aStat;
};
/*
** Schema of the terms table.
*/
#define FTS3_AUX_SCHEMA \
"CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)"
/*
** This function does all the work for both the xConnect and xCreate methods.
** These tables have no persistent representation of their own, so xConnect
** and xCreate are identical operations.
*/
static int fts3auxConnectMethod(
sqlite3 *db, /* Database connection */
void *pUnused, /* Unused */
int argc, /* Number of elements in argv array */
const char * const *argv, /* xCreate/xConnect argument array */
sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
char **pzErr /* OUT: sqlite3_malloc'd error message */
){
char const *zDb; /* Name of database (e.g. "main") */
char const *zFts3; /* Name of fts3 table */
int nDb; /* Result of strlen(zDb) */
int nFts3; /* Result of strlen(zFts3) */
sqlite3_int64 nByte; /* Bytes of space to allocate here */
int rc; /* value returned by declare_vtab() */
Fts3auxTable *p; /* Virtual table object to return */
UNUSED_PARAMETER(pUnused);
/* The user should invoke this in one of two forms:
**
** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table);
** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table);
*/
if( argc!=4 && argc!=5 ) goto bad_args;
zDb = argv[1];
nDb = (int)strlen(zDb);
if( argc==5 ){
if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){
zDb = argv[3];
nDb = (int)strlen(zDb);
zFts3 = argv[4];
}else{
goto bad_args;
}
}else{
zFts3 = argv[3];
}
nFts3 = (int)strlen(zFts3);
int iLangid = -1;
int iNext = 1; /* Next free argvIndex value */
UNUSED_PARAMETER(pVTab);
/* This vtab delivers always results in "ORDER BY term ASC" order. */
if( pInfo->nOrderBy==1
&& pInfo->aOrderBy[0].iColumn==0
&& pInfo->aOrderBy[0].desc==0
){
pInfo->orderByConsumed = 1;
}
/* Search for equality and range constraints on the "term" column.
** And equality constraints on the hidden "languageid" column. */
for(i=0; i<pInfo->nConstraint; i++){
if( pInfo->aConstraint[i].usable ){
int op = pInfo->aConstraint[i].op;
int iCol = pInfo->aConstraint[i].iColumn;
if( iCol==0 ){
if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
}
if( iCol==4 ){
if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i;
}
}
}
if( iEq>=0 ){
pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
pInfo->aConstraintUsage[iEq].argvIndex = iNext++;
pInfo->estimatedCost = 5;
}else{
pInfo->idxNum = 0;
pInfo->estimatedCost = 20000;
if( iGe>=0 ){
pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
pInfo->aConstraintUsage[iGe].argvIndex = iNext++;
pInfo->estimatedCost /= 2;
}
if( iLe>=0 ){
pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
pInfo->aConstraintUsage[iLe].argvIndex = iNext++;
pInfo->estimatedCost /= 2;
}
}
if( iLangid>=0 ){
pInfo->aConstraintUsage[iLangid].argvIndex = iNext++;
pInfo->estimatedCost--;
}
return SQLITE_OK;
}
/*
** xOpen - Open a cursor.
*/
static int fts3auxOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
Fts3auxCursor *pCsr; /* Pointer to cursor object to return */
UNUSED_PARAMETER(pVTab);
pCsr = (Fts3auxCursor *)sqlite3_malloc(sizeof(Fts3auxCursor));
if( !pCsr ) return SQLITE_NOMEM;
memset(pCsr, 0, sizeof(Fts3auxCursor));
*ppCsr = (sqlite3_vtab_cursor *)pCsr;
return SQLITE_OK;
}
/*
** xClose - Close a cursor.
*/
static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){
Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
sqlite3Fts3SegmentsClose(pFts3);
sqlite3Fts3SegReaderFinish(&pCsr->csr);
sqlite3_free((void *)pCsr->filter.zTerm);
sqlite3_free(pCsr->zStop);
sqlite3_free(pCsr->aStat);
sqlite3_free(pCsr);
return SQLITE_OK;
}
static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
if( nSize>pCsr->nStat ){
struct Fts3auxColstats *aNew;
aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat,
sizeof(struct Fts3auxColstats) * nSize
);
if( aNew==0 ) return SQLITE_NOMEM;
memset(&aNew[pCsr->nStat], 0,
sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat)
);
pCsr->aStat = aNew;
pCsr->nStat = nSize;
}
return SQLITE_OK;
}
/*
** xNext - Advance the cursor to the next row, if any.
*/
static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){
Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
int rc;
/* Increment our pretend rowid value. */
pCsr->iRowid++;
for(pCsr->iCol++; pCsr->iCol<pCsr->nStat; pCsr->iCol++){
if( pCsr->aStat[pCsr->iCol].nDoc>0 ) return SQLITE_OK;
}
rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr);
if( rc==SQLITE_ROW ){
int i = 0;
int nDoclist = pCsr->csr.nDoclist;
char *aDoclist = pCsr->csr.aDoclist;
int iCol;
int eState = 0;
if( pCsr->zStop ){
int n = (pCsr->nStop<pCsr->csr.nTerm) ? pCsr->nStop : pCsr->csr.nTerm;
int mc = memcmp(pCsr->zStop, pCsr->csr.zTerm, n);
if( mc<0 || (mc==0 && pCsr->csr.nTerm>pCsr->nStop) ){
pCsr->isEof = 1;
return SQLITE_OK;
}
}
if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
iCol = 0;
rc = SQLITE_OK;
while( i<nDoclist ){
sqlite3_int64 v = 0;
i += sqlite3Fts3GetVarint(&aDoclist[i], &v);
switch( eState ){
/* State 0. In this state the integer just read was a docid. */
case 0:
pCsr->aStat[0].nDoc++;
eState = 1;
iCol = 0;
break;
/* State 1. In this state we are expecting either a 1, indicating
** that the following integer will be a column number, or the
** start of a position list for column 0.
**
** The only difference between state 1 and state 2 is that if the
** integer encountered in state 1 is not 0 or 1, then we need to
** increment the column 0 "nDoc" count for this term.
*/
case 1:
assert( iCol==0 );
if( v>1 ){
pCsr->aStat[1].nDoc++;
}
eState = 2;
/* fall through */
case 2:
if( v==0 ){ /* 0x00. Next integer will be a docid. */
eState = 0;
}else if( v==1 ){ /* 0x01. Next integer will be a column number. */
eState = 3;
}else{ /* 2 or greater. A position. */
pCsr->aStat[iCol+1].nOcc++;
pCsr->aStat[0].nOcc++;
}
break;
/* State 3. The integer just read is a column number. */
default: assert( eState==3 );
iCol = (int)v;
if( iCol<1 ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
pCsr->aStat[iCol+1].nDoc++;
eState = 2;
break;
}
}
pCsr->iCol = 0;
}else{
pCsr->isEof = 1;
}
return rc;
}
/*
** xFilter - Initialize a cursor to point at the start of its data.
*/
static int fts3auxFilterMethod(
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
int idxNum, /* Strategy index */
const char *idxStr, /* Unused */
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
int rc;
int isScan = 0;
int iLangVal = 0; /* Language id to query */
int iEq = -1; /* Index of term=? value in apVal */
int iGe = -1; /* Index of term>=? value in apVal */
int iLe = -1; /* Index of term<=? value in apVal */
int iLangid = -1; /* Index of languageid=? value in apVal */
int iNext = 0;
UNUSED_PARAMETER(nVal);
UNUSED_PARAMETER(idxStr);
assert( idxStr==0 );
assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0
|| idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
|| idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
);
if( idxNum==FTS4AUX_EQ_CONSTRAINT ){
iEq = iNext++;
}else{
isScan = 1;
if( idxNum & FTS4AUX_GE_CONSTRAINT ){
iGe = iNext++;
}
if( idxNum & FTS4AUX_LE_CONSTRAINT ){
iLe = iNext++;
}
}
if( iNext<nVal ){
iLangid = iNext++;
}
/* In case this cursor is being reused, close and zero it. */
testcase(pCsr->filter.zTerm);
sqlite3Fts3SegReaderFinish(&pCsr->csr);
sqlite3_free((void *)pCsr->filter.zTerm);
sqlite3_free(pCsr->aStat);
sqlite3_free(pCsr->zStop);
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
if( iEq>=0 || iGe>=0 ){
const unsigned char *zStr = sqlite3_value_text(apVal[0]);
assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
if( zStr ){
pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm);
}
}
if( iLe>=0 ){
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
pCsr->nStop = (int)strlen(pCsr->zStop);
}
if( iLangid>=0 ){
iLangVal = sqlite3_value_int(apVal[iLangid]);
/* If the user specified a negative value for the languageid, use zero
** instead. This works, as the "languageid=?" constraint will also
** be tested by the VDBE layer. The test will always be false (since
** this module will not return a row with a negative languageid), and
** so the overall query will return zero rows. */
if( iLangVal<0 ) iLangVal = 0;
}
pCsr->iLangid = iLangVal;
rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL,
pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
);
if( rc==SQLITE_OK ){
rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter);
}
if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor);
return rc;
}
/*
** xEof - Return true if the cursor is at EOF, or false otherwise.
*/
static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){
Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
return pCsr->isEof;
}
/*
** xColumn - Return a column value.
*/
static int fts3auxColumnMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
assert( p->isEof==0 );
switch( iCol ){
case 0: /* term */
sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
break;
case 1: /* col */
if( p->iCol ){
sqlite3_result_int(pCtx, p->iCol-1);
}else{
sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC);
}
break;
case 2: /* documents */
sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc);
break;
case 3: /* occurrences */
sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc);
break;
default: /* languageid */
assert( iCol==4 );
sqlite3_result_int(pCtx, p->iLangid);
break;
}
return SQLITE_OK;
}
/*
** xRowid - Return the current rowid for the cursor.
*/
static int fts3auxRowidMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
sqlite_int64 *pRowid /* OUT: Rowid value */
){
Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
*pRowid = pCsr->iRowid;
return SQLITE_OK;
}
/*
** Register the fts3aux module with database connection db. Return SQLITE_OK
** if successful or an error code if sqlite3_create_module() fails.
*/
SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){
static const sqlite3_module fts3aux_module = {
0, /* iVersion */
fts3auxConnectMethod, /* xCreate */
fts3auxConnectMethod, /* xConnect */
fts3auxBestIndexMethod, /* xBestIndex */
fts3auxDisconnectMethod, /* xDisconnect */
fts3auxDisconnectMethod, /* xDestroy */
fts3auxOpenMethod, /* xOpen */
fts3auxCloseMethod, /* xClose */
fts3auxFilterMethod, /* xFilter */
fts3auxNextMethod, /* xNext */
fts3auxEofMethod, /* xEof */
fts3auxColumnMethod, /* xColumn */
fts3auxRowidMethod, /* xRowid */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindFunction */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
int rc; /* Return code */
rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0);
return rc;
}
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
/************** End of fts3_aux.c ********************************************/
/************** Begin file fts3_expr.c ***************************************/
/*
** 2008 Nov 28
**
** 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 span for NEAR operators.
*/
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
/* #include <string.h> */
/* #include <assert.h> */
/*
** isNot:
** This variable is used by function getNextNode(). When getNextNode() is
** called, it sets ParseContext.isNot to true if the 'next node' is a
** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to
** zero.
*/
typedef struct ParseContext ParseContext;
struct ParseContext {
sqlite3_tokenizer *pTokenizer; /* Tokenizer module */
int iLangid; /* Language id used with tokenizer */
const char **azCol; /* Array of column names for fts3 table */
int bFts4; /* True to allow FTS4-only syntax */
int nCol; /* Number of entries in azCol[] */
int iDefaultCol; /* Default column to query */
int isNot; /* True if getNextNode() sees a unary - */
sqlite3_context *pCtx; /* Write error message here */
int nNest; /* Number of nested brackets */
};
/*
** This function is equivalent to the standard isspace() function.
**
** The standard isspace() can be awkward to use safely, because although it
** is defined to accept an argument of type int, its behavior when passed
** an integer that falls outside of the range of the unsigned char type
** is undefined (and sometimes, "undefined" means segfault). This wrapper
** is defined to accept an argument of type char, and always returns 0 for
** any values that fall outside of the range of the unsigned char type (i.e.
** negative values).
*/
static int fts3isspace(char c){
return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}
/*
** Allocate nByte bytes of memory using sqlite3_malloc(). If successful,
** zero the memory before returning a pointer to it. If unsuccessful,
** return NULL.
*/
SQLITE_PRIVATE void *sqlite3Fts3MallocZero(sqlite3_int64 nByte){
void *pRet = sqlite3_malloc64(nByte);
if( pRet ) memset(pRet, 0, nByte);
return pRet;
}
SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(
sqlite3_tokenizer *pTokenizer,
int iLangid,
const char *z,
int n,
sqlite3_tokenizer_cursor **ppCsr
){
sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
sqlite3_tokenizer_cursor *pCsr = 0;
int rc;
rc = pModule->xOpen(pTokenizer, z, n, &pCsr);
assert( rc==SQLITE_OK || pCsr==0 );
if( rc==SQLITE_OK ){
pCsr->pTokenizer = pTokenizer;
if( pModule->iVersion>=1 ){
rc = pModule->xLanguageid(pCsr, iLangid);
if( rc!=SQLITE_OK ){
pModule->xClose(pCsr);
pCsr = 0;
}
}
}
*ppCsr = pCsr;
return rc;
}
/*
** Function getNextNode(), which is called by fts3ExprParse(), may itself
** call fts3ExprParse(). So this forward declaration is required.
*/
static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
/*
** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis
** is defined, search for '(' and ')' as well. Return the index of the first
** such character in the buffer. If there is no such character, return -1.
*/
static int findBarredChar(const char *z, int n){
int ii;
for(ii=0; ii<n; ii++){
if( (z[ii]=='"')
|| (sqlite3_fts3_enable_parentheses && (z[ii]=='(' || z[ii]==')'))
){
return ii;
}
}
return -1;
}
/*
** Extract the next token from buffer z (length n) using the tokenizer
** and other information (column names etc.) in pParse. Create an Fts3Expr
** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
** single token and set *ppExpr to point to it. If the end of the buffer is
** reached before a token is found, set *ppExpr to zero. It is the
** responsibility of the caller to eventually deallocate the allocated
** Fts3Expr structure (if any) by passing it to sqlite3_free().
**
** Return SQLITE_OK if successful, or SQLITE_NOMEM if a memory allocation
** fails.
*/
static int getNextToken(
ParseContext *pParse, /* fts3 query parse context */
int iCol, /* Value for Fts3Phrase.iColumn */
const char *z, int n, /* Input string */
Fts3Expr **ppExpr, /* OUT: expression */
int *pnConsumed /* OUT: Number of bytes consumed */
){
sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
int rc;
sqlite3_tokenizer_cursor *pCursor;
Fts3Expr *pRet = 0;
*pnConsumed = n;
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
sqlite3_int64 nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
/* Check that this tokenization did not gobble up any " characters. Or,
** if enable_parenthesis is true, that it did not gobble up any
** open or close parenthesis characters either. If it did, call
** getNextToken() again, but pass only that part of the input buffer
** up to the first such character. */
int iBarred = findBarredChar(z, iEnd);
if( iBarred>=0 ){
pModule->xClose(pCursor);
return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed);
}
nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken;
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
if( !pRet ){
rc = SQLITE_NOMEM;
}else{
pRet->eType = FTSQUERY_PHRASE;
pRet->pPhrase = (Fts3Phrase *)&pRet[1];
pRet->pPhrase->nToken = 1;
pRet->pPhrase->iColumn = iCol;
pRet->pPhrase->aToken[0].n = nToken;
pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1];
memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
if( iEnd<n && z[iEnd]=='*' ){
pRet->pPhrase->aToken[0].isPrefix = 1;
iEnd++;
}
while( 1 ){
if( !sqlite3_fts3_enable_parentheses
&& iStart>0 && z[iStart-1]=='-'
){
pParse->isNot = 1;
iStart--;
}else if( pParse->bFts4 && iStart>0 && z[iStart-1]=='^' ){
pRet->pPhrase->aToken[0].bFirst = 1;
iStart--;
}else{
break;
}
}
}
*pnConsumed = iEnd;
}else if( n && rc==SQLITE_DONE ){
int iBarred = findBarredChar(z, n);
if( iBarred>=0 ){
*pnConsumed = iBarred;
}
rc = SQLITE_OK;
}
pModule->xClose(pCursor);
}
*ppExpr = pRet;
return rc;
}
/*
** Enlarge a memory allocation. If an out-of-memory allocation occurs,
** then free the old allocation.
*/
static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){
void *pRet = sqlite3_realloc64(pOrig, nNew);
if( !pRet ){
sqlite3_free(pOrig);
}
return pRet;
}
/*
** Buffer zInput, length nInput, contains the contents of a quoted string
** that appeared as part of an fts3 query expression. Neither quote character
** is included in the buffer. This function attempts to tokenize the entire
** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE
** containing the results.
**
** If successful, SQLITE_OK is returned and *ppExpr set to point at the
** allocated Fts3Expr structure. Otherwise, either SQLITE_NOMEM (out of memory
** error) or SQLITE_ERROR (tokenization error) is returned and *ppExpr set
** to 0.
*/
static int getNextString(
ParseContext *pParse, /* fts3 query parse context */
const char *zInput, int nInput, /* Input string */
Fts3Expr **ppExpr /* OUT: expression */
){
sqlite3_tokenizer *pTokenizer = pParse->pTokenizer;
sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
int rc;
Fts3Expr *p = 0;
sqlite3_tokenizer_cursor *pCursor = 0;
char *zTemp = 0;
i64 nTemp = 0;
const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1);
int nToken = 0;
/* The final Fts3Expr data structure, including the Fts3Phrase,
** Fts3PhraseToken structures token buffers are all stored as a single
** allocation so that the expression can be freed with a single call to
** sqlite3_free(). Setting this up requires a two pass approach.
**
** The first pass, in the block below, uses a tokenizer cursor to iterate
** through the tokens in the expression. This pass uses fts3ReallocOrFree()
** to assemble data in two dynamic buffers:
**
** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase
** structure, followed by the array of Fts3PhraseToken
** structures. This pass only populates the Fts3PhraseToken array.
**
** Buffer zTemp: Contains copies of all tokens.
**
** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below,
** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase
** structures.
*/
rc = sqlite3Fts3OpenTokenizer(
pTokenizer, pParse->iLangid, zInput, nInput, &pCursor);
if( rc==SQLITE_OK ){
int ii;
for(ii=0; rc==SQLITE_OK; ii++){
const char *zByte;
int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0;
rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
if( rc==SQLITE_OK ){
Fts3PhraseToken *pToken;
p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
if( !zTemp || !p ){
rc = SQLITE_NOMEM;
goto getnextstring_out;
}
assert( nToken==ii );
pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
memset(pToken, 0, sizeof(Fts3PhraseToken));
memcpy(&zTemp[nTemp], zByte, nByte);
nTemp += nByte;
pToken->n = nByte;
pToken->isPrefix = (iEnd<nInput && zInput[iEnd]=='*');
pToken->bFirst = (iBegin>0 && zInput[iBegin-1]=='^');
nToken = ii+1;
}
}
}
if( rc==SQLITE_DONE ){
int jj;
char *zBuf = 0;
p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
if( !p ){
rc = SQLITE_NOMEM;
goto getnextstring_out;
}
memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
p->eType = FTSQUERY_PHRASE;
p->pPhrase = (Fts3Phrase *)&p[1];
p->pPhrase->iColumn = pParse->iDefaultCol;
p->pPhrase->nToken = nToken;
memcpy((void*)new_elem->pKey, pKey, nKey);
}else{
new_elem->pKey = (void*)pKey;
}
new_elem->nKey = nKey;
pH->count++;
assert( pH->htsize>0 );
assert( (pH->htsize & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
fts3HashInsertElement(pH, &pH->ht[h], new_elem);
new_elem->data = data;
return 0;
}
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
/************** End of fts3_hash.c *******************************************/
/************** Begin file fts3_porter.c *************************************/
/*
** 2006 September 30
**
** 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.
**
*************************************************************************
** Implementation of the full-text-search tokenizer that implements
** a Porter stemmer.
*/
/*
** The code in this file is only compiled if:
**
** * The FTS3 module is being built as an extension
** (in which case SQLITE_CORE is not defined), or
**
** * The FTS3 module is being built into the core of
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
/* #include "fts3Int.h" */
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stdio.h> */
/* #include <string.h> */
/* #include "fts3_tokenizer.h" */
/*
** Class derived from sqlite3_tokenizer
*/
typedef struct porter_tokenizer {
sqlite3_tokenizer base; /* Base class */
} porter_tokenizer;
/*
** Class derived from sqlite3_tokenizer_cursor
*/
typedef struct porter_tokenizer_cursor {
sqlite3_tokenizer_cursor base;
const char *zInput; /* input we are tokenizing */
int nInput; /* size of the input */
int iOffset; /* current position in zInput */
int iToken; /* index of next token to be returned */
char *zToken; /* storage for current token */
int nAllocated; /* space allocated to zToken buffer */
} porter_tokenizer_cursor;
/*
** Create a new tokenizer instance.
*/
static int porterCreate(
int argc, const char * const *argv,
sqlite3_tokenizer **ppTokenizer
){
porter_tokenizer *t;
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t));
if( t==NULL ) return SQLITE_NOMEM;
memset(t, 0, sizeof(*t));
*ppTokenizer = &t->base;
return SQLITE_OK;
}
/*
** Destroy a tokenizer
*/
static int porterDestroy(sqlite3_tokenizer *pTokenizer){
sqlite3_free(pTokenizer);
return SQLITE_OK;
}
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is zInput[0..nInput-1]. A cursor
** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int porterOpen(
sqlite3_tokenizer *pTokenizer, /* The tokenizer */
const char *zInput, int nInput, /* String to be tokenized */
sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
){
porter_tokenizer_cursor *c;
UNUSED_PARAMETER(pTokenizer);
c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
if( c==NULL ) return SQLITE_NOMEM;
c->zInput = zInput;
if( zInput==0 ){
c->nInput = 0;
}else if( nInput<0 ){
c->nInput = (int)strlen(zInput);
}else{
c->nInput = nInput;
}
c->iOffset = 0; /* start tokenizing at the beginning */
c->iToken = 0;
c->zToken = NULL; /* no space allocated, yet. */
c->nAllocated = 0;
*ppCursor = &c->base;
return SQLITE_OK;
}
/*
** Close a tokenization cursor previously opened by a call to
** porterOpen() above.
*/
static int porterClose(sqlite3_tokenizer_cursor *pCursor){
porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
sqlite3_free(c->zToken);
sqlite3_free(c);
return SQLITE_OK;
}
/*
** Vowel or consonant
*/
static const char cType[] = {
0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
1, 1, 1, 2, 1
};
/*
** isConsonant() and isVowel() determine if their first character in
** the string they point to is a consonant or a vowel, according
** to Porter ruls.
**
** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
** 'Y' is a consonant unless it follows another consonant,
** in which case it is a vowel.
**
** In these routine, the letters are in reverse order. So the 'y' rule
** is that 'y' is a consonant unless it is followed by another
** consonent.
*/
static int isVowel(const char*);
static int isConsonant(const char *z){
int j;
char x = *z;
if( x==0 ) return 0;
assert( x>='a' && x<='z' );
j = cType[x-'a'];
if( j<2 ) return j;
return z[1]==0 || isVowel(z + 1);
}
static int isVowel(const char *z){
int j;
char x = *z;
if( x==0 ) return 0;
assert( x>='a' && x<='z' );
j = cType[x-'a'];
if( j<2 ) return 1-j;
return isConsonant(z + 1);
}
/*
** Let any sequence of one or more vowels be represented by V and let
** C be sequence of one or more consonants. Then every word can be
** represented as:
**
** [C] (VC){m} [V]
**
** In prose: A word is an optional consonant followed by zero or
** vowel-consonant pairs followed by an optional vowel. "m" is the
** number of vowel consonant pairs. This routine computes the value
** of m for the first i bytes of a word.
**
** Return true if the m-value for z is 1 or more. In other words,
** return true if z contains at least one vowel that is followed
** by a consonant.
break;
case 't':
if( !stem(&z, "eta", "", m_gt_1) ){
stem(&z, "iti", "", m_gt_1);
}
break;
case 'u':
if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
z += 3;
}
break;
case 'v':
case 'z':
if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){
z += 3;
}
break;
}
/* Step 5a */
if( z[0]=='e' ){
if( m_gt_1(z+1) ){
z++;
}else if( m_eq_1(z+1) && !star_oh(z+1) ){
z++;
}
}
/* Step 5b */
if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){
z++;
}
/* z[] is now the stemmed word in reverse order. Flip it back
** around into forward order and return.
*/
*pnOut = i = (int)strlen(z);
zOut[i] = 0;
while( *z ){
zOut[--i] = *(z++);
}
}
/*
** Characters that can be part of a token. We assume any character
** whose value is greater than 0x80 (any UTF character) can be
** part of a token. In other words, delimiters all must have
** values of 0x7f or lower.
*/
static const char porterIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
};
#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30]))
/*
** Extract the next token from a tokenization cursor. The cursor must
** have been opened by a prior call to porterOpen().
*/
static int porterNext(
sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */
const char **pzToken, /* OUT: *pzToken is the token text */
int *pnBytes, /* OUT: Number of bytes in token */
int *piStartOffset, /* OUT: Starting offset of token */
int *piEndOffset, /* OUT: Ending offset of token */
int *piPosition /* OUT: Position integer of token */
){
porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
const char *z = c->zInput;
while( c->iOffset<c->nInput ){
int iStartOffset, ch;
/* Scan past delimiter characters */
while( c->iOffset<c->nInput && isDelim(z[c->iOffset]) ){
c->iOffset++;
}
/* Count non-delimiter characters. */
iStartOffset = c->iOffset;
while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
c->iOffset++;
}
if( c->iOffset>iStartOffset ){
int n = c->iOffset-iStartOffset;
if( n>c->nAllocated ){
char *pNew;
c->nAllocated = n+20;
pNew = sqlite3_realloc64(c->zToken, c->nAllocated);
if( !pNew ) return SQLITE_NOMEM;
c->zToken = pNew;
}
porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
*pzToken = c->zToken;
*piStartOffset = iStartOffset;
*piEndOffset = c->iOffset;
*piPosition = c->iToken++;
return SQLITE_OK;
}
}
return SQLITE_DONE;
}
/*
** The set of routines that implement the porter-stemmer tokenizer
*/
static const sqlite3_tokenizer_module porterTokenizerModule = {
0,
porterCreate,
porterDestroy,
porterOpen,
porterClose,
porterNext,
0
};
/*
** Allocate a new porter tokenizer. Return a pointer to the new
** tokenizer in *ppModule
*/
SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(
sqlite3_tokenizer_module const**ppModule
){
*ppModule = &porterTokenizerModule;
}
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
}
aArg = aNew;
aArg[iArg++] = z;
z[n] = '\0';
sqlite3Fts3Dequote(z);
z = &z[n+1];
}
rc = m->xCreate(iArg, aArg, ppTok);
assert( rc!=SQLITE_OK || *ppTok );
if( rc!=SQLITE_OK ){
sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer");
}else{
(*ppTok)->pModule = m;
}
sqlite3_free((void *)aArg);
}
sqlite3_free(zCopy);
return rc;
}
#ifdef SQLITE_TEST
#include "tclsqlite.h"
/* #include <string.h> */
/*
** Implementation of a special SQL scalar function for testing tokenizers
** designed to be used in concert with the Tcl testing framework. This
** function must be called with two or more arguments:
**
** SELECT <function-name>(<key-name>, ..., <input-string>);
**
** where <function-name> is the name passed as the second argument
** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer')
** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test').
**
** The return value is a string that may be interpreted as a Tcl
** list. For each token in the <input-string>, three elements are
** added to the returned list. The first is the token position, the
** second is the token text (folded, stemmed, etc.) and the third is the
** substring of <input-string> associated with the token. For example,
** using the built-in "simple" tokenizer:
**
** SELECT fts_tokenizer_test('simple', 'I don't see how');
**
** will return the string:
**
** "{0 i I 1 dont don't 2 see see 3 how how}"
**
*/
static void testFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Fts3Hash *pHash;
sqlite3_tokenizer_module *p;
sqlite3_tokenizer *pTokenizer = 0;
sqlite3_tokenizer_cursor *pCsr = 0;
const char *zErr = 0;
const char *zName;
int nName;
const char *zInput;
int nInput;
const char *azArg[64];
const char *zToken;
int nToken = 0;
int iStart = 0;
int iEnd = 0;
int iPos = 0;
int i;
Tcl_Obj *pRet;
if( argc<2 ){
sqlite3_result_error(context, "insufficient arguments", -1);
return;
}
nName = sqlite3_value_bytes(argv[0]);
zName = (const char *)sqlite3_value_text(argv[0]);
nInput = sqlite3_value_bytes(argv[argc-1]);
zInput = (const char *)sqlite3_value_text(argv[argc-1]);
pHash = (Fts3Hash *)sqlite3_user_data(context);
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
if( !p ){
char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName);
sqlite3_result_error(context, zErr2, -1);
sqlite3_free(zErr2);
return;
}
pRet = Tcl_NewObj();
Tcl_IncrRefCount(pRet);
for(i=1; i<argc-1; i++){
azArg[i-1] = (const char *)sqlite3_value_text(argv[i]);
}
if( SQLITE_OK!=p->xCreate(argc-2, azArg, &pTokenizer) ){
zErr = "error in xCreate()";
goto finish;
}
pTokenizer->pModule = p;
if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){
zErr = "error in xOpen()";
goto finish;
}
while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){
Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken));
zToken = &zInput[iStart];
#ifdef SQLITE_TEST
if( SQLITE_OK==rc ){
rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0);
}
if( SQLITE_OK==rc ){
rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0);
}
#endif
#ifdef SQLITE_TEST
sqlite3_free(zTest);
sqlite3_free(zTest2);
#endif
return rc;
}
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
/************** End of fts3_tokenizer.c **************************************/
/************** Begin file fts3_tokenizer1.c *********************************/
/*
** 2006 Oct 10
**
** 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.
**
******************************************************************************
**
** Implementation of the "simple" full-text-search tokenizer.
*/
/*
** The code in this file is only compiled if:
**
** * The FTS3 module is being built as an extension
** (in which case SQLITE_CORE is not defined), or
**
** * The FTS3 module is being built into the core of
** SQLite (in which case SQLITE_ENABLE_FTS3 is defined).
*/
/* #include "fts3Int.h" */
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stdio.h> */
/* #include <string.h> */
/* #include "fts3_tokenizer.h" */
typedef struct simple_tokenizer {
sqlite3_tokenizer base;
char delim[128]; /* flag ASCII delimiters */
} simple_tokenizer;
typedef struct simple_tokenizer_cursor {
sqlite3_tokenizer_cursor base;
const char *pInput; /* input we are tokenizing */
int nBytes; /* size of the input */
int iOffset; /* current position in pInput */
int iToken; /* index of next token to be returned */
char *pToken; /* storage for current token */
int nTokenAllocated; /* space allocated to zToken buffer */
} simple_tokenizer_cursor;
static int simpleDelim(simple_tokenizer *t, unsigned char c){
return c<0x80 && t->delim[c];
}
static int fts3_isalnum(int x){
return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z');
}
/*
** Create a new tokenizer instance.
*/
static int simpleCreate(
int argc, const char * const *argv,
sqlite3_tokenizer **ppTokenizer
){
simple_tokenizer *t;
t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t));
if( t==NULL ) return SQLITE_NOMEM;
memset(t, 0, sizeof(*t));
/* TODO(shess) Delimiters need to remain the same from run to run,
** else we need to reindex. One solution would be a meta-table to
** track such information in the database, then we'd only want this
** information on the initial create.
*/
if( argc>1 ){
int i, n = (int)strlen(argv[1]);
for(i=0; i<n; i++){
unsigned char ch = argv[1][i];
/* We explicitly don't support UTF-8 delimiters for now. */
if( ch>=0x80 ){
sqlite3_free(t);
return SQLITE_ERROR;
}
t->delim[ch] = 1;
}
} else {
/* Mark non-alphanumeric ASCII characters as delimiters */
int i;
for(i=1; i<0x80; i++){
t->delim[i] = !fts3_isalnum(i) ? -1 : 0;
}
}
*ppTokenizer = &t->base;
return SQLITE_OK;
}
/*
** Destroy a tokenizer
*/
static int simpleDestroy(sqlite3_tokenizer *pTokenizer){
sqlite3_free(pTokenizer);
return SQLITE_OK;
}
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is pInput[0..nBytes-1]. A cursor
** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int simpleOpen(
sqlite3_tokenizer *pTokenizer, /* The tokenizer */
const char *pInput, int nBytes, /* String to be tokenized */
sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
){
simple_tokenizer_cursor *c;
UNUSED_PARAMETER(pTokenizer);
c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
if( c==NULL ) return SQLITE_NOMEM;
c->pInput = pInput;
if( pInput==0 ){
c->nBytes = 0;
}else if( nBytes<0 ){
c->nBytes = (int)strlen(pInput);
}else{
c->nBytes = nBytes;
}
c->iOffset = 0; /* start tokenizing at the beginning */
c->iToken = 0;
c->pToken = NULL; /* no space allocated, yet. */
c->nTokenAllocated = 0;
*ppCursor = &c->base;
return SQLITE_OK;
}
/*
** Close a tokenization cursor previously opened by a call to
** simpleOpen() above.
*/
static int simpleClose(sqlite3_tokenizer_cursor *pCursor){
simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
sqlite3_free(c->pToken);
sqlite3_free(c);
return SQLITE_OK;
}
/*
** Extract the next token from a tokenization cursor. The cursor must
** have been opened by a prior call to simpleOpen().
*/
static int simpleNext(
sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
const char **ppToken, /* OUT: *ppToken is the token text */
int *pnBytes, /* OUT: Number of bytes in token */
int *piStartOffset, /* OUT: Starting offset of token */
int *piEndOffset, /* OUT: Ending offset of token */
int *piPosition /* OUT: Position integer of token */
){
simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor;
simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer;
unsigned char *p = (unsigned char *)c->pInput;
while( c->iOffset<c->nBytes ){
int iStartOffset;
/* Scan past delimiter characters */
while( c->iOffset<c->nBytes && simpleDelim(t, p[c->iOffset]) ){
c->iOffset++;
}
/* Count non-delimiter characters. */
iStartOffset = c->iOffset;
while( c->iOffset<c->nBytes && !simpleDelim(t, p[c->iOffset]) ){
c->iOffset++;
}
if( c->iOffset>iStartOffset ){
int i, n = c->iOffset-iStartOffset;
if( n>c->nTokenAllocated ){
char *pNew;
c->nTokenAllocated = n+20;
pNew = sqlite3_realloc64(c->pToken, c->nTokenAllocated);
if( !pNew ) return SQLITE_NOMEM;
c->pToken = pNew;
}
for(i=0; i<n; i++){
/* TODO(shess) This needs expansion to handle UTF-8
** case-insensitivity.
*/
unsigned char ch = p[iStartOffset+i];
c->pToken[i] = (char)((ch>='A' && ch<='Z') ? ch-'A'+'a' : ch);
}
*ppToken = c->pToken;
*pnBytes = n;
*piStartOffset = iStartOffset;
*piEndOffset = c->iOffset;
*piPosition = c->iToken++;
return SQLITE_OK;
}
}
return SQLITE_DONE;
}
/*
** The set of routines that implement the simple tokenizer
*/
static const sqlite3_tokenizer_module simpleTokenizerModule = {
0,
simpleCreate,
simpleDestroy,
simpleOpen,
simpleClose,
simpleNext,
0,
};
/*
** Allocate a new simple tokenizer. Return a pointer to the new
/************** Begin file fts3_tokenize_vtab.c ******************************/
/*
** 2013 Apr 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code for the "fts3tokenize" virtual table module.
** An fts3tokenize virtual table is created as follows:
**
** CREATE VIRTUAL TABLE <tbl> USING fts3tokenize(
** <tokenizer-name>, <arg-1>, ...
** );
**
** The table created has the following schema:
**
** CREATE TABLE <tbl>(input, token, start, end, position)
**
** When queried, the query must include a WHERE clause of type:
**
** input = <string>
**
** The virtual table module tokenizes this <string>, using the FTS3
** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE
** statement and returns one row for each token in the result. With
** fields set as follows:
**
** input: Always set to a copy of <string>
** token: A token from the input.
** start: Byte offset of the token within the input <string>.
** end: Byte offset of the byte immediately following the end of the
** token within the input string.
** pos: Token offset of token within input.
**
*/
/* #include "fts3Int.h" */
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/* #include <string.h> */
/* #include <assert.h> */
typedef struct Fts3tokTable Fts3tokTable;
typedef struct Fts3tokCursor Fts3tokCursor;
/*
** Virtual table structure.
*/
struct Fts3tokTable {
sqlite3_vtab base; /* Base class used by SQLite core */
const sqlite3_tokenizer_module *pMod;
sqlite3_tokenizer *pTok;
};
/*
** Virtual table cursor structure.
*/
struct Fts3tokCursor {
sqlite3_vtab_cursor base; /* Base class used by SQLite core */
char *zInput; /* Input string */
sqlite3_tokenizer_cursor *pCsr; /* Cursor to iterate through zInput */
int iRowid; /* Current 'rowid' value */
const char *zToken; /* Current 'token' value */
int nToken; /* Size of zToken in bytes */
int iStart; /* Current 'start' value */
int iEnd; /* Current 'end' value */
int iPos; /* Current 'pos' value */
};
/*
** Query FTS for the tokenizer implementation named zName.
*/
static int fts3tokQueryTokenizer(
Fts3Hash *pHash,
const char *zName,
const sqlite3_tokenizer_module **pp,
char **pzErr
){
sqlite3_tokenizer_module *p;
int nName = (int)strlen(zName);
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
if( !p ){
sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName);
return SQLITE_ERROR;
}
*pp = p;
return SQLITE_OK;
}
/*
** The second argument, argv[], is an array of pointers to nul-terminated
** strings. This function makes a copy of the array and strings into a
** single block of memory. It then dequotes any of the strings that appear
** to be quoted.
**
** If successful, output parameter *pazDequote is set to point at the
** array of dequoted strings and SQLITE_OK is returned. The caller is
** responsible for eventually calling sqlite3_free() to free the array
** in this case. Or, if an error occurs, an SQLite error code is returned.
** The final value of *pazDequote is undefined in this case.
*/
static int fts3tokDequoteArray(
int argc, /* Number of elements in argv[] */
const char * const *argv, /* Input array */
char ***pazDequote /* Output array */
){
int rc = SQLITE_OK; /* Return code */
if( argc==0 ){
*pazDequote = 0;
}else{
int i;
int nByte = 0;
char **azDequote;
for(i=0; i<argc; i++){
nByte += (int)(strlen(argv[i]) + 1);
}
*pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
}
if( rc==SQLITE_OK ){
memset(pTab, 0, sizeof(Fts3tokTable));
pTab->pMod = pMod;
pTab->pTok = pTok;
*ppVtab = &pTab->base;
}else{
if( pTok ){
pMod->xDestroy(pTok);
}
}
sqlite3_free(azDequote);
return rc;
}
/*
** This function does the work for both the xDisconnect and xDestroy methods.
** These tables have no persistent representation of their own, so xDisconnect
** and xDestroy are identical operations.
*/
static int fts3tokDisconnectMethod(sqlite3_vtab *pVtab){
Fts3tokTable *pTab = (Fts3tokTable *)pVtab;
pTab->pMod->xDestroy(pTab->pTok);
sqlite3_free(pTab);
return SQLITE_OK;
}
/*
** xBestIndex - Analyze a WHERE and ORDER BY clause.
*/
static int fts3tokBestIndexMethod(
sqlite3_vtab *pVTab,
sqlite3_index_info *pInfo
){
int i;
UNUSED_PARAMETER(pVTab);
for(i=0; i<pInfo->nConstraint; i++){
if( pInfo->aConstraint[i].usable
&& pInfo->aConstraint[i].iColumn==0
&& pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
){
pInfo->idxNum = 1;
pInfo->aConstraintUsage[i].argvIndex = 1;
pInfo->aConstraintUsage[i].omit = 1;
pInfo->estimatedCost = 1;
return SQLITE_OK;
}
}
pInfo->idxNum = 0;
assert( pInfo->estimatedCost>1000000.0 );
return SQLITE_OK;
}
/*
** xOpen - Open a cursor.
*/
static int fts3tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
Fts3tokCursor *pCsr;
UNUSED_PARAMETER(pVTab);
pCsr = (Fts3tokCursor *)sqlite3_malloc(sizeof(Fts3tokCursor));
if( pCsr==0 ){
return SQLITE_NOMEM;
}
memset(pCsr, 0, sizeof(Fts3tokCursor));
*ppCsr = (sqlite3_vtab_cursor *)pCsr;
return SQLITE_OK;
}
/*
** Reset the tokenizer cursor passed as the only argument. As if it had
** just been returned by fts3tokOpenMethod().
*/
static void fts3tokResetCursor(Fts3tokCursor *pCsr){
if( pCsr->pCsr ){
Fts3tokTable *pTab = (Fts3tokTable *)(pCsr->base.pVtab);
pTab->pMod->xClose(pCsr->pCsr);
pCsr->pCsr = 0;
}
sqlite3_free(pCsr->zInput);
pCsr->zInput = 0;
pCsr->zToken = 0;
pCsr->nToken = 0;
pCsr->iStart = 0;
pCsr->iEnd = 0;
pCsr->iPos = 0;
pCsr->iRowid = 0;
}
/*
** xClose - Close a cursor.
*/
static int fts3tokCloseMethod(sqlite3_vtab_cursor *pCursor){
Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
fts3tokResetCursor(pCsr);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** xNext - Advance the cursor to the next row, if any.
*/
static int fts3tokNextMethod(sqlite3_vtab_cursor *pCursor){
Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
int rc; /* Return code */
pCsr->iRowid++;
rc = pTab->pMod->xNext(pCsr->pCsr,
&pCsr->zToken, &pCsr->nToken,
&pCsr->iStart, &pCsr->iEnd, &pCsr->iPos
);
if( rc!=SQLITE_OK ){
fts3tokResetCursor(pCsr);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
return rc;
}
/*
** xFilter - Initialize a cursor to point at the start of its data.
*/
static int fts3tokFilterMethod(
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
int idxNum, /* Strategy index */
const char *idxStr, /* Unused */
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
int rc = SQLITE_ERROR;
Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(nVal);
fts3tokResetCursor(pCsr);
if( idxNum==1 ){
const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
sqlite3_int64 nByte = sqlite3_value_bytes(apVal[0]);
pCsr->zInput = sqlite3_malloc64(nByte+1);
if( pCsr->zInput==0 ){
rc = SQLITE_NOMEM;
}else{
if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
pCsr->zInput[nByte] = 0;
rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
if( rc==SQLITE_OK ){
pCsr->pCsr->pTokenizer = pTab->pTok;
}
}
}
if( rc!=SQLITE_OK ) return rc;
return fts3tokNextMethod(pCursor);
}
/*
** xEof - Return true if the cursor is at EOF, or false otherwise.
*/
static int fts3tokEofMethod(sqlite3_vtab_cursor *pCursor){
Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
return (pCsr->zToken==0);
}
/*
** xColumn - Return a column value.
*/
static int fts3tokColumnMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
/* CREATE TABLE x(input, token, start, end, position) */
switch( iCol ){
case 0:
sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT);
break;
case 1:
sqlite3_result_text(pCtx, pCsr->zToken, pCsr->nToken, SQLITE_TRANSIENT);
break;
case 2:
sqlite3_result_int(pCtx, pCsr->iStart);
break;
case 3:
sqlite3_result_int(pCtx, pCsr->iEnd);
break;
default:
assert( iCol==4 );
sqlite3_result_int(pCtx, pCsr->iPos);
break;
}
return SQLITE_OK;
}
/*
** xRowid - Return the current rowid for the cursor.
*/
static int fts3tokRowidMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
sqlite_int64 *pRowid /* OUT: Rowid value */
){
Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
*pRowid = (sqlite3_int64)pCsr->iRowid;
return SQLITE_OK;
}
/*
** Register the fts3tok module with database connection db. Return SQLITE_OK
** if successful or an error code if sqlite3_create_module() fails.
*/
SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
static const sqlite3_module fts3tok_module = {
0, /* iVersion */
fts3tokConnectMethod, /* xCreate */
fts3tokConnectMethod, /* xConnect */
fts3tokBestIndexMethod, /* xBestIndex */
fts3tokDisconnectMethod, /* xDisconnect */
fts3tokDisconnectMethod, /* xDestroy */
fts3tokOpenMethod, /* xOpen */
fts3tokCloseMethod, /* xClose */
fts3tokFilterMethod, /* xFilter */
fts3tokNextMethod, /* xNext */
fts3tokEofMethod, /* xEof */
fts3tokColumnMethod, /* xColumn */
fts3tokRowidMethod, /* xRowid */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindFunction */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
int rc; /* Return code */
rc = sqlite3_create_module_v2(
db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy
);
return rc;
}
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
/************** End of fts3_tokenize_vtab.c **********************************/
/************** Begin file fts3_write.c **************************************/
/*
** 2009 Oct 23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
** The code is written so that the hard lower-limit for each of these values
** is 1. Clearly such small values would be inefficient, but can be useful
** for testing purposes.
**
** If this module is built with SQLITE_TEST defined, these constants may
** be overridden at runtime for testing purposes. File fts3_test.c contains
** a Tcl interface to read and write the values.
*/
#ifdef SQLITE_TEST
int test_fts3_node_chunksize = (4*1024);
int test_fts3_node_chunk_threshold = (4*1024)*4;
# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize
# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
#else
# define FTS3_NODE_CHUNKSIZE (4*1024)
# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
#endif
/*
** The values that may be meaningfully bound to the :1 parameter in
** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
*/
#define FTS_STAT_DOCTOTAL 0
#define FTS_STAT_INCRMERGEHINT 1
#define FTS_STAT_AUTOINCRMERGE 2
/*
** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic
** and incremental merge operation that takes place. This is used for
** debugging FTS only, it should not usually be turned on in production
** systems.
*/
#ifdef FTS3_LOG_MERGES
static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){
sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel);
}
#else
#define fts3LogMerge(x, y)
#endif
typedef struct PendingList PendingList;
typedef struct SegmentNode SegmentNode;
typedef struct SegmentWriter SegmentWriter;
/*
** An instance of the following data structure is used to build doclists
** incrementally. See function fts3PendingListAppend() for details.
*/
struct PendingList {
int nData;
char *aData;
int nSpace;
sqlite3_int64 iLastDocid;
sqlite3_int64 iLastCol;
sqlite3_int64 iLastPos;
};
/*
** Each cursor has a (possibly empty) linked list of the following objects.
*/
struct Fts3DeferredToken {
Fts3PhraseToken *pToken; /* Pointer to corresponding expr token */
int iCol; /* Column token must occur in */
Fts3DeferredToken *pNext; /* Next in list of deferred tokens */
PendingList *pList; /* Doclist is assembled here */
};
/*
** An instance of this structure is used to iterate through the terms on
** a contiguous set of segment b-tree leaf nodes. Although the details of
** this structure are only manipulated by code in this file, opaque handles
** of type Fts3SegReader* are also used by code in fts3.c to iterate through
** terms when querying the full-text index. See functions:
**
** sqlite3Fts3SegReaderNew()
** sqlite3Fts3SegReaderFree()
** sqlite3Fts3SegReaderIterate()
**
** Methods used to manipulate Fts3SegReader structures:
**
** fts3SegReaderNext()
** fts3SegReaderFirstDocid()
** fts3SegReaderNextDocid()
*/
struct Fts3SegReader {
int iIdx; /* Index within level, or 0x7FFFFFFF for PT */
u8 bLookup; /* True for a lookup only */
u8 rootOnly; /* True for a root-only reader */
sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */
sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */
sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */
sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */
char *aNode; /* Pointer to node data (or NULL) */
int nNode; /* Size of buffer at aNode (or 0) */
int nPopulate; /* If >0, bytes of buffer aNode[] loaded */
sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */
Fts3HashElem **ppNextElem;
/* Variables set by fts3SegReaderNext(). These may be read directly
** by the caller. They are valid from the time SegmentReaderNew() returns
** until SegmentReaderNext() returns something other than SQLITE_OK
** (i.e. SQLITE_DONE).
*/
int nTerm; /* Number of bytes in current term */
char *zTerm; /* Pointer to current term */
int nTermAlloc; /* Allocated size of zTerm buffer */
char *aDoclist; /* Pointer to doclist of current entry */
int nDoclist; /* Size of doclist in current entry */
/* The following variables are used by fts3SegReaderNextDocid() to iterate
** through the current doclist (aDoclist/nDoclist).
*/
char *pOffsetList;
int nOffsetList; /* For descending pending seg-readers only */
sqlite3_int64 iDocid;
};
/*
** Add an entry to one of the pending-terms hash tables.
*/
static int fts3PendingTermsAddOne(
Fts3Table *p,
int iCol,
int iPos,
Fts3Hash *pHash, /* Pending terms hash table to add entry to */
const char *zToken,
int nToken
){
PendingList *pList;
int rc = SQLITE_OK;
pList = (PendingList *)fts3HashFind(pHash, zToken, nToken);
if( pList ){
p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem));
}
if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
/* Malloc failed while inserting the new entry. This can only
** happen if there was no previous entry for this token.
*/
assert( 0==fts3HashFind(pHash, zToken, nToken) );
sqlite3_free(pList);
rc = SQLITE_NOMEM;
}
}
if( rc==SQLITE_OK ){
p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem));
}
return rc;
}
/*
** Tokenize the nul-terminated string zText and add all tokens to the
** pending-terms hash-table. The docid used is that currently stored in
** p->iPrevDocid, and the column is specified by argument iCol.
**
** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code.
*/
static int fts3PendingTermsAdd(
Fts3Table *p, /* Table into which text will be inserted */
int iLangid, /* Language id to use */
const char *zText, /* Text of document to be inserted */
int iCol, /* Column into which text is being inserted */
u32 *pnWord /* IN/OUT: Incr. by number tokens inserted */
){
int rc;
int iStart = 0;
int iEnd = 0;
int iPos = 0;
int nWord = 0;
char const *zToken;
int nToken = 0;
sqlite3_tokenizer *pTokenizer = p->pTokenizer;
sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
sqlite3_tokenizer_cursor *pCsr;
int (*xNext)(sqlite3_tokenizer_cursor *pCursor,
const char**,int*,int*,int*,int*);
assert( pTokenizer && pModule );
/* If the user has inserted a NULL value, this function may be called with
** zText==0. In this case, add zero token entries to the hash table and
** return early. */
if( zText==0 ){
*pnWord = 0;
return SQLITE_OK;
}
rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr);
if( rc!=SQLITE_OK ){
return rc;
}
xNext = pModule->xNext;
while( SQLITE_OK==rc
&& SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos))
){
int i;
if( iPos>=nWord ) nWord = iPos+1;
/* Positions cannot be negative; we use -1 as a terminator internally.
** Tokens must have a non-zero length.
*/
if( iPos<0 || !zToken || nToken<=0 ){
rc = SQLITE_ERROR;
break;
}
/* Add the term to the terms index */
rc = fts3PendingTermsAddOne(
p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
);
/* Add the term to each of the prefix indexes that it is not too
** short for. */
for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
struct Fts3Index *pIndex = &p->aIndex[i];
if( nToken<pIndex->nPrefix ) continue;
rc = fts3PendingTermsAddOne(
p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix
);
}
}
pModule->xClose(pCsr);
*pnWord += nWord;
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}
/*
** Calling this function indicates that subsequent calls to
** fts3PendingTermsAdd() are to add term/position-list pairs for the
** contents of the document with docid iDocid.
*/
static int fts3PendingTermsDocid(
Fts3Table *p, /* Full-text table handle */
sqlite3_free(aByte);
aByte = 0;
}
}
*paBlob = aByte;
}
}else if( rc==SQLITE_ERROR ){
rc = FTS_CORRUPT_VTAB;
}
return rc;
}
/*
** Close the blob handle at p->pSegments, if it is open. See comments above
** the sqlite3Fts3ReadBlock() function for details.
*/
SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){
sqlite3_blob_close(p->pSegments);
p->pSegments = 0;
}
static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
int nRead; /* Number of bytes to read */
int rc; /* Return code */
nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
rc = sqlite3_blob_read(
pReader->pBlob,
&pReader->aNode[pReader->nPopulate],
nRead,
pReader->nPopulate
);
if( rc==SQLITE_OK ){
pReader->nPopulate += nRead;
memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING);
if( pReader->nPopulate==pReader->nNode ){
sqlite3_blob_close(pReader->pBlob);
pReader->pBlob = 0;
pReader->nPopulate = 0;
}
}
return rc;
}
static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
int rc = SQLITE_OK;
assert( !pReader->pBlob
|| (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
);
while( pReader->pBlob && rc==SQLITE_OK
&& (pFrom - pReader->aNode + nByte)>pReader->nPopulate
){
rc = fts3SegReaderIncrRead(pReader);
}
return rc;
}
/*
** Set an Fts3SegReader cursor to point at EOF.
*/
static void fts3SegReaderSetEof(Fts3SegReader *pSeg){
if( !fts3SegReaderIsRootOnly(pSeg) ){
sqlite3_free(pSeg->aNode);
sqlite3_blob_close(pSeg->pBlob);
pSeg->pBlob = 0;
}
pSeg->aNode = 0;
}
/*
** Move the iterator passed as the first argument to the next term in the
** segment. If successful, SQLITE_OK is returned. If there is no next term,
** SQLITE_DONE. Otherwise, an SQLite error code.
*/
static int fts3SegReaderNext(
Fts3Table *p,
Fts3SegReader *pReader,
int bIncr
){
int rc; /* Return code of various sub-routines */
char *pNext; /* Cursor variable */
int nPrefix; /* Number of bytes in term prefix */
int nSuffix; /* Number of bytes in term suffix */
if( !pReader->aDoclist ){
pNext = pReader->aNode;
}else{
pNext = &pReader->aDoclist[pReader->nDoclist];
}
if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
if( fts3SegReaderIsPending(pReader) ){
Fts3HashElem *pElem = *(pReader->ppNextElem);
sqlite3_free(pReader->aNode);
pReader->aNode = 0;
if( pElem ){
char *aCopy;
PendingList *pList = (PendingList *)fts3HashData(pElem);
int nCopy = pList->nData+1;
int nTerm = fts3HashKeysize(pElem);
if( (nTerm+1)>pReader->nTermAlloc ){
sqlite3_free(pReader->zTerm);
pReader->zTerm = (char*)sqlite3_malloc64(((i64)nTerm+1)*2);
if( !pReader->zTerm ) return SQLITE_NOMEM;
pReader->nTermAlloc = (nTerm+1)*2;
}
memcpy(pReader->zTerm, fts3HashKey(pElem), nTerm);
pReader->zTerm[nTerm] = '\0';
pReader->nTerm = nTerm;
aCopy = (char*)sqlite3_malloc64(nCopy);
if( !aCopy ) return SQLITE_NOMEM;
memcpy(aCopy, pList->aData, nCopy);
pReader->nNode = pReader->nDoclist = nCopy;
pReader->aNode = pReader->aDoclist = aCopy;
pReader->ppNextElem++;
assert( pReader->aNode );
}else{
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ){
sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3;
aSz = (u32 *)sqlite3_malloc64(nByte);
if( aSz==0 ){
rc = SQLITE_NOMEM;
}else{
memset(aSz, 0, nByte);
aSzIns = &aSz[p->nColumn+1];
aSzDel = &aSzIns[p->nColumn+1];
}
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
int iCol;
int iLangid = langidFromSelect(p, pStmt);
rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0));
memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
if( p->abNotindexed[iCol]==0 ){
const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
}
}
if( p->bHasDocsize ){
fts3InsertDocsize(&rc, p, aSz);
}
if( rc!=SQLITE_OK ){
sqlite3_finalize(pStmt);
pStmt = 0;
}else{
nEntry++;
for(iCol=0; iCol<=p->nColumn; iCol++){
aSzIns[iCol] += aSz[iCol];
}
}
}
if( p->bFts4 ){
fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry);
}
sqlite3_free(aSz);
if( pStmt ){
int rc2 = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK ){
rc = rc2;
}
}
}
return rc;
}
/*
** This function opens a cursor used to read the input data for an
** incremental merge operation. Specifically, it opens a cursor to scan
** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
** level iAbsLevel.
*/
static int fts3IncrmergeCsr(
Fts3Table *p, /* FTS3 table handle */
sqlite3_int64 iAbsLevel, /* Absolute level to open */
int nSeg, /* Number of segments to merge */
Fts3MultiSegReader *pCsr /* Cursor object to populate */
){
int rc; /* Return Code */
sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
sqlite3_int64 nByte; /* Bytes allocated at pCsr->apSegment[] */
/* Allocate space for the Fts3MultiSegReader.aCsr[] array */
memset(pCsr, 0, sizeof(*pCsr));
nByte = sizeof(Fts3SegReader *) * nSeg;
pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc64(nByte);
if( pCsr->apSegment==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pCsr->apSegment, 0, nByte);
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
}
if( rc==SQLITE_OK ){
int i;
int rc2;
sqlite3_bind_int64(pStmt, 1, iAbsLevel);
assert( pCsr->nSegment==0 );
for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && i<nSeg; i++){
rc = sqlite3Fts3SegReaderNew(i, 0,
sqlite3_column_int64(pStmt, 1), /* segdir.start_block */
sqlite3_column_int64(pStmt, 2), /* segdir.leaves_end_block */
sqlite3_column_int64(pStmt, 3), /* segdir.end_block */
sqlite3_column_blob(pStmt, 4), /* segdir.root */
sqlite3_column_bytes(pStmt, 4), /* segdir.root */
&pCsr->apSegment[i]
);
pCsr->nSegment++;
}
rc2 = sqlite3_reset(pStmt);
if( rc==SQLITE_OK ) rc = rc2;
}
return rc;
}
typedef struct IncrmergeWriter IncrmergeWriter;
typedef struct NodeWriter NodeWriter;
typedef struct Blob Blob;
typedef struct NodeReader NodeReader;
/*
** An instance of the following structure is used as a dynamic buffer
** to build up nodes or other blobs of data in.
**
** The function blobGrowBuffer() is used to extend the allocation.
*/
struct Blob {
char *a; /* Pointer to allocation */
** If the size of the value in blob pPrev is zero, then this is the first
** term written to the node. Otherwise, pPrev contains a copy of the
** previous term. Before this function returns, it is updated to contain a
** copy of zTerm/nTerm.
**
** It is assumed that the buffer associated with pNode is already large
** enough to accommodate the new entry. The buffer associated with pPrev
** is extended by this function if required.
**
** If an error (i.e. OOM condition) occurs, an SQLite error code is
** returned. Otherwise, SQLITE_OK.
*/
static int fts3AppendToNode(
Blob *pNode, /* Current node image to append to */
Blob *pPrev, /* Buffer containing previous term written */
const char *zTerm, /* New term to write */
int nTerm, /* Size of zTerm in bytes */
const char *aDoclist, /* Doclist (or NULL) to write */
int nDoclist /* Size of aDoclist in bytes */
){
int rc = SQLITE_OK; /* Return code */
int bFirst = (pPrev->n==0); /* True if this is the first term written */
int nPrefix; /* Size of term prefix in bytes */
int nSuffix; /* Size of term suffix in bytes */
/* Node must have already been started. There must be a doclist for a
** leaf node, and there must not be a doclist for an internal node. */
assert( pNode->n>0 );
assert_fts3_nc( (pNode->a[0]=='\0')==(aDoclist!=0) );
blobGrowBuffer(pPrev, nTerm, &rc);
if( rc!=SQLITE_OK ) return rc;
assert( pPrev!=0 );
assert( pPrev->a!=0 );
nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
memcpy(pPrev->a, zTerm, nTerm);
pPrev->n = nTerm;
if( bFirst==0 ){
pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix);
}
pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix);
memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix);
pNode->n += nSuffix;
if( aDoclist ){
pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist);
memcpy(&pNode->a[pNode->n], aDoclist, nDoclist);
pNode->n += nDoclist;
}
assert( pNode->n<=pNode->nAlloc );
return SQLITE_OK;
}
/*
** Append the current term and doclist pointed to by cursor pCsr to the
** appendable b-tree segment opened for writing by pWriter.
**
** Return SQLITE_OK if successful, or an SQLite error code otherwise.
*/
static int fts3IncrmergeAppend(
Fts3Table *p, /* Fts3 table handle */
IncrmergeWriter *pWriter, /* Writer object */
Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */
){
const char *zTerm = pCsr->zTerm;
int nTerm = pCsr->nTerm;
const char *aDoclist = pCsr->aDoclist;
int nDoclist = pCsr->nDoclist;
int rc = SQLITE_OK; /* Return code */
int nSpace; /* Total space in bytes required on leaf */
int nPrefix; /* Size of prefix shared with previous term */
int nSuffix; /* Size of suffix (nTerm - nPrefix) */
NodeWriter *pLeaf; /* Object used to write leaf nodes */
pLeaf = &pWriter->aNodeWriter[0];
nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
nSpace = sqlite3Fts3VarintLen(nPrefix);
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
/* If the current block is not empty, and if adding this term/doclist
** to the current block would make it larger than Fts3Table.nNodeSize bytes,
** and if there is still room for another leaf page, write this block out to
** the database. */
if( pLeaf->block.n>0
&& (pLeaf->block.n + nSpace)>p->nNodeSize
&& pLeaf->iBlock < (pWriter->iStart + pWriter->nLeafEst)
){
rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n);
pWriter->nWork++;
/* Add the current term to the parent node. The term added to the
** parent must:
**
** a) be greater than the largest term on the leaf node just written
** to the database (still available in pLeaf->key), and
**
** b) be less than or equal to the term about to be added to the new
** leaf node (zTerm/nTerm).
**
** In other words, it must be the prefix of zTerm 1 byte longer than
** the common prefix (if any) of zTerm and pWriter->zTerm.
*/
if( rc==SQLITE_OK ){
rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1);
}
/* Advance to the next output block */
pLeaf->iBlock++;
pLeaf->key.n = 0;
pLeaf->block.n = 0;
while( rc==SQLITE_OK && iBlock ){
char *aBlock = 0;
int nBlock = 0;
iNewStart = iBlock;
rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0);
if( rc==SQLITE_OK ){
rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock);
}
if( rc==SQLITE_OK ){
rc = fts3WriteSegment(p, iNewStart, block.a, block.n);
}
sqlite3_free(aBlock);
}
/* Variable iNewStart now contains the first valid leaf node. */
if( rc==SQLITE_OK && iNewStart ){
sqlite3_stmt *pDel = 0;
rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pDel, 1, iOldStart);
sqlite3_bind_int64(pDel, 2, iNewStart-1);
sqlite3_step(pDel);
rc = sqlite3_reset(pDel);
}
}
if( rc==SQLITE_OK ){
sqlite3_stmt *pChomp = 0;
rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pChomp, 1, iNewStart);
sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC);
sqlite3_bind_int64(pChomp, 3, iAbsLevel);
sqlite3_bind_int(pChomp, 4, iIdx);
sqlite3_step(pChomp);
rc = sqlite3_reset(pChomp);
sqlite3_bind_null(pChomp, 2);
}
}
sqlite3_free(root.a);
sqlite3_free(block.a);
return rc;
}
/*
** This function is called after an incrmental-merge operation has run to
** merge (or partially merge) two or more segments from absolute level
** iAbsLevel.
**
** Each input segment is either removed from the db completely (if all of
** its data was copied to the output segment by the incrmerge operation)
** or modified in place so that it no longer contains those entries that
** have been duplicated in the output segment.
*/
static int fts3IncrmergeChomp(
Fts3Table *p, /* FTS table handle */
sqlite3_int64 iAbsLevel, /* Absolute level containing segments */
Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */
int *pnRem /* Number of segments not deleted */
){
int i;
int nRem = 0;
int rc = SQLITE_OK;
for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){
Fts3SegReader *pSeg = 0;
int j;
/* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding
** somewhere in the pCsr->apSegment[] array. */
for(j=0; ALWAYS(j<pCsr->nSegment); j++){
pSeg = pCsr->apSegment[j];
if( pSeg->iIdx==i ) break;
}
assert( j<pCsr->nSegment && pSeg->iIdx==i );
if( pSeg->aNode==0 ){
/* Seg-reader is at EOF. Remove the entire input segment. */
rc = fts3DeleteSegment(p, pSeg);
if( rc==SQLITE_OK ){
rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx);
}
*pnRem = 0;
}else{
/* The incremental merge did not copy all the data from this
** segment to the upper level. The segment is modified in place
** so that it contains no keys smaller than zTerm/nTerm. */
const char *zTerm = pSeg->zTerm;
int nTerm = pSeg->nTerm;
rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm);
nRem++;
}
}
if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){
rc = fts3RepackSegdirLevel(p, iAbsLevel);
}
*pnRem = nRem;
return rc;
}
/*
** Store an incr-merge hint in the database.
*/
static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
sqlite3_stmt *pReplace = 0;
int rc; /* Return code */
rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT);
sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
sqlite3_step(pReplace);
rc = sqlite3_reset(pReplace);
sqlite3_bind_null(pReplace, 2);
}
** and the number of input segments.
**
** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs,
** set *pRc to an SQLite error code before returning.
*/
static void fts3IncrmergeHintPush(
Blob *pHint, /* Hint blob to append to */
i64 iAbsLevel, /* First varint to store in hint */
int nInput, /* Second varint to store in hint */
int *pRc /* IN/OUT: Error code */
){
blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc);
if( *pRc==SQLITE_OK ){
pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel);
pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput);
}
}
/*
** Read the last entry (most recently pushed) from the hint blob *pHint
** and then remove the entry. Write the two values read to *piAbsLevel and
** *pnInput before returning.
**
** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does
** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB.
*/
static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
const int nHint = pHint->n;
int i;
i = pHint->n-1;
if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB;
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
if( i==0 ) return FTS_CORRUPT_VTAB;
i--;
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
pHint->n = i;
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
i += fts3GetVarint32(&pHint->a[i], pnInput);
assert( i<=nHint );
if( i!=nHint ) return FTS_CORRUPT_VTAB;
return SQLITE_OK;
}
/*
** Attempt an incremental merge that writes nMerge leaf blocks.
**
** Incremental merges happen nMin segments at a time. The segments
** to be merged are the nMin oldest segments (the ones with the smallest
** values for the _segdir.idx field) in the highest level that contains
** at least nMin segments. Multiple merges might occur in an attempt to
** write the quota of nMerge leaf blocks.
*/
SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
int rc; /* Return code */
int nRem = nMerge; /* Number of leaf pages yet to be written */
Fts3MultiSegReader *pCsr; /* Cursor used to read input data */
Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */
IncrmergeWriter *pWriter; /* Writer object */
int nSeg = 0; /* Number of input segments */
sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */
Blob hint = {0, 0, 0}; /* Hint read from %_stat table */
int bDirtyHint = 0; /* True if blob 'hint' has been modified */
/* Allocate space for the cursor, filter and writer objects */
const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
pWriter = (IncrmergeWriter *)sqlite3_malloc64(nAlloc);
if( !pWriter ) return SQLITE_NOMEM;
pFilter = (Fts3SegFilter *)&pWriter[1];
pCsr = (Fts3MultiSegReader *)&pFilter[1];
rc = fts3IncrmergeHintLoad(p, &hint);
while( rc==SQLITE_OK && nRem>0 ){
const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
int bUseHint = 0; /* True if attempting to append */
int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
/* Search the %_segdir table for the absolute level with the smallest
** relative level number that contains at least nMin segments, if any.
** If one is found, set iAbsLevel to the absolute level number and
** nSeg to nMin. If no level with at least nMin segments can be found,
** set nSeg to -1.
*/
rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0);
sqlite3_bind_int(pFindLevel, 1, MAX(2, nMin));
if( sqlite3_step(pFindLevel)==SQLITE_ROW ){
iAbsLevel = sqlite3_column_int64(pFindLevel, 0);
nSeg = sqlite3_column_int(pFindLevel, 1);
assert( nSeg>=2 );
}else{
nSeg = -1;
}
rc = sqlite3_reset(pFindLevel);
/* If the hint read from the %_stat table is not empty, check if the
** last entry in it specifies a relative level smaller than or equal
** to the level identified by the block above (if any). If so, this
** iteration of the loop will work on merging at the hinted level.
*/
if( rc==SQLITE_OK && hint.n ){
int nHint = hint.n;
sqlite3_int64 iHintAbsLevel = 0; /* Hint level */
int nHintSeg = 0; /* Hint number of segments */
rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
/* Based on the scan in the block above, it is known that there
** are no levels with a relative level smaller than that of
** iAbsLevel with more than nSeg segments, or if nSeg is -1,
** no levels with more than nMin segments. Use this to limit the
** value of nHintSeg to avoid a large memory allocation in case the
** merge-hint is corrupt*/
iAbsLevel = iHintAbsLevel;
nSeg = MIN(MAX(nMin,nSeg), nHintSeg);
bUseHint = 1;
bDirtyHint = 1;
}else{
/* This undoes the effect of the HintPop() above - so that no entry
** is removed from the hint blob. */
hint.n = nHint;
}
}
/* If nSeg is less that zero, then there is no level with at least
** nMin segments and no hint in the %_stat table. No work to do.
** Exit early in this case. */
if( nSeg<=0 ) break;
assert( nMod<=0x7FFFFFFF );
if( iAbsLevel<0 || iAbsLevel>(nMod<<32) ){
rc = FTS_CORRUPT_VTAB;
break;
}
/* Open a cursor to iterate through the contents of the oldest nSeg
** indexes of absolute level iAbsLevel. If this cursor is opened using
** the 'hint' parameters, it is possible that there are less than nSeg
** segments available in level iAbsLevel. In this case, no work is
** done on iAbsLevel - fall through to the next iteration of the loop
** to start work on some other level. */
memset(pWriter, 0, nAlloc);
pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
if( rc==SQLITE_OK ){
rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
assert( bUseHint==1 || bUseHint==0 );
if( iIdx==0 || (bUseHint && iIdx==1) ){
int bIgnore = 0;
rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore);
if( bIgnore ){
pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY;
}
}
}
if( rc==SQLITE_OK ){
rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
}
if( SQLITE_OK==rc && pCsr->nSegment==nSeg
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
){
int bEmpty = 0;
rc = sqlite3Fts3SegReaderStep(p, pCsr);
if( rc==SQLITE_OK ){
bEmpty = 1;
}else if( rc!=SQLITE_ROW ){
sqlite3Fts3SegReaderFinish(pCsr);
break;
}
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
}else{
rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
}
if( rc==SQLITE_OK && pWriter->nLeafEst ){
fts3LogMerge(nSeg, iAbsLevel);
if( bEmpty==0 ){
do {
rc = fts3IncrmergeAppend(p, pWriter, pCsr);
if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
}while( rc==SQLITE_ROW );
}
/* Update or delete the input segments */
if( rc==SQLITE_OK ){
nRem -= (1 + pWriter->nWork);
rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg);
if( nSeg!=0 ){
bDirtyHint = 1;
fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc);
}
}
sqlite3Fts3SegReaderFinish(&csr);
*pRc = rc;
return cksum;
}
/*
** Check if the contents of the FTS index match the current contents of the
** content table. If no error occurs and the contents do match, set *pbOk
** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk
** to false before returning.
**
** If an error occurs (e.g. an OOM or IO error), return an SQLite error
** code. The final value of *pbOk is undefined in this case.
*/
SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
int rc = SQLITE_OK; /* Return code */
u64 cksum1 = 0; /* Checksum based on FTS index contents */
u64 cksum2 = 0; /* Checksum based on %_content contents */
sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */
/* This block calculates the checksum according to the FTS index. */
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
if( rc==SQLITE_OK ){
int rc2;
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
sqlite3_bind_int(pAllLangid, 2, p->nIndex);
while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
int iLangid = sqlite3_column_int(pAllLangid, 0);
int i;
for(i=0; i<p->nIndex; i++){
cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc);
}
}
rc2 = sqlite3_reset(pAllLangid);
if( rc==SQLITE_OK ) rc = rc2;
}
/* This block calculates the checksum according to the %_content table */
if( rc==SQLITE_OK ){
sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
sqlite3_stmt *pStmt = 0;
char *zSql;
zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
}
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
i64 iDocid = sqlite3_column_int64(pStmt, 0);
int iLang = langidFromSelect(p, pStmt);
int iCol;
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
if( p->abNotindexed[iCol]==0 ){
const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
sqlite3_tokenizer_cursor *pT = 0;
rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
int nToken = 0; /* Number of bytes in token */
int iDum1 = 0, iDum2 = 0; /* Dummy variables */
int iPos = 0; /* Position of token in zText */
rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
if( rc==SQLITE_OK ){
int i;
cksum2 = cksum2 ^ fts3ChecksumEntry(
zToken, nToken, iLang, 0, iDocid, iCol, iPos
);
for(i=1; i<p->nIndex; i++){
if( p->aIndex[i].nPrefix<=nToken ){
cksum2 = cksum2 ^ fts3ChecksumEntry(
zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
);
}
}
}
}
if( pT ) pModule->xClose(pT);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
}
}
sqlite3_finalize(pStmt);
}
if( rc==SQLITE_CORRUPT_VTAB ){
rc = SQLITE_OK;
*pbOk = 0;
}else{
*pbOk = (rc==SQLITE_OK && cksum1==cksum2);
}
return rc;
}
/*
** Run the integrity-check. If no error occurs and the current contents of
** the FTS index are correct, return SQLITE_OK. Or, if the contents of the
** FTS index are incorrect, return SQLITE_CORRUPT_VTAB.
**
** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
** error code.
**
** The integrity-check works as follows. For each token and indexed token
** prefix in the document set, a 64-bit checksum is calculated (by code
** in fts3ChecksumEntry()) based on the following:
**
** + The index number (0 for the main index, 1 for the first prefix
** index etc.),
** + The token (or token prefix) text itself,
** + The language-id of the row it appears in,
** + The docid of the row it appears in,
** + The column it appears in, and
** + The tokens position within that column.
rc = SQLITE_OK;
}
}
#endif
return rc;
}
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
/*
** Delete all cached deferred doclists. Deferred doclists are cached
** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
*/
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){
Fts3DeferredToken *pDef;
for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){
fts3PendingListDelete(pDef->pList);
pDef->pList = 0;
}
}
/*
** Free all entries in the pCsr->pDeffered list. Entries are added to
** this list using sqlite3Fts3DeferToken().
*/
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
Fts3DeferredToken *pDef;
Fts3DeferredToken *pNext;
for(pDef=pCsr->pDeferred; pDef; pDef=pNext){
pNext = pDef->pNext;
fts3PendingListDelete(pDef->pList);
sqlite3_free(pDef);
}
pCsr->pDeferred = 0;
}
/*
** Generate deferred-doclists for all tokens in the pCsr->pDeferred list
** based on the row that pCsr currently points to.
**
** A deferred-doclist is like any other doclist with position information
** included, except that it only contains entries for a single row of the
** table, not for all rows.
*/
SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
int rc = SQLITE_OK; /* Return code */
if( pCsr->pDeferred ){
int i; /* Used to iterate through table columns */
sqlite3_int64 iDocid; /* Docid of the row pCsr points to */
Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
sqlite3_tokenizer *pT = p->pTokenizer;
sqlite3_tokenizer_module const *pModule = pT->pModule;
assert( pCsr->isRequireSeek==0 );
iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
if( p->abNotindexed[i]==0 ){
const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
sqlite3_tokenizer_cursor *pTC = 0;
rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
int nToken = 0; /* Number of bytes in token */
int iDum1 = 0, iDum2 = 0; /* Dummy variables */
int iPos = 0; /* Position of token in zText */
rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
Fts3PhraseToken *pPT = pDef->pToken;
if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
&& (pPT->bFirst==0 || iPos==0)
&& (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
&& (0==memcmp(zToken, pPT->z, pPT->n))
){
fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
}
}
}
if( pTC ) pModule->xClose(pTC);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
}
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
if( pDef->pList ){
rc = fts3PendingListAppendVarint(&pDef->pList, 0);
}
}
}
return rc;
}
SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(
Fts3DeferredToken *p,
char **ppData,
int *pnData
){
char *pRet;
int nSkip;
sqlite3_int64 dummy;
*ppData = 0;
*pnData = 0;
if( p->pList==0 ){
return SQLITE_OK;
}
pRet = (char *)sqlite3_malloc64(p->pList->nData);
if( !pRet ) return SQLITE_NOMEM;
nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
*pnData = p->pList->nData - nSkip;
*ppData = pRet;
memcpy(pRet, &p->pList->aData[nSkip], *pnData);
return SQLITE_OK;
}
/*
** Add an entry for token pToken to the pCsr->pDeferred list.
*/
SQLITE_PRIVATE int sqlite3Fts3DeferToken(
Fts3Cursor *pCsr, /* Fts3 table cursor */
Fts3PhraseToken *pToken, /* Token to defer */
int iCol /* Column that token must appear in (or -1) */
){
Fts3DeferredToken *pDeferred;
pDeferred = sqlite3_malloc64(sizeof(*pDeferred));
if( !pDeferred ){
return SQLITE_NOMEM;
}
memset(pDeferred, 0, sizeof(*pDeferred));
pDeferred->pToken = pToken;
pDeferred->pNext = pCsr->pDeferred;
pDeferred->iCol = iCol;
pCsr->pDeferred = pDeferred;
assert( pToken->pDeferred==0 );
pToken->pDeferred = pDeferred;
return SQLITE_OK;
}
#endif
/*
** SQLite value pRowid contains the rowid of a row that may or may not be
** present in the FTS3 table. If it is, delete it and adjust the contents
** of subsidiary data structures accordingly.
*/
static int fts3DeleteByRowid(
Fts3Table *p,
sqlite3_value *pRowid,
int *pnChng, /* IN/OUT: Decrement if row is deleted */
u32 *aSzDel
){
int rc = SQLITE_OK; /* Return code */
int bFound = 0; /* True if *pRowid really is in the table */
fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound);
if( bFound && rc==SQLITE_OK ){
int isEmpty = 0; /* Deleting *pRowid leaves the table empty */
rc = fts3IsEmpty(p, pRowid, &isEmpty);
if( rc==SQLITE_OK ){
if( isEmpty ){
/* Deleting this row means the whole table is empty. In this case
** delete the contents of all three tables and throw away any
** data in the pendingTerms hash table. */
rc = fts3DeleteAll(p, 1);
*pnChng = 0;
memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2);
}else{
*pnChng = *pnChng - 1;
if( p->zContentTbl==0 ){
fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
}
if( p->bHasDocsize ){
fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
}
}
}
}
return rc;
static int fts3ExprIterate2(
Fts3Expr *pExpr, /* Expression to iterate phrases of */
int *piPhrase, /* Pointer to phrase counter */
int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
void *pCtx /* Second argument to pass to callback */
){
int rc; /* Return code */
int eType = pExpr->eType; /* Type of expression node pExpr */
if( eType!=FTSQUERY_PHRASE ){
assert( pExpr->pLeft && pExpr->pRight );
rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx);
if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){
rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx);
}
}else{
rc = x(pExpr, *piPhrase, pCtx);
(*piPhrase)++;
}
return rc;
}
/*
** Iterate through all phrase nodes in an FTS3 query, except those that
** are part of a sub-tree that is the right-hand-side of a NOT operator.
** For each phrase node found, the supplied callback function is invoked.
**
** If the callback function returns anything other than SQLITE_OK,
** the iteration is abandoned and the error code returned immediately.
** Otherwise, SQLITE_OK is returned after a callback has been made for
** all eligible phrase nodes.
*/
SQLITE_PRIVATE int sqlite3Fts3ExprIterate(
Fts3Expr *pExpr, /* Expression to iterate phrases of */
int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */
void *pCtx /* Second argument to pass to callback */
){
int iPhrase = 0; /* Variable used as the phrase counter */
return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
}
/*
** This is an sqlite3Fts3ExprIterate() callback used while loading the
** doclists for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
** fts3ExprLoadDoclists().
*/
static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
int rc = SQLITE_OK;
Fts3Phrase *pPhrase = pExpr->pPhrase;
LoadDoclistCtx *p = (LoadDoclistCtx *)ctx;
UNUSED_PARAMETER(iPhrase);
p->nPhrase++;
p->nToken += pPhrase->nToken;
return rc;
}
/*
** Load the doclists for each phrase in the query associated with FTS3 cursor
** pCsr.
**
** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable
** phrases in the expression (all phrases except those directly or
** indirectly descended from the right-hand-side of a NOT operator). If
** pnToken is not NULL, then it is set to the number of tokens in all
** matchable phrases of the expression.
*/
static int fts3ExprLoadDoclists(
Fts3Cursor *pCsr, /* Fts3 cursor for current query */
int *pnPhrase, /* OUT: Number of phrases in query */
int *pnToken /* OUT: Number of tokens in query */
){
int rc; /* Return Code */
LoadDoclistCtx sCtx = {0,0,0}; /* Context for sqlite3Fts3ExprIterate() */
sCtx.pCsr = pCsr;
rc = sqlite3Fts3ExprIterate(pCsr->pExpr,fts3ExprLoadDoclistsCb,(void*)&sCtx);
if( pnPhrase ) *pnPhrase = sCtx.nPhrase;
if( pnToken ) *pnToken = sCtx.nToken;
return rc;
}
static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
(*(int *)ctx)++;
pExpr->iPhrase = iPhrase;
return SQLITE_OK;
}
static int fts3ExprPhraseCount(Fts3Expr *pExpr){
int nPhrase = 0;
(void)sqlite3Fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase);
return nPhrase;
}
/*
** Advance the position list iterator specified by the first two
** arguments so that it points to the first element with a value greater
** than or equal to parameter iNext.
*/
static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
char *pIter = *ppIter;
if( pIter ){
i64 iIter = *piIter;
while( iIter<iNext ){
if( 0==(*pIter & 0xFE) ){
iIter = -1;
pIter = 0;
break;
}
fts3GetDeltaPosition(&pIter, &iIter);
}
*piIter = iIter;
*ppIter = pIter;
}
}
/*
** Advance the snippet iterator to the next candidate snippet.
*/
static int fts3SnippetNextCandidate(SnippetIter *pIter){
int i; /* Loop counter */
if( pIter->iCurrent<0 ){
/* The SnippetIter object has just been initialized. The first snippet
** candidate always starts at offset 0 (even if this candidate has a
** score of 0.0).
*/
pIter->iCurrent = 0;
memcpy(&pStr->z[pStr->n], zAppend, nAppend);
pStr->n += nAppend;
pStr->z[pStr->n] = '\0';
return SQLITE_OK;
}
/*
** The fts3BestSnippet() function often selects snippets that end with a
** query term. That is, the final term of the snippet is always a term
** that requires highlighting. For example, if 'X' is a highlighted term
** and '.' is a non-highlighted term, BestSnippet() may select:
**
** ........X.....X
**
** This function "shifts" the beginning of the snippet forward in the
** document so that there are approximately the same number of
** non-highlighted terms to the right of the final highlighted term as there
** are to the left of the first highlighted term. For example, to this:
**
** ....X.....X....
**
** This is done as part of extracting the snippet text, not when selecting
** the snippet. Snippet selection is done based on doclists only, so there
** is no way for fts3BestSnippet() to know whether or not the document
** actually contains terms that follow the final highlighted term.
*/
static int fts3SnippetShift(
Fts3Table *pTab, /* FTS3 table snippet comes from */
int iLangid, /* Language id to use in tokenizing */
int nSnippet, /* Number of tokens desired for snippet */
const char *zDoc, /* Document text to extract snippet from */
int nDoc, /* Size of buffer zDoc in bytes */
int *piPos, /* IN/OUT: First token of snippet */
u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */
){
u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */
if( hlmask ){
int nLeft; /* Tokens to the left of first highlight */
int nRight; /* Tokens to the right of last highlight */
int nDesired; /* Ideal number of tokens to shift forward */
for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 );
nDesired = (nLeft-nRight)/2;
/* Ideally, the start of the snippet should be pushed forward in the
** document nDesired tokens. This block checks if there are actually
** nDesired tokens to the right of the snippet. If so, *piPos and
** *pHlMask are updated to shift the snippet nDesired tokens to the
** right. Otherwise, the snippet is shifted by the number of tokens
** available.
*/
if( nDesired>0 ){
int nShift; /* Number of tokens to shift snippet by */
int iCurrent = 0; /* Token counter */
int rc; /* Return Code */
sqlite3_tokenizer_module *pMod;
sqlite3_tokenizer_cursor *pC;
pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
/* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired)
** or more tokens in zDoc/nDoc.
*/
rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC);
if( rc!=SQLITE_OK ){
return rc;
}
while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0;
rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
}
pMod->xClose(pC);
if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; }
nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet;
assert( nShift<=nDesired );
if( nShift>0 ){
*piPos += nShift;
*pHlmask = hlmask >> nShift;
}
}
}
return SQLITE_OK;
}
/*
** Extract the snippet text for fragment pFragment from cursor pCsr and
** append it to string buffer pOut.
*/
static int fts3SnippetText(
Fts3Cursor *pCsr, /* FTS3 Cursor */
SnippetFragment *pFragment, /* Snippet to extract */
int iFragment, /* Fragment number */
int isLast, /* True for final fragment in snippet */
int nSnippet, /* Number of tokens in extracted snippet */
const char *zOpen, /* String inserted before highlighted term */
const char *zClose, /* String inserted after highlighted term */
const char *zEllipsis, /* String inserted between snippets */
StrBuffer *pOut /* Write output here */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc; /* Return code */
const char *zDoc; /* Document text to extract snippet from */
int nDoc; /* Size of zDoc in bytes */
int iCurrent = 0; /* Current token number of document */
int iEnd = 0; /* Byte offset of end of current token */
int isShiftDone = 0; /* True after snippet is shifted */
int iPos = pFragment->iPos; /* First token of snippet */
u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */
int iCol = pFragment->iCol+1; /* Query column to extract text from */
sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */
zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
if( zDoc==0 ){
if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){
return SQLITE_NOMEM;
}
return SQLITE_OK;
}
nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol);
/* Open a token cursor on the document. */
pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule;
rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC);
if( rc!=SQLITE_OK ){
return rc;
}
while( rc==SQLITE_OK ){
const char *ZDUMMY; /* Dummy argument used with tokenizer */
int DUMMY1 = -1; /* Dummy argument used with tokenizer */
int iBegin = 0; /* Offset in zDoc of start of token */
int iFin = 0; /* Offset in zDoc of end of token */
int isHighlight = 0; /* True for highlighted terms */
/* Variable DUMMY1 is initialized to a negative value above. Elsewhere
** in the FTS code the variable that the third argument to xNext points to
** is initialized to zero before the first (*but not necessarily
** subsequent*) call to xNext(). This is done for a particular application
** that needs to know whether or not the tokenizer is being used for
** snippet generation or for some other purpose.
**
** Extreme care is required when writing code to depend on this
** initialization. It is not a documented part of the tokenizer interface.
** If a tokenizer is used directly by any code outside of FTS, this
** convention might not be respected. */
rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
/* Special case - the last token of the snippet is also the last token
** of the column. Append any punctuation that occurred between the end
** of the previous token and the end of the document to the output.
** Then break out of the loop. */
rc = fts3StringAppend(pOut, &zDoc[iEnd], -1);
}
break;
}
if( iCurrent<iPos ){ continue; }
if( !isShiftDone ){
int n = nDoc - iBegin;
rc = fts3SnippetShift(
pTab, pCsr->iLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask
);
isShiftDone = 1;
/* Now that the shift has been done, check if the initial "..." are
** required. They are required if (a) this is not the first fragment,
** or (b) this fragment does not begin at position 0 of its column.
*/
if( rc==SQLITE_OK ){
if( iPos>0 || iFragment>0 ){
rc = fts3StringAppend(pOut, zEllipsis, -1);
}else if( iBegin ){
rc = fts3StringAppend(pOut, zDoc, iBegin);
}
}
if( rc!=SQLITE_OK || iCurrent<iPos ) continue;
}
if( iCurrent>=(iPos+nSnippet) ){
if( isLast ){
pIt->iPos = pIt->iPosOffset;
fts3LcsIteratorAdvance(pIt);
if( pIt->pRead==0 ){
rc = FTS_CORRUPT_VTAB;
goto matchinfo_lcs_out;
}
nLive++;
}
}
while( nLive>0 ){
LcsIterator *pAdv = 0; /* The iterator to advance by one position */
int nThisLcs = 0; /* LCS for the current iterator positions */
for(i=0; i<pInfo->nPhrase; i++){
LcsIterator *pIter = &aIter[i];
if( pIter->pRead==0 ){
/* This iterator is already at EOF for this column. */
nThisLcs = 0;
}else{
if( pAdv==0 || pIter->iPos<pAdv->iPos ){
pAdv = pIter;
}
if( nThisLcs==0 || pIter->iPos==pIter[-1].iPos ){
nThisLcs++;
}else{
nThisLcs = 1;
}
if( nThisLcs>nLcs ) nLcs = nThisLcs;
}
}
if( fts3LcsIteratorAdvance(pAdv) ) nLive--;
}
pInfo->aMatchinfo[iCol] = nLcs;
}
matchinfo_lcs_out:
sqlite3_free(aIter);
return rc;
}
/*
** Populate the buffer pInfo->aMatchinfo[] with an array of integers to
** be returned by the matchinfo() function. Argument zArg contains the
** format string passed as the second argument to matchinfo (or the
** default value "pcx" if no second argument was specified). The format
** string has already been validated and the pInfo->aMatchinfo[] array
** is guaranteed to be large enough for the output.
**
** If bGlobal is true, then populate all fields of the matchinfo() output.
** If it is false, then assume that those fields that do not change between
** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS)
** have already been populated.
**
** Return SQLITE_OK if successful, or an SQLite error code if an error
** occurs. If a value other than SQLITE_OK is returned, the state the
** pInfo->aMatchinfo[] buffer is left in is undefined.
*/
static int fts3MatchinfoValues(
Fts3Cursor *pCsr, /* FTS3 cursor object */
int bGlobal, /* True to grab the global stats */
MatchInfo *pInfo, /* Matchinfo context object */
const char *zArg /* Matchinfo format string */
){
int rc = SQLITE_OK;
int i;
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
sqlite3_stmt *pSelect = 0;
for(i=0; rc==SQLITE_OK && zArg[i]; i++){
pInfo->flag = zArg[i];
switch( zArg[i] ){
case FTS3_MATCHINFO_NPHRASE:
if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase;
break;
case FTS3_MATCHINFO_NCOL:
if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol;
break;
case FTS3_MATCHINFO_NDOC:
if( bGlobal ){
sqlite3_int64 nDoc = 0;
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0);
pInfo->aMatchinfo[0] = (u32)nDoc;
}
break;
case FTS3_MATCHINFO_AVGLENGTH:
if( bGlobal ){
sqlite3_int64 nDoc; /* Number of rows in table */
const char *a; /* Aggregate column length array */
const char *pEnd; /* First byte past end of length array */
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd);
if( rc==SQLITE_OK ){
int iCol;
for(iCol=0; iCol<pInfo->nCol; iCol++){
u32 iVal;
sqlite3_int64 nToken;
a += sqlite3Fts3GetVarint(a, &nToken);
if( a>pEnd ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
pInfo->aMatchinfo[iCol] = iVal;
}
}
}
break;
case FTS3_MATCHINFO_LENGTH: {
sqlite3_stmt *pSelectDocsize = 0;
rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize);
if( rc==SQLITE_OK ){
int iCol;
const char *a = sqlite3_column_blob(pSelectDocsize, 0);
const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0);
for(iCol=0; iCol<pInfo->nCol; iCol++){
** restart it as a regular, non-incremental query. Return SQLITE_OK
** if successful, or an SQLite error code otherwise.
*/
static int fts3ExprRestartIfCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
TermOffsetCtx *p = (TermOffsetCtx*)ctx;
int rc = SQLITE_OK;
UNUSED_PARAMETER(iPhrase);
if( pExpr->pPhrase && pExpr->pPhrase->bIncr ){
rc = sqlite3Fts3MsrCancel(p->pCsr, pExpr);
pExpr->pPhrase->bIncr = 0;
}
return rc;
}
/*
** Implementation of offsets() function.
*/
SQLITE_PRIVATE void sqlite3Fts3Offsets(
sqlite3_context *pCtx, /* SQLite function call context */
Fts3Cursor *pCsr /* Cursor object */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
int rc; /* Return Code */
int nToken; /* Number of tokens in query */
int iCol; /* Column currently being processed */
StrBuffer res = {0, 0, 0}; /* Result string */
TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */
if( !pCsr->pExpr ){
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
return;
}
memset(&sCtx, 0, sizeof(sCtx));
assert( pCsr->isRequireSeek==0 );
/* Count the number of terms in the query */
rc = fts3ExprLoadDoclists(pCsr, 0, &nToken);
if( rc!=SQLITE_OK ) goto offsets_out;
/* Allocate the array of TermOffset iterators. */
sCtx.aTerm = (TermOffset *)sqlite3Fts3MallocZero(sizeof(TermOffset)*nToken);
if( 0==sCtx.aTerm ){
rc = SQLITE_NOMEM;
goto offsets_out;
}
sCtx.iDocid = pCsr->iPrevId;
sCtx.pCsr = pCsr;
/* If a query restart will be required, do it here, rather than later of
** after pointers to poslist buffers that may be invalidated by a restart
** have been saved. */
rc = sqlite3Fts3ExprIterate(pCsr->pExpr, fts3ExprRestartIfCb, (void*)&sCtx);
if( rc!=SQLITE_OK ) goto offsets_out;
/* Loop through the table columns, appending offset information to
** string-buffer res for each column.
*/
for(iCol=0; iCol<pTab->nColumn; iCol++){
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
const char *ZDUMMY; /* Dummy argument used with xNext() */
int NDUMMY = 0; /* Dummy argument used with xNext() */
int iStart = 0;
int iEnd = 0;
int iCurrent = 0;
const char *zDoc;
int nDoc;
/* Initialize the contents of sCtx.aTerm[] for column iCol. This
** operation may fail if the database contains corrupt records.
*/
sCtx.iCol = iCol;
sCtx.iTerm = 0;
rc = sqlite3Fts3ExprIterate(
pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx
);
if( rc!=SQLITE_OK ) goto offsets_out;
/* Retreive the text stored in column iCol. If an SQL NULL is stored
** in column iCol, jump immediately to the next iteration of the loop.
** If an OOM occurs while retrieving the data (this can happen if SQLite
** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM
** to the caller.
*/
zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1);
nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
if( zDoc==0 ){
if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){
continue;
}
rc = SQLITE_NOMEM;
goto offsets_out;
}
/* Initialize a tokenizer iterator to iterate through column iCol. */
rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid,
zDoc, nDoc, &pC
);
if( rc!=SQLITE_OK ) goto offsets_out;
rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
while( rc==SQLITE_OK ){
int i; /* Used to loop through terms */
int iMinPos = 0x7FFFFFFF; /* Position of next token */
TermOffset *pTerm = 0; /* TermOffset associated with next token */
for(i=0; i<nToken; i++){
TermOffset *pT = &sCtx.aTerm[i];
if( pT->pList && (pT->iPos-pT->iOff)<iMinPos ){
iMinPos = pT->iPos-pT->iOff;
pTerm = pT;
}
}
if( !pTerm ){
/* All offsets for this column have been gathered. */
rc = SQLITE_DONE;
}else{
assert_fts3_nc( iCurrent<=iMinPos );
if( 0==(0xFE&*pTerm->pList) ){
pTerm->pList = 0;
}else{
fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos);
}
while( rc==SQLITE_OK && iCurrent<iMinPos ){
rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
}
if( rc==SQLITE_OK ){
char aBuffer[64];
sqlite3_snprintf(sizeof(aBuffer), aBuffer,
"%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
);
rc = fts3StringAppend(&res, aBuffer, -1);
}else if( rc==SQLITE_DONE && pTab->zContentTbl==0 ){
rc = FTS_CORRUPT_VTAB;
}
}
}
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
}
pMod->xClose(pC);
if( rc!=SQLITE_OK ) goto offsets_out;
}
offsets_out:
sqlite3_free(sCtx.aTerm);
assert( rc!=SQLITE_DONE );
sqlite3Fts3SegmentsClose(pTab);
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pCtx, rc);
sqlite3_free(res.z);
}else{
sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free);
}
return;
}
/*
** Implementation of matchinfo() function.
*/
SQLITE_PRIVATE void sqlite3Fts3Matchinfo(
sqlite3_context *pContext, /* Function call context */
Fts3Cursor *pCsr, /* FTS3 table cursor */
const char *zArg /* Second arg to matchinfo() function */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
const char *zFormat;
if( zArg ){
zFormat = zArg;
}else{
zFormat = FTS3_MATCHINFO_DEFAULT;
}
if( !pCsr->pExpr ){
sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC);
return;
}else{
/* Retrieve matchinfo() data. */
fts3GetMatchinfo(pContext, pCsr, zFormat);
sqlite3Fts3SegmentsClose(pTab);
}
}
#endif
/************** End of fts3_snippet.c ****************************************/
/************** Begin file fts3_unicode.c ************************************/
/*
** 2012 May 24
**
** 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.
**
******************************************************************************
**
** Implementation of the "unicode" full-text-search tokenizer.
*/
#ifndef SQLITE_DISABLE_FTS3_UNICODE
/* #include "fts3Int.h" */
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/* #include <assert.h> */
/* #include <stdlib.h> */
/* #include <stdio.h> */
/* #include <string.h> */
/* #include "fts3_tokenizer.h" */
/*
** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
** from the sqlite3 source file utf.c. If this file is compiled as part
** of the amalgamation, they are not required.
*/
#ifndef SQLITE_AMALGAMATION
static const unsigned char sqlite3Utf8Trans1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
};
#define READ_UTF8(zIn, zTerm, c) \
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
if( c<0x80 \
|| (c&0xFFFFF800)==0xD800 \
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
}
#define WRITE_UTF8(zOut, c) { \
if( c<0x00080 ){ \
*zOut++ = (u8)(c&0xFF); \
} \
else if( c<0x00800 ){ \
*zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
*zOut++ = 0x80 + (u8)(c & 0x3F); \
} \
else if( c<0x10000 ){ \
*zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
*zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
*zOut++ = 0x80 + (u8)(c & 0x3F); \
}else{ \
*zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
*zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
*zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
*zOut++ = 0x80 + (u8)(c & 0x3F); \
} \
}
#endif /* ifndef SQLITE_AMALGAMATION */
typedef struct unicode_tokenizer unicode_tokenizer;
typedef struct unicode_cursor unicode_cursor;
struct unicode_tokenizer {
sqlite3_tokenizer base;
int eRemoveDiacritic;
int nException;
int *aiException;
};
struct unicode_cursor {
sqlite3_tokenizer_cursor base;
const unsigned char *aInput; /* Input text being tokenized */
int nInput; /* Size of aInput[] in bytes */
int iOff; /* Current offset within aInput[] */
int iToken; /* Index of next token to be returned */
char *zToken; /* storage for current token */
int nAlloc; /* space allocated at zToken */
};
/*
** Destroy a tokenizer allocated by unicodeCreate().
*/
static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
if( pTokenizer ){
unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer;
sqlite3_free(p->aiException);
sqlite3_free(p);
}
return SQLITE_OK;
}
/*
** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE
** statement has specified that the tokenizer for this table shall consider
** all characters in string zIn/nIn to be separators (if bAlnum==0) or
** token characters (if bAlnum==1).
**
** For each codepoint in the zIn/nIn string, this function checks if the
** sqlite3FtsUnicodeIsalnum() function already returns the desired result.
** If so, no action is taken. Otherwise, the codepoint is added to the
** unicode_tokenizer.aiException[] array. For the purposes of tokenization,
** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all
** codepoints in the aiException[] array.
**
** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
** It is not possible to change the behavior of the tokenizer with respect
** to these codepoints.
*/
static int unicodeAddExceptions(
unicode_tokenizer *p, /* Tokenizer to add exceptions to */
int bAlnum, /* Replace Isalnum() return value with this */
const char *zIn, /* Array of characters to make exceptions */
int nIn /* Length of z in bytes */
){
const unsigned char *z = (const unsigned char *)zIn;
const unsigned char *zTerm = &z[nIn];
unsigned int iCode;
int nEntry = 0;
assert( bAlnum==0 || bAlnum==1 );
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
assert( (sqlite3FtsUnicodeIsalnum((int)iCode) & 0xFFFFFFFE)==0 );
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
){
nEntry++;
}
** Return true if, for the purposes of tokenization, codepoint iCode is
** considered a token character (not a separator).
*/
static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode);
}
/*
** Create a new tokenizer instance.
*/
static int unicodeCreate(
int nArg, /* Size of array argv[] */
const char * const *azArg, /* Tokenizer creation arguments */
sqlite3_tokenizer **pp /* OUT: New tokenizer handle */
){
unicode_tokenizer *pNew; /* New tokenizer object */
int i;
int rc = SQLITE_OK;
pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
if( pNew==NULL ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(unicode_tokenizer));
pNew->eRemoveDiacritic = 1;
for(i=0; rc==SQLITE_OK && i<nArg; i++){
const char *z = azArg[i];
int n = (int)strlen(z);
if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
pNew->eRemoveDiacritic = 1;
}
else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
pNew->eRemoveDiacritic = 0;
}
else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){
pNew->eRemoveDiacritic = 2;
}
else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
}
else if( n>=11 && memcmp("separators=", z, 11)==0 ){
rc = unicodeAddExceptions(pNew, 0, &z[11], n-11);
}
else{
/* Unrecognized argument */
rc = SQLITE_ERROR;
}
}
if( rc!=SQLITE_OK ){
unicodeDestroy((sqlite3_tokenizer *)pNew);
pNew = 0;
}
*pp = (sqlite3_tokenizer *)pNew;
return rc;
}
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is pInput[0..nBytes-1]. A cursor
** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int unicodeOpen(
sqlite3_tokenizer *p, /* The tokenizer */
const char *aInput, /* Input string */
int nInput, /* Size of string aInput in bytes */
sqlite3_tokenizer_cursor **pp /* OUT: New cursor object */
){
unicode_cursor *pCsr;
pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor));
if( pCsr==0 ){
return SQLITE_NOMEM;
}
memset(pCsr, 0, sizeof(unicode_cursor));
pCsr->aInput = (const unsigned char *)aInput;
if( aInput==0 ){
pCsr->nInput = 0;
pCsr->aInput = (const unsigned char*)"";
}else if( nInput<0 ){
pCsr->nInput = (int)strlen(aInput);
}else{
pCsr->nInput = nInput;
}
*pp = &pCsr->base;
UNUSED_PARAMETER(p);
return SQLITE_OK;
}
/*
** Close a tokenization cursor previously opened by a call to
** simpleOpen() above.
*/
static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){
unicode_cursor *pCsr = (unicode_cursor *) pCursor;
sqlite3_free(pCsr->zToken);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** Extract the next token from a tokenization cursor. The cursor must
** have been opened by a prior call to simpleOpen().
*/
static int unicodeNext(
sqlite3_tokenizer_cursor *pC, /* Cursor returned by simpleOpen */
const char **paToken, /* OUT: Token text */
int *pnToken, /* OUT: Number of bytes at *paToken */
int *piStart, /* OUT: Starting offset of token */
int *piEnd, /* OUT: Ending offset of token */
int *piPos /* OUT: Position integer of token */
){
unicode_cursor *pCsr = (unicode_cursor *)pC;
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
unsigned int iCode = 0;
char *zOut;
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
const unsigned char *zStart = z;
const unsigned char *zEnd;
const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
/* Scan past any delimiter characters before the start of the next token.
** Return SQLITE_DONE early if this takes us all the way to the end of
** the input. */
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
if( unicodeIsAlnum(p, (int)iCode) ) break;
zStart = z;
}
if( zStart>=zTerm ) return SQLITE_DONE;
zOut = pCsr->zToken;
do {
int iOut;
/* Grow the output buffer if required. */
if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64);
if( !zNew ) return SQLITE_NOMEM;
zOut = &zNew[zOut - pCsr->zToken];
pCsr->zToken = zNew;
pCsr->nAlloc += 64;
}
/* Write the folded case of the last character read to the output */
zEnd = z;
iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic);
if( iOut ){
WRITE_UTF8(zOut, iOut);
}
/* If the cursor is not at EOF, read the next character */
if( z>=zTerm ) break;
READ_UTF8(z, zTerm, iCode);
}while( unicodeIsAlnum(p, (int)iCode)
|| sqlite3FtsUnicodeIsdiacritic((int)iCode)
);
/* Set the output variables and return. */
pCsr->iOff = (int)(z - pCsr->aInput);
*paToken = pCsr->zToken;
*pnToken = (int)(zOut - pCsr->zToken);
*piStart = (int)(zStart - pCsr->aInput);
*piEnd = (int)(zEnd - pCsr->aInput);
*piPos = pCsr->iToken++;
return SQLITE_OK;
}
/*
** Set *ppModule to a pointer to the sqlite3_tokenizer_module
** structure for the unicode tokenizer.
*/
SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){
static const sqlite3_tokenizer_module module = {
0,
unicodeCreate,
unicodeDestroy,
unicodeOpen,
unicodeClose,
unicodeNext,
0,
};
*ppModule = &module;
}
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
#endif /* ifndef SQLITE_DISABLE_FTS3_UNICODE */
/************** End of fts3_unicode.c ****************************************/
/************** Begin file fts3_unicode2.c ***********************************/
/*
** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
*/
/*
** DO NOT EDIT THIS MACHINE GENERATED FILE.
*/
#ifndef SQLITE_DISABLE_FTS3_UNICODE
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
/* #include <assert.h> */
}
}
}
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
JsonString *pStr;
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
if( pStr ){
int flags;
jsonAppendChar(pStr, '}');
pStr->pCtx = ctx;
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
if( pStr->eErr ){
jsonReturnString(pStr, 0, 0);
return;
}else if( flags & JSON_BLOB ){
jsonReturnStringAsBlob(pStr);
if( isFinal ){
if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf);
}else{
jsonStringTrimOneChar(pStr);
}
return;
}else if( isFinal ){
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
pStr->bStatic ? SQLITE_TRANSIENT :
sqlite3RCStrUnref);
pStr->bStatic = 1;
}else{
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
jsonStringTrimOneChar(pStr);
}
}else{
sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
}
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
static void jsonObjectValue(sqlite3_context *ctx){
jsonObjectCompute(ctx, 0);
}
static void jsonObjectFinal(sqlite3_context *ctx){
jsonObjectCompute(ctx, 1);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/****************************************************************************
** The json_each virtual table
****************************************************************************/
typedef struct JsonParent JsonParent;
struct JsonParent {
u32 iHead; /* Start of object or array */
u32 iValue; /* Start of the value */
u32 iEnd; /* First byte past the end */
u32 nPath; /* Length of path */
i64 iKey; /* Key for JSONB_ARRAY */
};
typedef struct JsonEachCursor JsonEachCursor;
struct JsonEachCursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
u32 iRowid; /* The rowid */
u32 i; /* Index in sParse.aBlob[] of current row */
u32 iEnd; /* EOF when i equals or exceeds this value */
u32 nRoot; /* Size of the root path in bytes */
u8 eType; /* Type of the container for element i */
u8 bRecursive; /* True for json_tree(). False for json_each() */
u8 eMode; /* 1 for json_each(). 2 for jsonb_each() */
u32 nParent; /* Current nesting depth */
u32 nParentAlloc; /* Space allocated for aParent[] */
JsonParent *aParent; /* Parent elements of i */
sqlite3 *db; /* Database connection */
JsonString path; /* Current path */
JsonParse sParse; /* Parse of the input JSON */
};
typedef struct JsonEachConnection JsonEachConnection;
struct JsonEachConnection {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection */
u8 eMode; /* 1 for json_each(). 2 for jsonb_each() */
u8 bRecursive; /* True for json_tree(). False for json_each() */
};
/* Constructor for the json_each virtual table */
static int jsonEachConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
JsonEachConnection *pNew;
int rc;
/* Column numbers */
#define JEACH_KEY 0
#define JEACH_VALUE 1
#define JEACH_TYPE 2
#define JEACH_ATOM 3
#define JEACH_ID 4
#define JEACH_PARENT 5
#define JEACH_FULLKEY 6
#define JEACH_PATH 7
/* The xBestIndex method assumes that the JSON and ROOT columns are
** the last two columns in the table. Should this ever changes, be
** sure to update the xBestIndex method. */
#define JEACH_JSON 8
#define JEACH_ROOT 9
UNUSED_PARAMETER(pzErr);
UNUSED_PARAMETER(argv);
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(pAux);
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
"json HIDDEN,root HIDDEN)");
if( rc==SQLITE_OK ){
pNew = (JsonEachConnection*)sqlite3DbMallocZero(db, sizeof(*pNew));
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
pNew->db = db;
pNew->eMode = argv[0][4]=='b' ? 2 : 1;
pNew->bRecursive = argv[0][4+pNew->eMode]=='t';
}
return rc;
}
/* destructor for json_each virtual table */
static int jsonEachDisconnect(sqlite3_vtab *pVtab){
JsonEachConnection *p = (JsonEachConnection*)pVtab;
sqlite3DbFree(p->db, pVtab);
return SQLITE_OK;
}
/* constructor for a JsonEachCursor object for json_each()/json_tree(). */
static int jsonEachOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
JsonEachConnection *pVtab = (JsonEachConnection*)p;
JsonEachCursor *pCur;
UNUSED_PARAMETER(p);
pCur = sqlite3DbMallocZero(pVtab->db, sizeof(*pCur));
if( pCur==0 ) return SQLITE_NOMEM;
pCur->db = pVtab->db;
pCur->eMode = pVtab->eMode;
pCur->bRecursive = pVtab->bRecursive;
jsonStringZero(&pCur->path);
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/* Reset a JsonEachCursor back to its original state. Free any memory
** held. */
static void jsonEachCursorReset(JsonEachCursor *p){
jsonParseReset(&p->sParse);
jsonStringReset(&p->path);
sqlite3DbFree(p->db, p->aParent);
p->iRowid = 0;
p->i = 0;
p->aParent = 0;
p->nParent = 0;
p->nParentAlloc = 0;
p->iEnd = 0;
p->eType = 0;
}
/* Destructor for a jsonEachCursor object */
static int jsonEachClose(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
jsonEachCursorReset(p);
sqlite3DbFree(p->db, cur);
return SQLITE_OK;
}
/* Return TRUE if the jsonEachCursor object has been advanced off the end
** of the JSON object */
static int jsonEachEof(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
return p->i >= p->iEnd;
}
/*
** If the cursor is currently pointing at the label of a object entry,
** then return the index of the value. For all other cases, return the
** current pointer position, which is the value.
*/
static int jsonSkipLabel(JsonEachCursor *p){
if( p->eType==JSONB_OBJECT ){
u32 sz = 0;
u32 n = jsonbPayloadSize(&p->sParse, p->i, &sz);
return p->i + n + sz;
}else{
return p->i;
}
}
/*
** Append the path name for the current element.
*/
static void jsonAppendPathName(JsonEachCursor *p){
assert( p->nParent>0 );
assert( p->eType==JSONB_ARRAY || p->eType==JSONB_OBJECT );
if( p->eType==JSONB_ARRAY ){
jsonPrintf(30, &p->path, "[%lld]", p->aParent[p->nParent-1].iKey);
}else{
u32 n, sz = 0, k, i;
const char *z;
int needQuote = 0;
n = jsonbPayloadSize(&p->sParse, p->i, &sz);
k = p->i + n;
z = (const char*)&p->sParse.aBlob[k];
if( sz==0 || !sqlite3Isalpha(z[0]) ){
needQuote = 1;
}else{
for(i=0; i<sz; i++){
if( !sqlite3Isalnum(z[i]) ){
needQuote = 1;
break;
}
}
}
if( needQuote ){
jsonPrintf(sz+4,&p->path,".\"%.*s\"", sz, z);
}else{
jsonPrintf(sz+2,&p->path,".%.*s", sz, z);
}
}
}
/* Advance the cursor to the next element for json_tree() */
static int jsonEachNext(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
int rc = SQLITE_OK;
if( p->bRecursive ){
u8 x;
u8 levelChange = 0;
u32 n, sz = 0;
u32 i = jsonSkipLabel(p);
x = p->sParse.aBlob[i] & 0x0f;
n = jsonbPayloadSize(&p->sParse, i, &sz);
if( x==JSONB_OBJECT || x==JSONB_ARRAY ){
JsonParent *pParent;
if( p->nParent>=p->nParentAlloc ){
JsonParent *pNew;
u64 nNew;
nNew = p->nParentAlloc*2 + 3;
pNew = sqlite3DbRealloc(p->db, p->aParent, sizeof(JsonParent)*nNew);
if( pNew==0 ) return SQLITE_NOMEM;
p->nParentAlloc = (u32)nNew;
p->aParent = pNew;
}
levelChange = 1;
pParent = &p->aParent[p->nParent];
pParent->iHead = p->i;
pParent->iValue = i;
pParent->iEnd = i + n + sz;
pParent->iKey = -1;
pParent->nPath = (u32)p->path.nUsed;
if( p->eType && p->nParent ){
jsonAppendPathName(p);
if( p->path.eErr ) rc = SQLITE_NOMEM;
}
p->nParent++;
p->i = i + n;
}else{
p->i = i + n + sz;
}
while( p->nParent>0 && p->i >= p->aParent[p->nParent-1].iEnd ){
p->nParent--;
p->path.nUsed = p->aParent[p->nParent].nPath;
levelChange = 1;
}
if( levelChange ){
if( p->nParent>0 ){
JsonParent *pParent = &p->aParent[p->nParent-1];
u32 iVal = pParent->iValue;
p->eType = p->sParse.aBlob[iVal] & 0x0f;
}else{
p->eType = 0;
}
}
}else{
u32 n, sz = 0;
u32 i = jsonSkipLabel(p);
n = jsonbPayloadSize(&p->sParse, i, &sz);
p->i = i + n + sz;
}
if( p->eType==JSONB_ARRAY && p->nParent ){
p->aParent[p->nParent-1].iKey++;
}
p->iRowid++;
return rc;
}
/* Length of the path for rowid==0 in bRecursive mode.
*/
static int jsonEachPathLength(JsonEachCursor *p){
u32 n = p->path.nUsed;
char *z = p->path.zBuf;
if( p->iRowid==0 && p->bRecursive && n>=2 ){
while( n>1 ){
n--;
if( z[n]=='[' || z[n]=='.' ){
u32 x, sz = 0;
char cSaved = z[n];
z[n] = 0;
assert( p->sParse.eEdit==0 );
x = jsonLookupStep(&p->sParse, 0, z+1, 0);
z[n] = cSaved;
if( JSON_LOOKUP_ISERROR(x) ) continue;
if( x + jsonbPayloadSize(&p->sParse, x, &sz) == p->i ) break;
}
}
}
return n;
}
/* Return the value of a column */
static int jsonEachColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int iColumn /* Which column to return */
){
JsonEachCursor *p = (JsonEachCursor*)cur;
switch( iColumn ){
case JEACH_KEY: {
if( p->nParent==0 ){
u32 n, j;
if( p->nRoot==1 ) break;
j = jsonEachPathLength(p);
n = p->nRoot - j;
if( n==0 ){
break;
}else if( p->path.zBuf[j]=='[' ){
i64 x;
sqlite3Atoi64(&p->path.zBuf[j+1], &x, n-1, SQLITE_UTF8);
sqlite3_result_int64(ctx, x);
}else if( p->path.zBuf[j+1]=='"' ){
sqlite3_result_text(ctx, &p->path.zBuf[j+2], n-3, SQLITE_TRANSIENT);
}else{
sqlite3_result_text(ctx, &p->path.zBuf[j+1], n-1, SQLITE_TRANSIENT);
}
break;
}
if( p->eType==JSONB_OBJECT ){
jsonReturnFromBlob(&p->sParse, p->i, ctx, 1);
}else{
assert( p->eType==JSONB_ARRAY );
sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey);
}
break;
}
case JEACH_VALUE: {
u32 i = jsonSkipLabel(p);
jsonReturnFromBlob(&p->sParse, i, ctx, p->eMode);
if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
}
break;
}
case JEACH_TYPE: {
u32 i = jsonSkipLabel(p);
u8 eType = p->sParse.aBlob[i] & 0x0f;
sqlite3_result_text(ctx, jsonbType[eType], -1, SQLITE_STATIC);
break;
}
case JEACH_ATOM: {
u32 i = jsonSkipLabel(p);
if( (p->sParse.aBlob[i] & 0x0f)<JSONB_ARRAY ){
jsonReturnFromBlob(&p->sParse, i, ctx, 1);
}
break;
}
case JEACH_ID: {
sqlite3_result_int64(ctx, (sqlite3_int64)p->i);
break;
}
case JEACH_PARENT: {
if( p->nParent>0 && p->bRecursive ){
sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iHead);
}
break;
}
case JEACH_FULLKEY: {
u64 nBase = p->path.nUsed;
if( p->nParent ) jsonAppendPathName(p);
sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed,
SQLITE_TRANSIENT, SQLITE_UTF8);
p->path.nUsed = nBase;
break;
}
case JEACH_PATH: {
u32 n = jsonEachPathLength(p);
sqlite3_result_text64(ctx, p->path.zBuf, n,
SQLITE_TRANSIENT, SQLITE_UTF8);
break;
}
default: {
sqlite3_result_text(ctx, p->path.zBuf, p->nRoot, SQLITE_STATIC);
break;
}
case JEACH_JSON: {
if( p->sParse.zJson==0 ){
sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
SQLITE_TRANSIENT);
}else{
sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_TRANSIENT);
}
break;
}
}
return SQLITE_OK;
}
/* Return the current rowid value */
static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
JsonEachCursor *p = (JsonEachCursor*)cur;
*pRowid = p->iRowid;
return SQLITE_OK;
}
/* The query strategy is to look for an equality constraint on the json
** column. Without such a constraint, the table cannot operate. idxNum is
** 1 if the constraint is found, 3 if the constraint and zRoot are found,
** and 0 otherwise.
*/
static int jsonEachBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i; /* Loop counter or computed array index */
int aIdx[2]; /* Index of constraints for JSON and ROOT */
int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */
int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */
const struct sqlite3_index_constraint *pConstraint;
/* This implementation assumes that JSON and ROOT are the last two
** columns in the table */
assert( JEACH_ROOT == JEACH_JSON+1 );
UNUSED_PARAMETER(tab);
aIdx[0] = aIdx[1] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
int iCol;
int iMask;
if( pConstraint->iColumn < JEACH_JSON ) continue;
iCol = pConstraint->iColumn - JEACH_JSON;
assert( iCol==0 || iCol==1 );
testcase( iCol==0 );
iMask = 1 << iCol;
if( pConstraint->usable==0 ){
unusableMask |= iMask;
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
aIdx[iCol] = i;
idxMask |= iMask;
}
}
if( pIdxInfo->nOrderBy>0
&& pIdxInfo->aOrderBy[0].iColumn<0
&& pIdxInfo->aOrderBy[0].desc==0
){
pIdxInfo->orderByConsumed = 1;
}
if( (unusableMask & ~idxMask)!=0 ){
/* If there are any unusable constraints on JSON or ROOT, then reject
** this entire plan */
return SQLITE_CONSTRAINT;
}
if( aIdx[0]<0 ){
/* No JSON input. Leave estimatedCost at the huge value that it was
** initialized to to discourage the query planner from selecting this
** plan. */
pIdxInfo->idxNum = 0;
}else{
pIdxInfo->estimatedCost = 1.0;
i = aIdx[0];
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
pIdxInfo->aConstraintUsage[i].omit = 1;
if( aIdx[1]<0 ){
pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */
}else{
i = aIdx[1];
pIdxInfo->aConstraintUsage[i].argvIndex = 2;
pIdxInfo->aConstraintUsage[i].omit = 1;
pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */
}
}
return SQLITE_OK;
}
/* Start a search on a new JSON string */
static int jsonEachFilter(
sqlite3_vtab_cursor *cur,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
JsonEachCursor *p = (JsonEachCursor*)cur;
const char *zRoot = 0;
u32 i, n, sz;
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(argc);
jsonEachCursorReset(p);
if( idxNum==0 ) return SQLITE_OK;
memset(&p->sParse, 0, sizeof(p->sParse));
p->sParse.nJPRef = 1;
p->sParse.db = p->db;
if( jsonArgIsJsonb(argv[0], &p->sParse) ){
/* We have JSONB */
}else{
p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
p->sParse.nJson = sqlite3_value_bytes(argv[0]);
if( p->sParse.zJson==0 ){
p->i = p->iEnd = 0;
return SQLITE_OK;
}
if( jsonConvertTextToBlob(&p->sParse, 0) ){
if( p->sParse.oom ){
return SQLITE_NOMEM;
}
goto json_each_malformed_input;
}
}
if( idxNum==3 ){
zRoot = (const char*)sqlite3_value_text(argv[1]);
if( zRoot==0 ) return SQLITE_OK;
if( zRoot[0]!='$' ){
sqlite3_free(cur->pVtab->zErrMsg);
cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
jsonEachCursorReset(p);
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
p->nRoot = sqlite3Strlen30(zRoot);
if( zRoot[1]==0 ){
i = p->i = 0;
p->eType = 0;
}else{
i = jsonLookupStep(&p->sParse, 0, zRoot+1, 0);
if( JSON_LOOKUP_ISERROR(i) ){
if( i==JSON_LOOKUP_NOTFOUND ){
p->i = 0;
p->eType = 0;
p->iEnd = 0;
return SQLITE_OK;
}
sqlite3_free(cur->pVtab->zErrMsg);
cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot);
jsonEachCursorReset(p);
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
if( p->sParse.iLabel ){
p->i = p->sParse.iLabel;
p->eType = JSONB_OBJECT;
}else{
p->i = i;
p->eType = JSONB_ARRAY;
}
}
jsonAppendRaw(&p->path, zRoot, p->nRoot);
}else{
i = p->i = 0;
p->eType = 0;
p->nRoot = 1;
jsonAppendRaw(&p->path, "$", 1);
}
p->nParent = 0;
n = jsonbPayloadSize(&p->sParse, i, &sz);
p->iEnd = i+n+sz;
if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY && !p->bRecursive ){
p->i = i + n;
p->eType = p->sParse.aBlob[i] & 0x0f;
p->aParent = sqlite3DbMallocZero(p->db, sizeof(JsonParent));
if( p->aParent==0 ) return SQLITE_NOMEM;
p->nParent = 1;
p->nParentAlloc = 1;
p->aParent[0].iKey = 0;
p->aParent[0].iEnd = p->iEnd;
p->aParent[0].iHead = p->i;
p->aParent[0].iValue = i;
}
return SQLITE_OK;
json_each_malformed_input:
sqlite3_free(cur->pVtab->zErrMsg);
cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
jsonEachCursorReset(p);
return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
/* The methods of the json_each virtual table */
static sqlite3_module jsonEachModule = {
0, /* iVersion */
0, /* xCreate */
jsonEachConnect, /* xConnect */
jsonEachBestIndex, /* xBestIndex */
jsonEachDisconnect, /* xDisconnect */
0, /* xDestroy */
jsonEachOpen, /* xOpen - open a cursor */
jsonEachClose, /* xClose - close a cursor */
jsonEachFilter, /* xFilter - configure scan constraints */
jsonEachNext, /* xNext - advance a cursor */
jsonEachEof, /* xEof - check for end of scan */
jsonEachColumn, /* xColumn - read data */
jsonEachRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#endif /* !defined(SQLITE_OMIT_JSON) */
/*
** Register JSON functions.
*/
SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){
#ifndef SQLITE_OMIT_JSON
static FuncDef aJsonFunc[] = {
/* sqlite3_result_subtype() ----, ,--- sqlite3_value_subtype() */
/* | | */
/* Uses cache ------, | | ,---- Returns JSONB */
/* | | | | */
/* Number of arguments ---, | | | | ,--- Flags */
/* | | | | | | */
JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc),
JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc),
JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc),
JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc),
JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc),
JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc),
JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc),
JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc),
JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc),
JFUNCTION(->, 2,1,1, 0,0,JSON_JSON, jsonExtractFunc),
JFUNCTION(->>, 2,1,0, 0,0,JSON_SQL, jsonExtractFunc),
JFUNCTION(json_insert, -1,1,1, 1,0,0, jsonSetFunc),
JFUNCTION(jsonb_insert, -1,1,0, 1,1,0, jsonSetFunc),
JFUNCTION(json_object, -1,0,1, 1,0,0, jsonObjectFunc),
JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc),
JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc),
JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc),
JFUNCTION(json_pretty, 1,1,0, 0,0,0, jsonPrettyFunc),
JFUNCTION(json_pretty, 2,1,0, 0,0,0, jsonPrettyFunc),
JFUNCTION(json_quote, 1,0,1, 1,0,0, jsonQuoteFunc),
JFUNCTION(json_remove, -1,1,1, 0,0,0, jsonRemoveFunc),
JFUNCTION(jsonb_remove, -1,1,0, 0,1,0, jsonRemoveFunc),
JFUNCTION(json_replace, -1,1,1, 1,0,0, jsonReplaceFunc),
JFUNCTION(jsonb_replace, -1,1,0, 1,1,0, jsonReplaceFunc),
JFUNCTION(json_set, -1,1,1, 1,0,JSON_ISSET, jsonSetFunc),
JFUNCTION(jsonb_set, -1,1,0, 1,1,JSON_ISSET, jsonSetFunc),
JFUNCTION(json_type, 1,1,0, 0,0,0, jsonTypeFunc),
JFUNCTION(json_type, 2,1,0, 0,0,0, jsonTypeFunc),
JFUNCTION(json_valid, 1,1,0, 0,0,0, jsonValidFunc),
# define UNUSED_PARAMETER(x) (void)(x)
#endif
typedef struct Rtree Rtree;
typedef struct RtreeCursor RtreeCursor;
typedef struct RtreeNode RtreeNode;
typedef struct RtreeCell RtreeCell;
typedef struct RtreeConstraint RtreeConstraint;
typedef struct RtreeMatchArg RtreeMatchArg;
typedef struct RtreeGeomCallback RtreeGeomCallback;
typedef union RtreeCoord RtreeCoord;
typedef struct RtreeSearchPoint RtreeSearchPoint;
/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
#define RTREE_MAX_DIMENSIONS 5
/* Maximum number of auxiliary columns */
#define RTREE_MAX_AUX_COLUMN 100
/* Size of hash table Rtree.aHash. This hash table is not expected to
** ever contain very many entries, so a fixed number of buckets is
** used.
*/
#define HASHSIZE 97
/* The xBestIndex method of this virtual table requires an estimate of
** the number of rows in the virtual table to calculate the costs of
** various strategies. If possible, this estimate is loaded from the
** sqlite_stat1 table (with RTREE_MIN_ROWEST as a hard-coded minimum).
** Otherwise, if no sqlite_stat1 entry is available, use
** RTREE_DEFAULT_ROWEST.
*/
#define RTREE_DEFAULT_ROWEST 1048576
#define RTREE_MIN_ROWEST 100
/*
** An rtree virtual-table object.
*/
struct Rtree {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db; /* Host database connection */
int iNodeSize; /* Size in bytes of each node in the node table */
u8 nDim; /* Number of dimensions */
u8 nDim2; /* Twice the number of dimensions */
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
u8 nBytesPerCell; /* Bytes consumed per cell */
u8 inWrTrans; /* True if inside write transaction */
u8 nAux; /* # of auxiliary columns in %_rowid */
#ifdef SQLITE_ENABLE_GEOPOLY
u8 nAuxNotNull; /* Number of initial not-null aux columns */
#endif
#ifdef SQLITE_DEBUG
u8 bCorrupt; /* Shadow table corruption detected */
#endif
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
char *zName; /* Name of r-tree table */
char *zNodeName; /* Name of the %_node table */
u32 nBusy; /* Current number of users of this structure */
i64 nRowEst; /* Estimated number of rows in this table */
u32 nCursor; /* Number of open cursors */
u32 nNodeRef; /* Number RtreeNodes with positive nRef */
char *zReadAuxSql; /* SQL for statement to read aux data */
/* List of nodes removed during a CondenseTree operation. List is
** linked together via the pointer normally used for hash chains -
** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree
** headed by the node (leaf nodes have RtreeNode.iNode==0).
*/
RtreeNode *pDeleted;
/* Blob I/O on xxx_node */
sqlite3_blob *pNodeBlob;
/* Statements to read/write/delete a record from xxx_node */
sqlite3_stmt *pWriteNode;
sqlite3_stmt *pDeleteNode;
/* Statements to read/write/delete a record from xxx_rowid */
sqlite3_stmt *pReadRowid;
sqlite3_stmt *pWriteRowid;
sqlite3_stmt *pDeleteRowid;
/* Statements to read/write/delete a record from xxx_parent */
sqlite3_stmt *pReadParent;
sqlite3_stmt *pWriteParent;
sqlite3_stmt *pDeleteParent;
/* Statement for writing to the "aux:" fields, if there are any */
sqlite3_stmt *pWriteAux;
RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
};
/* Possible values for Rtree.eCoordType: */
#define RTREE_COORD_REAL32 0
#define RTREE_COORD_INT32 1
/*
** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will
** only deal with integer coordinates. No floating point operations
** will be done.
*/
#ifdef SQLITE_RTREE_INT_ONLY
typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */
typedef int RtreeValue; /* Low accuracy coordinate */
# define RTREE_ZERO 0
#else
typedef double RtreeDValue; /* High accuracy coordinate */
typedef float RtreeValue; /* Low accuracy coordinate */
# define RTREE_ZERO 0.0
#endif
/*
** Set the Rtree.bCorrupt flag
*/
#ifdef SQLITE_DEBUG
# define RTREE_IS_CORRUPT(X) ((X)->bCorrupt = 1)
#else
# define RTREE_IS_CORRUPT(X)
#endif
/*
** When doing a search of an r-tree, instances of the following structure
** record intermediate results from the tree walk.
**
** The id is always a node-id. For iLevel>=1 the id is the node-id of
** the node that the RtreeSearchPoint represents. When iLevel==0, however,
** the id is of the parent node and the cell that RtreeSearchPoint
** represents is the iCell-th entry in the parent node.
*/
struct RtreeSearchPoint {
RtreeDValue rScore; /* The score for this node. Smallest goes first. */
sqlite3_int64 id; /* Node ID */
u8 iLevel; /* 0=entries. 1=leaf node. 2+ for higher */
u8 eWithin; /* PARTLY_WITHIN or FULLY_WITHIN */
u8 iCell; /* Cell index within the node */
};
/*
** The minimum number of cells allowed for a node is a third of the
** maximum. In Gutman's notation:
**
** m = M/3
**
** If an R*-tree "Reinsert" operation is required, the same number of
** cells are removed from the overfull node and reinserted into the tree.
*/
#define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3)
#define RTREE_REINSERT(p) RTREE_MINCELLS(p)
#define RTREE_MAXCELLS 51
/*
** The smallest possible node-size is (512-64)==448 bytes. And the largest
** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates).
** Therefore all non-root nodes must contain at least 3 entries. Since
** 3^40 is greater than 2^64, an r-tree structure always has a depth of
** 40 or less.
*/
#define RTREE_MAX_DEPTH 40
/*
** Number of entries in the cursor RtreeNode cache. The first entry is
** used to cache the RtreeNode for RtreeCursor.sPoint. The remaining
** entries cache the RtreeNode for the first elements of the priority queue.
*/
#define RTREE_CACHE_SZ 5
/*
** An rtree cursor object.
*/
struct RtreeCursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
u8 atEOF; /* True if at end of search */
u8 bPoint; /* True if sPoint is valid */
u8 bAuxValid; /* True if pReadAux is valid */
int iStrategy; /* Copy of idxNum search parameter */
int nConstraint; /* Number of entries in aConstraint */
RtreeConstraint *aConstraint; /* Search constraints. */
int nPointAlloc; /* Number of slots allocated for aPoint[] */
int nPoint; /* Number of slots used in aPoint[] */
int mxLevel; /* iLevel value for root of the tree */
RtreeSearchPoint *aPoint; /* Priority queue for search points */
sqlite3_stmt *pReadAux; /* Statement to read aux-data */
RtreeSearchPoint sPoint; /* Cached next search point */
RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */
u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */
};
/* Return the Rtree of a RtreeCursor */
#define RTREE_OF_CURSOR(X) ((Rtree*)((X)->base.pVtab))
/*
** A coordinate can be either a floating point number or a integer. All
** coordinates within a single R-Tree are always of the same time.
*/
union RtreeCoord {
RtreeValue f; /* Floating point value */
int i; /* Integer value */
u32 u; /* Unsigned for byte-order conversions */
};
/*
** The argument is an RtreeCoord. Return the value stored within the RtreeCoord
** formatted as a RtreeDValue (double or int64). This macro assumes that local
** variable pRtree points to the Rtree structure associated with the
** RtreeCoord.
*/
#ifdef SQLITE_RTREE_INT_ONLY
# define DCOORD(coord) ((RtreeDValue)coord.i)
#else
# define DCOORD(coord) ( \
(pRtree->eCoordType==RTREE_COORD_REAL32) ? \
((double)coord.f) : \
((double)coord.i) \
)
#endif
/*
** A search constraint.
*/
struct RtreeConstraint {
int iCoord; /* Index of constrained coordinate */
int op; /* Constraining operation */
union {
RtreeDValue rValue; /* Constraint value. */
int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*);
int (*xQueryFunc)(sqlite3_rtree_query_info*);
} u;
sqlite3_rtree_query_info *pInfo; /* xGeom and xQueryFunc argument */
};
/* Possible values for RtreeConstraint.op */
#define RTREE_EQ 0x41 /* A */
#define RTREE_LE 0x42 /* B */
#define RTREE_LT 0x43 /* C */
#define RTREE_GE 0x44 /* D */
#define RTREE_GT 0x45 /* E */
#define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */
#define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */
/* Special operators available only on cursors. Needs to be consecutive
** with the normal values above, but must be less than RTREE_MATCH. These
** are used in the cursor for contraints such as x=NULL (RTREE_FALSE) or
** x<'xyz' (RTREE_TRUE) */
#define RTREE_TRUE 0x3f /* ? */
#define RTREE_FALSE 0x40 /* @ */
/*
** An rtree structure node.
*/
struct RtreeNode {
RtreeNode *pParent; /* Parent node */
i64 iNode; /* The node number */
int nRef; /* Number of references to this node */
int isDirty; /* True if the node needs to be written to disk */
u8 *zData; /* Content of the node, as should be on disk */
RtreeNode *pNext; /* Next node in this hash collision chain */
};
/* Return the number of cells in a node */
#define NCELL(pNode) readInt16(&(pNode)->zData[2])
/*
** A single cell from a node, deserialized
*/
struct RtreeCell {
i64 iRowid; /* Node or entry ID */
RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; /* Bounding box coordinates */
};
/*
** This object becomes the sqlite3_user_data() for the SQL functions
** that are created by sqlite3_rtree_geometry_callback() and
** sqlite3_rtree_query_callback() and which appear on the right of MATCH
** operators in order to constrain a search.
**
** xGeom and xQueryFunc are the callback functions. Exactly one of
** xGeom and xQueryFunc fields is non-NULL, depending on whether the
** SQL function was created using sqlite3_rtree_geometry_callback() or
** sqlite3_rtree_query_callback().
**
** This object is deleted automatically by the destructor mechanism in
** sqlite3_create_function_v2().
*/
struct RtreeGeomCallback {
int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
int (*xQueryFunc)(sqlite3_rtree_query_info*);
void (*xDestructor)(void*);
void *pContext;
};
/*
** An instance of this structure (in the form of a BLOB) is returned by
** the SQL functions that sqlite3_rtree_geometry_callback() and
** sqlite3_rtree_query_callback() create, and is read as the right-hand
** operand to the MATCH operator of an R-Tree.
*/
struct RtreeMatchArg {
u32 iSize; /* Size of this object */
RtreeGeomCallback cb; /* Info about the callback functions */
int nParam; /* Number of parameters to the SQL function */
sqlite3_value **apSqlParam; /* Original SQL parameter values */
static void rtreeRelease(Rtree *pRtree){
pRtree->nBusy--;
if( pRtree->nBusy==0 ){
pRtree->inWrTrans = 0;
assert( pRtree->nCursor==0 );
nodeBlobReset(pRtree);
assert( pRtree->nNodeRef==0 || pRtree->bCorrupt );
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
sqlite3_finalize(pRtree->pReadRowid);
sqlite3_finalize(pRtree->pWriteRowid);
sqlite3_finalize(pRtree->pDeleteRowid);
sqlite3_finalize(pRtree->pReadParent);
sqlite3_finalize(pRtree->pWriteParent);
sqlite3_finalize(pRtree->pDeleteParent);
sqlite3_finalize(pRtree->pWriteAux);
sqlite3_free(pRtree->zReadAuxSql);
sqlite3_free(pRtree);
}
}
/*
** Rtree virtual table module xDisconnect method.
*/
static int rtreeDisconnect(sqlite3_vtab *pVtab){
rtreeRelease((Rtree *)pVtab);
return SQLITE_OK;
}
/*
** Rtree virtual table module xDestroy method.
*/
static int rtreeDestroy(sqlite3_vtab *pVtab){
Rtree *pRtree = (Rtree *)pVtab;
int rc;
char *zCreate = sqlite3_mprintf(
"DROP TABLE '%q'.'%q_node';"
"DROP TABLE '%q'.'%q_rowid';"
"DROP TABLE '%q'.'%q_parent';",
pRtree->zDb, pRtree->zName,
pRtree->zDb, pRtree->zName,
pRtree->zDb, pRtree->zName
);
if( !zCreate ){
rc = SQLITE_NOMEM;
}else{
nodeBlobReset(pRtree);
rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0);
sqlite3_free(zCreate);
}
if( rc==SQLITE_OK ){
rtreeRelease(pRtree);
}
return rc;
}
/*
** Rtree virtual table module xOpen method.
*/
static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
int rc = SQLITE_NOMEM;
Rtree *pRtree = (Rtree *)pVTab;
RtreeCursor *pCsr;
pCsr = (RtreeCursor *)sqlite3_malloc64(sizeof(RtreeCursor));
if( pCsr ){
memset(pCsr, 0, sizeof(RtreeCursor));
pCsr->base.pVtab = pVTab;
rc = SQLITE_OK;
pRtree->nCursor++;
}
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return rc;
}
/*
** Reset a cursor back to its initial state.
*/
static void resetCursor(RtreeCursor *pCsr){
Rtree *pRtree = (Rtree *)(pCsr->base.pVtab);
int ii;
sqlite3_stmt *pStmt;
if( pCsr->aConstraint ){
int i; /* Used to iterate through constraint array */
for(i=0; i<pCsr->nConstraint; i++){
sqlite3_rtree_query_info *pInfo = pCsr->aConstraint[i].pInfo;
if( pInfo ){
if( pInfo->xDelUser ) pInfo->xDelUser(pInfo->pUser);
sqlite3_free(pInfo);
}
}
sqlite3_free(pCsr->aConstraint);
pCsr->aConstraint = 0;
}
for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
sqlite3_free(pCsr->aPoint);
pStmt = pCsr->pReadAux;
memset(pCsr, 0, sizeof(RtreeCursor));
pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
pCsr->pReadAux = pStmt;
/* The following will only fail if the previous sqlite3_step() call failed,
** in which case the error has already been caught. This statement never
** encounters an error within an sqlite3_column_xxx() function, as it
** calls sqlite3_column_value(), which does not use malloc(). So it is safe
** to ignore the error code here. */
sqlite3_reset(pStmt);
}
/*
** Rtree virtual table module xClose method.
*/
static int rtreeClose(sqlite3_vtab_cursor *cur){
Rtree *pRtree = (Rtree *)(cur->pVtab);
RtreeCursor *pCsr = (RtreeCursor *)cur;
assert( pRtree->nCursor>0 );
resetCursor(pCsr);
sqlite3_finalize(pCsr->pReadAux);
sqlite3_free(pCsr);
pRtree->nCursor--;
if( pRtree->nCursor==0 && pRtree->inWrTrans==0 ){
nodeBlobReset(pRtree);
}
return SQLITE_OK;
}
/*
** Rtree virtual table module xEof method.
**
** Return non-zero if the cursor does not currently point to a valid
** record (i.e if the scan has finished), or zero otherwise.
*/
static int rtreeEof(sqlite3_vtab_cursor *cur){
RtreeCursor *pCsr = (RtreeCursor *)cur;
return pCsr->atEOF;
}
/*
** Convert raw bits from the on-disk RTree record into a coordinate value.
** The on-disk format is big-endian and needs to be converted for little-
** endian platforms. The on-disk record stores integer coordinates if
** eInt is true and it stores 32-bit floating point records if eInt is
** false. a[] is the four bytes of the on-disk record to be decoded.
** Store the results in "r".
**
** There are five versions of this macro. The last one is generic. The
** other four are various architectures-specific optimizations.
*/
#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
c.u = _byteswap_ulong(*(u32*)a); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
c.u = __builtin_bswap32(*(u32*)a); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#elif SQLITE_BYTEORDER==1234
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
memcpy(&c.u,a,4); \
c.u = ((c.u>>24)&0xff)|((c.u>>8)&0xff00)| \
((c.u&0xff)<<24)|((c.u&0xff00)<<8); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#elif SQLITE_BYTEORDER==4321
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
memcpy(&c.u,a,4); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#else
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
c.u = ((u32)a[0]<<24) + ((u32)a[1]<<16) \
+((u32)a[2]<<8) + a[3]; \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#endif
/*
** Check the RTree node or entry given by pCellData and p against the MATCH
** constraint pConstraint.
*/
static int rtreeCallbackConstraint(
RtreeConstraint *pConstraint, /* The constraint to test */
int eInt, /* True if RTree holding integer coordinates */
u8 *pCellData, /* Raw cell content */
RtreeSearchPoint *pSearch, /* Container of this cell */
sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */
/*
** One of the cells in node pNode is guaranteed to have a 64-bit
** integer value equal to iRowid. Return the index of this cell.
*/
static int nodeRowidIndex(
Rtree *pRtree,
RtreeNode *pNode,
i64 iRowid,
int *piIndex
){
int ii;
int nCell = NCELL(pNode);
assert( nCell<200 );
for(ii=0; ii<nCell; ii++){
if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){
*piIndex = ii;
return SQLITE_OK;
}
}
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
/*
** Return the index of the cell containing a pointer to node pNode
** in its parent. If pNode is the root node, return -1.
*/
static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
RtreeNode *pParent = pNode->pParent;
if( ALWAYS(pParent) ){
return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
}else{
*piIndex = -1;
return SQLITE_OK;
}
}
/*
** Compare two search points. Return negative, zero, or positive if the first
** is less than, equal to, or greater than the second.
**
** The rScore is the primary key. Smaller rScore values come first.
** If the rScore is a tie, then use iLevel as the tie breaker with smaller
** iLevel values coming first. In this way, if rScore is the same for all
** SearchPoints, then iLevel becomes the deciding factor and the result
** is a depth-first search, which is the desired default behavior.
*/
static int rtreeSearchPointCompare(
const RtreeSearchPoint *pA,
const RtreeSearchPoint *pB
){
if( pA->rScore<pB->rScore ) return -1;
if( pA->rScore>pB->rScore ) return +1;
if( pA->iLevel<pB->iLevel ) return -1;
if( pA->iLevel>pB->iLevel ) return +1;
return 0;
}
/*
** Interchange two search points in a cursor.
*/
static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){
RtreeSearchPoint t = p->aPoint[i];
assert( i<j );
p->aPoint[i] = p->aPoint[j];
p->aPoint[j] = t;
i++; j++;
if( i<RTREE_CACHE_SZ ){
if( j>=RTREE_CACHE_SZ ){
nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]);
p->aNode[i] = 0;
}else{
RtreeNode *pTemp = p->aNode[i];
p->aNode[i] = p->aNode[j];
p->aNode[j] = pTemp;
}
}
}
/*
** Return the search point with the lowest current score.
*/
static RtreeSearchPoint *rtreeSearchPointFirst(RtreeCursor *pCur){
return pCur->bPoint ? &pCur->sPoint : pCur->nPoint ? pCur->aPoint : 0;
}
/*
** Get the RtreeNode for the search point with the lowest score.
*/
static RtreeNode *rtreeNodeOfFirstSearchPoint(RtreeCursor *pCur, int *pRC){
sqlite3_int64 id;
int ii = 1 - pCur->bPoint;
assert( ii==0 || ii==1 );
assert( pCur->bPoint || pCur->nPoint );
if( pCur->aNode[ii]==0 ){
assert( pRC!=0 );
id = ii ? pCur->aPoint[0].id : pCur->sPoint.id;
*pRC = nodeAcquire(RTREE_OF_CURSOR(pCur), id, 0, &pCur->aNode[ii]);
}
return pCur->aNode[ii];
}
/*
** Push a new element onto the priority queue
*/
static RtreeSearchPoint *rtreeEnqueue(
RtreeCursor *pCur, /* The cursor */
RtreeDValue rScore, /* Score for the new search point */
u8 iLevel /* Level for the new search point */
){
int i, j;
RtreeSearchPoint *pNew;
if( pCur->nPoint>=pCur->nPointAlloc ){
int nNew = pCur->nPointAlloc*2 + 8;
pNew = sqlite3_realloc64(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
if( pNew==0 ) return 0;
pCur->aPoint = pNew;
pCur->nPointAlloc = nNew;
}
i = pCur->nPoint++;
pNew = pCur->aPoint + i;
pNew->rScore = rScore;
pNew->iLevel = iLevel;
assert( iLevel<=RTREE_MAX_DEPTH );
while( i>0 ){
RtreeSearchPoint *pParent;
j = (i-1)/2;
pParent = pCur->aPoint + j;
if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break;
rtreeSearchPointSwap(pCur, j, i);
i = j;
pNew = pParent;
}
return pNew;
}
/*
** Allocate a new RtreeSearchPoint and return a pointer to it. Return
** NULL if malloc fails.
*/
static RtreeSearchPoint *rtreeSearchPointNew(
RtreeCursor *pCur, /* The cursor */
RtreeDValue rScore, /* Score for the new search point */
u8 iLevel /* Level for the new search point */
){
RtreeSearchPoint *pNew, *pFirst;
pFirst = rtreeSearchPointFirst(pCur);
pCur->anQueue[iLevel]++;
if( pFirst==0
|| pFirst->rScore>rScore
|| (pFirst->rScore==rScore && pFirst->iLevel>iLevel)
){
if( pCur->bPoint ){
int ii;
pNew = rtreeEnqueue(pCur, rScore, iLevel);
if( pNew==0 ) return 0;
ii = (int)(pNew - pCur->aPoint) + 1;
assert( ii==1 );
if( ALWAYS(ii<RTREE_CACHE_SZ) ){
assert( pCur->aNode[ii]==0 );
pCur->aNode[ii] = pCur->aNode[0];
}else{
nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]);
}
pCur->aNode[0] = 0;
*pNew = pCur->sPoint;
}
pCur->sPoint.rScore = rScore;
pCur->sPoint.iLevel = iLevel;
pCur->bPoint = 1;
return &pCur->sPoint;
}else{
return rtreeEnqueue(pCur, rScore, iLevel);
}
}
#if 0
/* Tracing routines for the RtreeSearchPoint queue */
static void tracePoint(RtreeSearchPoint *p, int idx, RtreeCursor *pCur){
if( idx<0 ){ printf(" s"); }else{ printf("%2d", idx); }
printf(" %d.%05lld.%02d %g %d",
p->iLevel, p->id, p->iCell, p->rScore, p->eWithin
);
idx++;
if( idx<RTREE_CACHE_SZ ){
printf(" %p\n", pCur->aNode[idx]);
}else{
printf("\n");
}
}
static void traceQueue(RtreeCursor *pCur, const char *zPrefix){
int ii;
printf("=== %9s ", zPrefix);
if( pCur->bPoint ){
tracePoint(&pCur->sPoint, -1, pCur);
}
for(ii=0; ii<pCur->nPoint; ii++){
if( ii>0 || pCur->bPoint ) printf(" ");
tracePoint(&pCur->aPoint[ii], ii, pCur);
}
}
# define RTREE_QUEUE_TRACE(A,B) traceQueue(A,B)
#else
# define RTREE_QUEUE_TRACE(A,B) /* no-op */
#endif
/* Remove the search point with the lowest current score.
*/
static void rtreeSearchPointPop(RtreeCursor *p){
int i, j, k, n;
i = 1 - p->bPoint;
assert( i==0 || i==1 );
if( p->aNode[i] ){
nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]);
p->aNode[i] = 0;
}
if( p->bPoint ){
p->anQueue[p->sPoint.iLevel]--;
p->bPoint = 0;
}else if( ALWAYS(p->nPoint) ){
p->anQueue[p->aPoint[0].iLevel]--;
n = --p->nPoint;
p->aPoint[0] = p->aPoint[n];
if( n<RTREE_CACHE_SZ-1 ){
p->aNode[1] = p->aNode[n+1];
p->aNode[n+1] = 0;
}
i = 0;
while( (j = i*2+1)<n ){
k = j+1;
if( k<n && rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[j])<0 ){
if( rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[i])<0 ){
rtreeSearchPointSwap(p, i, k);
i = k;
}else{
break;
}
}else{
if( rtreeSearchPointCompare(&p->aPoint[j], &p->aPoint[i])<0 ){
rtreeSearchPointSwap(p, i, j);
i = j;
}else{
break;
}
}
}
}
}
/*
** Continue the search on cursor pCur until the front of the queue
** contains an entry suitable for returning as a result-set row,
** or until the RtreeSearchPoint queue is empty, indicating that the
** query has completed.
*/
static int rtreeStepToLeaf(RtreeCursor *pCur){
RtreeSearchPoint *p;
Rtree *pRtree = RTREE_OF_CURSOR(pCur);
RtreeNode *pNode;
int eWithin;
int rc = SQLITE_OK;
int nCell;
int nConstraint = pCur->nConstraint;
int ii;
int eInt;
RtreeSearchPoint x;
eInt = pRtree->eCoordType==RTREE_COORD_INT32;
while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
u8 *pCellData;
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
if( rc ) return rc;
nCell = NCELL(pNode);
assert( nCell<200 );
pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
while( p->iCell<nCell ){
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
eWithin = FULLY_WITHIN;
for(ii=0; ii<nConstraint; ii++){
RtreeConstraint *pConstraint = pCur->aConstraint + ii;
if( pConstraint->op>=RTREE_MATCH ){
rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p,
&rScore, &eWithin);
if( rc ) return rc;
}else if( p->iLevel==1 ){
rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin);
}else{
rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin);
}
if( eWithin==NOT_WITHIN ){
p->iCell++;
pCellData += pRtree->nBytesPerCell;
break;
}
}
if( eWithin==NOT_WITHIN ) continue;
p->iCell++;
x.iLevel = p->iLevel - 1;
if( x.iLevel ){
x.id = readInt64(pCellData);
for(ii=0; ii<pCur->nPoint; ii++){
if( pCur->aPoint[ii].id==x.id ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
}
x.iCell = 0;
}else{
x.id = p->id;
x.iCell = p->iCell - 1;
}
if( p->iCell>=nCell ){
RTREE_QUEUE_TRACE(pCur, "POP-S:");
rtreeSearchPointPop(pCur);
}
if( rScore<RTREE_ZERO ) rScore = RTREE_ZERO;
p = rtreeSearchPointNew(pCur, rScore, x.iLevel);
if( p==0 ) return SQLITE_NOMEM;
p->eWithin = (u8)eWithin;
p->id = x.id;
p->iCell = x.iCell;
RTREE_QUEUE_TRACE(pCur, "PUSH-S:");
break;
}
if( p->iCell>=nCell ){
RTREE_QUEUE_TRACE(pCur, "POP-Se:");
rtreeSearchPointPop(pCur);
}
}
pCur->atEOF = p==0;
return SQLITE_OK;
}
/*
** Rtree virtual table module xNext method.
*/
static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
int rc = SQLITE_OK;
/* Move to the next entry that matches the configured constraints. */
RTREE_QUEUE_TRACE(pCsr, "POP-Nx:");
if( pCsr->bAuxValid ){
pCsr->bAuxValid = 0;
sqlite3_reset(pCsr->pReadAux);
}
rtreeSearchPointPop(pCsr);
rc = rtreeStepToLeaf(pCsr);
return rc;
}
/*
** Rtree virtual table module xRowid method.
*/
static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
int rc = SQLITE_OK;
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
if( rc==SQLITE_OK && ALWAYS(p) ){
if( p->iCell>=NCELL(pNode) ){
rc = SQLITE_ABORT;
}else{
*pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
}
}
return rc;
}
/*
** Rtree virtual table module xColumn method.
*/
static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
Rtree *pRtree = (Rtree *)cur->pVtab;
RtreeCursor *pCsr = (RtreeCursor *)cur;
RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
RtreeCoord c;
int rc = SQLITE_OK;
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
if( rc ) return rc;
if( NEVER(p==0) ) return SQLITE_OK;
if( p->iCell>=NCELL(pNode) ) return SQLITE_ABORT;
if( i==0 ){
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
}else if( i<=pRtree->nDim2 ){
nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
sqlite3_result_double(ctx, c.f);
}else
#endif
{
assert( pRtree->eCoordType==RTREE_COORD_INT32 );
sqlite3_result_int(ctx, c.i);
}
}else{
if( !pCsr->bAuxValid ){
if( pCsr->pReadAux==0 ){
rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0,
&pCsr->pReadAux, 0);
if( rc ) return rc;
}
sqlite3_bind_int64(pCsr->pReadAux, 1,
nodeGetRowid(pRtree, pNode, p->iCell));
rc = sqlite3_step(pCsr->pReadAux);
if( rc==SQLITE_ROW ){
pCsr->bAuxValid = 1;
}else{
sqlite3_reset(pCsr->pReadAux);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
return rc;
}
}
sqlite3_result_value(ctx,
sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1));
}
return SQLITE_OK;
}
/*
** Use nodeAcquire() to obtain the leaf node containing the record with
** rowid iRowid. If successful, set *ppLeaf to point to the node and
** return SQLITE_OK. If there is no such record in the table, set
** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf
** to zero and return an SQLite error code.
*/
static int findLeafNode(
Rtree *pRtree, /* RTree to search */
i64 iRowid, /* The rowid searching for */
RtreeNode **ppLeaf, /* Write the node here */
sqlite3_int64 *piNode /* Write the node-id here */
){
int rc;
*ppLeaf = 0;
sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid);
if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){
i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0);
if( piNode ) *piNode = iNode;
rc = nodeAcquire(pRtree, iNode, 0, ppLeaf);
sqlite3_reset(pRtree->pReadRowid);
}else{
rc = sqlite3_reset(pRtree->pReadRowid);
}
return rc;
}
/*
** This function is called to configure the RtreeConstraint object passed
** as the second argument for a MATCH constraint. The value passed as the
** first argument to this function is the right-hand operand to the MATCH
** operator.
*/
static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
RtreeMatchArg *pBlob, *pSrc; /* BLOB returned by geometry function */
sqlite3_rtree_query_info *pInfo; /* Callback information */
pSrc = sqlite3_value_pointer(pValue, "RtreeMatchArg");
if( pSrc==0 ) return SQLITE_ERROR;
pInfo = (sqlite3_rtree_query_info*)
sqlite3_malloc64( sizeof(*pInfo)+pSrc->iSize );
if( !pInfo ) return SQLITE_NOMEM;
memset(pInfo, 0, sizeof(*pInfo));
pBlob = (RtreeMatchArg*)&pInfo[1];
memcpy(pBlob, pSrc, pSrc->iSize);
pInfo->pContext = pBlob->cb.pContext;
pInfo->nParam = pBlob->nParam;
pInfo->aParam = pBlob->aParam;
pInfo->apSqlParam = pBlob->apSqlParam;
if( pBlob->cb.xGeom ){
pCons->u.xGeom = pBlob->cb.xGeom;
}else{
pCons->op = RTREE_QUERY;
pCons->u.xQueryFunc = pBlob->cb.xQueryFunc;
}
pCons->pInfo = pInfo;
return SQLITE_OK;
}
SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double);
/*
** Rtree virtual table module xFilter method.
*/
static int rtreeFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
RtreeNode *pRoot = 0;
int ii;
int rc = SQLITE_OK;
int iCell = 0;
rtreeReference(pRtree);
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
resetCursor(pCsr);
pCsr->iStrategy = idxNum;
if( idxNum==1 ){
/* Special case - lookup by rowid. */
RtreeNode *pLeaf; /* Leaf on which the required cell resides */
RtreeSearchPoint *p; /* Search point for the leaf */
i64 iRowid = sqlite3_value_int64(argv[0]);
i64 iNode = 0;
int eType = sqlite3_value_numeric_type(argv[0]);
if( eType==SQLITE_INTEGER
|| (eType==SQLITE_FLOAT
&& 0==sqlite3IntFloatCompare(iRowid,sqlite3_value_double(argv[0])))
){
rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
}else{
rc = SQLITE_OK;
pLeaf = 0;
}
if( rc==SQLITE_OK && pLeaf!=0 ){
p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
assert( p!=0 ); /* Always returns pCsr->sPoint */
pCsr->aNode[0] = pLeaf;
p->id = iNode;
p->eWithin = PARTLY_WITHIN;
rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
p->iCell = (u8)iCell;
RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
}else{
pCsr->atEOF = 1;
}
}else{
/* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
** with the configured constraints.
*/
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
if( rc==SQLITE_OK && argc>0 ){
pCsr->aConstraint = sqlite3_malloc64(sizeof(RtreeConstraint)*argc);
pCsr->nConstraint = argc;
if( !pCsr->aConstraint ){
rc = SQLITE_NOMEM;
}else{
memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc);
memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1));
assert( (idxStr==0 && argc==0)
|| (idxStr && (int)strlen(idxStr)==argc*2) );
for(ii=0; ii<argc; ii++){
RtreeConstraint *p = &pCsr->aConstraint[ii];
int eType = sqlite3_value_numeric_type(argv[ii]);
p->op = idxStr[ii*2];
p->iCoord = idxStr[ii*2+1]-'0';
if( p->op>=RTREE_MATCH ){
/* A MATCH operator. The right-hand-side must be a blob that
** can be cast into an RtreeMatchArg object. One created using
** an sqlite3_rtree_geometry_callback() SQL user function.
*/
rc = deserializeGeometry(argv[ii], p);
if( rc!=SQLITE_OK ){
break;
}
** (at pRtree->base.zErrMsg) to an appropriate value and returns
** SQLITE_CONSTRAINT.
**
** Parameter iCol is the index of the leftmost column involved in the
** constraint failure. If it is 0, then the constraint that failed is
** the unique constraint on the id column. Otherwise, it is the rtree
** (c1<=c2) constraint on columns iCol and iCol+1 that has failed.
**
** If an OOM occurs, SQLITE_NOMEM is returned instead of SQLITE_CONSTRAINT.
*/
static int rtreeConstraintError(Rtree *pRtree, int iCol){
sqlite3_stmt *pStmt = 0;
char *zSql;
int rc;
assert( iCol==0 || iCol%2 );
zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", pRtree->zDb, pRtree->zName);
if( zSql ){
rc = sqlite3_prepare_v2(pRtree->db, zSql, -1, &pStmt, 0);
}else{
rc = SQLITE_NOMEM;
}
sqlite3_free(zSql);
if( rc==SQLITE_OK ){
if( iCol==0 ){
const char *zCol = sqlite3_column_name(pStmt, 0);
pRtree->base.zErrMsg = sqlite3_mprintf(
"UNIQUE constraint failed: %s.%s", pRtree->zName, zCol
);
}else{
const char *zCol1 = sqlite3_column_name(pStmt, iCol);
const char *zCol2 = sqlite3_column_name(pStmt, iCol+1);
pRtree->base.zErrMsg = sqlite3_mprintf(
"rtree constraint failed: %s.(%s<=%s)", pRtree->zName, zCol1, zCol2
);
}
}
sqlite3_finalize(pStmt);
return (rc==SQLITE_OK ? SQLITE_CONSTRAINT : rc);
}
/*
** The xUpdate method for rtree module virtual tables.
*/
static int rtreeUpdate(
sqlite3_vtab *pVtab,
int nData,
sqlite3_value **aData,
sqlite_int64 *pRowid
){
Rtree *pRtree = (Rtree *)pVtab;
int rc = SQLITE_OK;
RtreeCell cell; /* New cell to insert if nData>1 */
int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
if( pRtree->nNodeRef ){
/* Unable to write to the btree while another cursor is reading from it,
** since the write might do a rebalance which would disrupt the read
** cursor. */
return SQLITE_LOCKED_VTAB;
}
rtreeReference(pRtree);
assert(nData>=1);
memset(&cell, 0, sizeof(cell));
/* Constraint handling. A write operation on an r-tree table may return
** SQLITE_CONSTRAINT for two reasons:
**
** 1. A duplicate rowid value, or
** 2. The supplied data violates the "x2>=x1" constraint.
**
** In the first case, if the conflict-handling mode is REPLACE, then
** the conflicting row can be removed before proceeding. In the second
** case, SQLITE_CONSTRAINT must be returned regardless of the
** conflict-handling mode specified by the user.
*/
if( nData>1 ){
int ii;
int nn = nData - 4;
if( nn > pRtree->nDim2 ) nn = pRtree->nDim2;
/* Populate the cell.aCoord[] array. The first coordinate is aData[3].
**
** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
** with "column" that are interpreted as table constraints.
** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
** This problem was discovered after years of use, so we silently ignore
** these kinds of misdeclared tables to avoid breaking any legacy.
*/
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
for(ii=0; ii<nn; ii+=2){
cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]);
cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]);
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
rc = rtreeConstraintError(pRtree, ii+1);
goto constraint;
}
}
}else
#endif
{
for(ii=0; ii<nn; ii+=2){
cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]);
cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]);
if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
rc = rtreeConstraintError(pRtree, ii+1);
goto constraint;
}
}
}
/* If a rowid value was supplied, check if it is already present in
** the table. If so, the constraint has failed. */
if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){
cell.iRowid = sqlite3_value_int64(aData[2]);
if( sqlite3_value_type(aData[0])==SQLITE_NULL
/*
** This function populates the pRtree->nRowEst variable with an estimate
** of the number of rows in the virtual table. If possible, this is based
** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
*/
static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
const char *zFmt = "SELECT stat FROM %Q.sqlite_stat1 WHERE tbl = '%q_rowid'";
char *zSql;
sqlite3_stmt *p;
int rc;
i64 nRow = RTREE_MIN_ROWEST;
rc = sqlite3_table_column_metadata(
db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
);
if( rc!=SQLITE_OK ){
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
return rc==SQLITE_ERROR ? SQLITE_OK : rc;
}
zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
if( rc==SQLITE_OK ){
if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
rc = sqlite3_finalize(p);
}
sqlite3_free(zSql);
}
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
return rc;
}
/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int rtreeShadowName(const char *zName){
static const char *azName[] = {
"node", "parent", "rowid"
};
unsigned int i;
for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
}
return 0;
}
/* Forward declaration */
static int rtreeIntegrity(sqlite3_vtab*, const char*, const char*, int, char**);
static sqlite3_module rtreeModule = {
4, /* iVersion */
rtreeCreate, /* xCreate - create a table */
rtreeConnect, /* xConnect - connect to an existing table */
rtreeBestIndex, /* xBestIndex - Determine search strategy */
rtreeDisconnect, /* xDisconnect - Disconnect from a table */
rtreeDestroy, /* xDestroy - Drop a table */
rtreeOpen, /* xOpen - open a cursor */
rtreeClose, /* xClose - close a cursor */
rtreeFilter, /* xFilter - configure scan constraints */
rtreeNext, /* xNext - advance a cursor */
rtreeEof, /* xEof */
rtreeColumn, /* xColumn - read data */
rtreeRowid, /* xRowid - read data */
rtreeUpdate, /* xUpdate - write data */
rtreeBeginTransaction, /* xBegin - begin transaction */
rtreeEndTransaction, /* xSync - sync transaction */
rtreeEndTransaction, /* xCommit - commit transaction */
rtreeRollback, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
rtreeRename, /* xRename - rename the table */
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
rtreeShadowName, /* xShadowName */
rtreeIntegrity /* xIntegrity */
};
static int rtreeSqlInit(
Rtree *pRtree,
sqlite3 *db,
const char *zDb,
const char *zPrefix,
int isCreate
){
int rc = SQLITE_OK;
#define N_STATEMENT 8
static const char *azSql[N_STATEMENT] = {
/* Write the xxx_node table */
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(?1, ?2)",
"DELETE FROM '%q'.'%q_node' WHERE nodeno = ?1",
/* Read and write the xxx_rowid table */
"SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = ?1",
"INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(?1, ?2)",
"DELETE FROM '%q'.'%q_rowid' WHERE rowid = ?1",
/* Read and write the xxx_parent table */
"SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1",
"INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)",
"DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1"
};
sqlite3_stmt **appStmt[N_STATEMENT];
int i;
const int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
pRtree->db = db;
if( isCreate ){
char *zCreate;
sqlite3_str *p = sqlite3_str_new(db);
int ii;
sqlite3_str_appendf(p,
"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno",
zDb, zPrefix);
for(ii=0; ii<pRtree->nAux; ii++){
sqlite3_str_appendf(p,",a%d",ii);
}
sqlite3_str_appendf(p,
");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);",
rc = getNodeSize(db, pRtree, isCreate, pzErr);
if( rc ) goto geopolyInit_fail;
rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate);
if( rc ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
goto geopolyInit_fail;
}
*ppVtab = (sqlite3_vtab *)pRtree;
return SQLITE_OK;
geopolyInit_fail:
if( rc==SQLITE_OK ) rc = SQLITE_ERROR;
assert( *ppVtab==0 );
assert( pRtree->nBusy==1 );
rtreeRelease(pRtree);
return rc;
}
/*
** GEOPOLY virtual table module xCreate method.
*/
static int geopolyCreate(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
}
/*
** GEOPOLY virtual table module xConnect method.
*/
static int geopolyConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0);
}
/*
** GEOPOLY virtual table module xFilter method.
**
** Query plans:
**
** 1 rowid lookup
** 2 search for objects overlapping the same bounding box
** that contains polygon argv[0]
** 3 search for objects overlapping the same bounding box
** that contains polygon argv[0]
** 4 full table scan
*/
static int geopolyFilter(
sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */
int idxNum, /* Query plan */
const char *idxStr, /* Not Used */
int argc, sqlite3_value **argv /* Parameters to the query plan */
){
Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
RtreeNode *pRoot = 0;
int rc = SQLITE_OK;
int iCell = 0;
(void)idxStr;
rtreeReference(pRtree);
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
resetCursor(pCsr);
pCsr->iStrategy = idxNum;
if( idxNum==1 ){
/* Special case - lookup by rowid. */
RtreeNode *pLeaf; /* Leaf on which the required cell resides */
RtreeSearchPoint *p; /* Search point for the leaf */
i64 iRowid = sqlite3_value_int64(argv[0]);
i64 iNode = 0;
rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
if( rc==SQLITE_OK && pLeaf!=0 ){
p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
assert( p!=0 ); /* Always returns pCsr->sPoint */
pCsr->aNode[0] = pLeaf;
p->id = iNode;
p->eWithin = PARTLY_WITHIN;
rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
p->iCell = (u8)iCell;
RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
}else{
pCsr->atEOF = 1;
}
}else{
/* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
** with the configured constraints.
*/
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
if( rc==SQLITE_OK && idxNum<=3 ){
RtreeCoord bbox[4];
RtreeConstraint *p;
assert( argc==1 );
assert( argv[0]!=0 );
geopolyBBox(0, argv[0], bbox, &rc);
if( rc ){
goto geopoly_filter_end;
}
pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4);
pCsr->nConstraint = 4;
if( p==0 ){
rc = SQLITE_NOMEM;
}else{
memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4);
memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1));
if( idxNum==2 ){
/* Overlap query */
p->op = 'B';
p->iCoord = 0;
p->u.rValue = bbox[1].f;
p++;
p->op = 'D';
p->iCoord = 1;
p->u.rValue = bbox[0].f;
p++;
p->op = 'B';
p->iCoord = 2;
p->u.rValue = bbox[3].f;
p++;
p->op = 'D';
p->iCoord = 3;
p->u.rValue = bbox[2].f;
** ------------------------------------------------
** 1 "rowid" Direct lookup by rowid.
** 2 "rtree" R-tree overlap query using geopoly_overlap()
** 3 "rtree" R-tree within query using geopoly_within()
** 4 "fullscan" full-table scan.
** ------------------------------------------------
*/
static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int ii;
int iRowidTerm = -1;
int iFuncTerm = -1;
int idxNum = 0;
(void)tab;
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
if( !p->usable ) continue;
if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
iRowidTerm = ii;
break;
}
if( p->iColumn==0 && p->op>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){
/* p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION for geopoly_overlap()
** p->op==(SQLITE_INDEX_CONTRAINT_FUNCTION+1) for geopoly_within().
** See geopolyFindFunction() */
iFuncTerm = ii;
idxNum = p->op - SQLITE_INDEX_CONSTRAINT_FUNCTION + 2;
}
}
if( iRowidTerm>=0 ){
pIdxInfo->idxNum = 1;
pIdxInfo->idxStr = "rowid";
pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1;
pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1;
pIdxInfo->estimatedCost = 30.0;
pIdxInfo->estimatedRows = 1;
pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
return SQLITE_OK;
}
if( iFuncTerm>=0 ){
pIdxInfo->idxNum = idxNum;
pIdxInfo->idxStr = "rtree";
pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1;
pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0;
pIdxInfo->estimatedCost = 300.0;
pIdxInfo->estimatedRows = 10;
return SQLITE_OK;
}
pIdxInfo->idxNum = 4;
pIdxInfo->idxStr = "fullscan";
pIdxInfo->estimatedCost = 3000000.0;
pIdxInfo->estimatedRows = 100000;
return SQLITE_OK;
}
/*
** GEOPOLY virtual table module xColumn method.
*/
static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
Rtree *pRtree = (Rtree *)cur->pVtab;
RtreeCursor *pCsr = (RtreeCursor *)cur;
RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
int rc = SQLITE_OK;
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
if( rc ) return rc;
if( p==0 ) return SQLITE_OK;
if( i==0 && sqlite3_vtab_nochange(ctx) ) return SQLITE_OK;
if( i<=pRtree->nAux ){
if( !pCsr->bAuxValid ){
if( pCsr->pReadAux==0 ){
rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0,
&pCsr->pReadAux, 0);
if( rc ) return rc;
}
sqlite3_bind_int64(pCsr->pReadAux, 1,
nodeGetRowid(pRtree, pNode, p->iCell));
rc = sqlite3_step(pCsr->pReadAux);
if( rc==SQLITE_ROW ){
pCsr->bAuxValid = 1;
}else{
sqlite3_reset(pCsr->pReadAux);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
return rc;
}
}
sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2));
}
return SQLITE_OK;
}
/*
** The xUpdate method for GEOPOLY module virtual tables.
**
** For DELETE:
**
** argv[0] = the rowid to be deleted
**
** For INSERT:
**
** argv[0] = SQL NULL
** argv[1] = rowid to insert, or an SQL NULL to select automatically
** argv[2] = _shape column
** argv[3] = first application-defined column....
**
** For UPDATE:
**
** argv[0] = rowid to modify. Never NULL
** argv[1] = rowid after the change. Never NULL
** argv[2] = new value for _shape
** argv[3] = new value for first application-defined column....
*/
static int geopolyUpdate(
sqlite3_vtab *pVtab,
int nData,
sqlite3_value **aData,
sqlite_int64 *pRowid
){
Rtree *pRtree = (Rtree *)pVtab;
int rc = SQLITE_OK;
RtreeCell cell; /* New cell to insert if nData>1 */
i64 oldRowid; /* The old rowid */
int oldRowidValid; /* True if oldRowid is valid */
i64 newRowid; /* The new rowid */
int newRowidValid; /* True if newRowid is valid */
int coordChange = 0; /* Change in coordinates */
if( pRtree->nNodeRef ){
/* Unable to write to the btree while another cursor is reading from it,
** since the write might do a rebalance which would disrupt the read
** cursor. */
return SQLITE_LOCKED_VTAB;
}
rtreeReference(pRtree);
assert(nData>=1);
oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;;
oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0;
newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL;
newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0;
cell.iRowid = newRowid;
if( nData>1 /* not a DELETE */
&& (!oldRowidValid /* INSERT */
|| !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */
|| oldRowid!=newRowid) /* Rowid change */
){
assert( aData[2]!=0 );
geopolyBBox(0, aData[2], cell.aCoord, &rc);
if( rc ){
if( rc==SQLITE_ERROR ){
pVtab->zErrMsg =
sqlite3_mprintf("_shape does not contain a valid polygon");
}
goto geopoly_update_end;
}
coordChange = 1;
/* If a rowid value was supplied, check if it is already present in
** the table. If so, the constraint has failed. */
if( newRowidValid && (!oldRowidValid || oldRowid!=newRowid) ){
int steprc;
sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
steprc = sqlite3_step(pRtree->pReadRowid);
rc = sqlite3_reset(pRtree->pReadRowid);
if( SQLITE_ROW==steprc ){
if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){
rc = rtreeDeleteRowid(pRtree, cell.iRowid);
}else{
rc = rtreeConstraintError(pRtree, 0);
}
}
}
}
/* If aData[0] is not an SQL NULL value, it is the rowid of a
** record to delete from the r-tree table. The following block does
** just that.
*/
if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){
rc = rtreeDeleteRowid(pRtree, oldRowid);
}
/* If the aData[] array contains more than one element, elements
** (aData[2]..aData[argc-1]) contain a new record to insert into
** the r-tree structure.
*/
if( rc==SQLITE_OK && nData>1 && coordChange ){
/* Insert the new record into the r-tree */
RtreeNode *pLeaf = 0;
if( !newRowidValid ){
if( sqlite3_value_type(aData[2])==SQLITE_TEXT
&& (p = geopolyFuncParam(0, aData[2], &rc))!=0
&& rc==SQLITE_OK
){
sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT);
}else{
sqlite3_bind_value(pUp, 2, aData[2]);
}
sqlite3_free(p);
nChange = 1;
}
for(jj=1; jj<nData-2; jj++){
nChange++;
sqlite3_bind_value(pUp, jj+2, aData[jj+2]);
}
if( nChange ){
sqlite3_step(pUp);
rc = sqlite3_reset(pUp);
}
}
geopoly_update_end:
rtreeRelease(pRtree);
return rc;
}
/*
** Report that geopoly_overlap() is an overloaded function suitable
** for use in xBestIndex.
*/
static int geopolyFindFunction(
sqlite3_vtab *pVtab,
int nArg,
const char *zName,
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg
){
(void)pVtab;
(void)nArg;
if( sqlite3_stricmp(zName, "geopoly_overlap")==0 ){
*pxFunc = geopolyOverlapFunc;
*ppArg = 0;
return SQLITE_INDEX_CONSTRAINT_FUNCTION;
}
if( sqlite3_stricmp(zName, "geopoly_within")==0 ){
*pxFunc = geopolyWithinFunc;
*ppArg = 0;
return SQLITE_INDEX_CONSTRAINT_FUNCTION+1;
}
return 0;
}
static sqlite3_module geopolyModule = {
3, /* iVersion */
geopolyCreate, /* xCreate - create a table */
geopolyConnect, /* xConnect - connect to an existing table */
geopolyBestIndex, /* xBestIndex - Determine search strategy */
rtreeDisconnect, /* xDisconnect - Disconnect from a table */
rtreeDestroy, /* xDestroy - Drop a table */
rtreeOpen, /* xOpen - open a cursor */
rtreeClose, /* xClose - close a cursor */
geopolyFilter, /* xFilter - configure scan constraints */
rtreeNext, /* xNext - advance a cursor */
rtreeEof, /* xEof */
geopolyColumn, /* xColumn - read data */
rtreeRowid, /* xRowid - read data */
geopolyUpdate, /* xUpdate - write data */
rtreeBeginTransaction, /* xBegin - begin transaction */
rtreeEndTransaction, /* xSync - sync transaction */
rtreeEndTransaction, /* xCommit - commit transaction */
rtreeEndTransaction, /* xRollback - rollback transaction */
geopolyFindFunction, /* xFindFunction - function overloading */
rtreeRename, /* xRename - rename the table */
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
rtreeShadowName, /* xShadowName */
rtreeIntegrity /* xIntegrity */
};
static int sqlite3_geopoly_init(sqlite3 *db){
int rc = SQLITE_OK;
static const struct {
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
signed char nArg;
unsigned char bPure;
const char *zName;
} aFunc[] = {
{ geopolyAreaFunc, 1, 1, "geopoly_area" },
{ geopolyBlobFunc, 1, 1, "geopoly_blob" },
{ geopolyJsonFunc, 1, 1, "geopoly_json" },
{ geopolySvgFunc, -1, 1, "geopoly_svg" },
{ geopolyWithinFunc, 2, 1, "geopoly_within" },
{ geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" },
{ geopolyOverlapFunc, 2, 1, "geopoly_overlap" },
{ geopolyDebugFunc, 1, 0, "geopoly_debug" },
{ geopolyBBoxFunc, 1, 1, "geopoly_bbox" },
{ geopolyXformFunc, 7, 1, "geopoly_xform" },
{ geopolyRegularFunc, 4, 1, "geopoly_regular" },
{ geopolyCcwFunc, 1, 1, "geopoly_ccw" },
};
static const struct {
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
void (*xFinal)(sqlite3_context*);
const char *zName;
} aAgg[] = {
{ geopolyBBoxStep, geopolyBBoxFinal, "geopoly_group_bbox" },
};
unsigned int i;
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
int enc;
if( aFunc[i].bPure ){
enc = SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS;
}else{
enc = SQLITE_UTF8|SQLITE_DIRECTONLY;
}
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
enc, 0,
aFunc[i].xFunc, 0, 0);
}
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
rc = sqlite3_create_function(db, aAgg[i].zName, 1,
SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS, 0,
p->xFunc, 0, 0
);
}
return rc;
}
#ifndef SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
SQLITE_API int sqlite3_icu_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
SQLITE_EXTENSION_INIT2(pApi)
return sqlite3IcuInit(db);
}
#endif
#endif
/************** End of icu.c *************************************************/
/************** Begin file fts3_icu.c ****************************************/
/*
** 2007 June 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements a tokenizer for fts3 based on the ICU library.
*/
/* #include "fts3Int.h" */
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
#ifdef SQLITE_ENABLE_ICU
/* #include <assert.h> */
/* #include <string.h> */
/* #include "fts3_tokenizer.h" */
#include <unicode/ubrk.h>
/* #include <unicode/ucol.h> */
/* #include <unicode/ustring.h> */
#include <unicode/utf16.h>
typedef struct IcuTokenizer IcuTokenizer;
typedef struct IcuCursor IcuCursor;
struct IcuTokenizer {
sqlite3_tokenizer base;
char *zLocale;
};
struct IcuCursor {
sqlite3_tokenizer_cursor base;
UBreakIterator *pIter; /* ICU break-iterator object */
int nChar; /* Number of UChar elements in pInput */
UChar *aChar; /* Copy of input using utf-16 encoding */
int *aOffset; /* Offsets of each character in utf-8 input */
int nBuffer;
char *zBuffer;
int iToken;
};
/*
** Create a new tokenizer instance.
*/
static int icuCreate(
int argc, /* Number of entries in argv[] */
const char * const *argv, /* Tokenizer creation arguments */
sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
){
IcuTokenizer *p;
int n = 0;
if( argc>0 ){
n = strlen(argv[0])+1;
}
p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n);
if( !p ){
return SQLITE_NOMEM;
}
memset(p, 0, sizeof(IcuTokenizer));
if( n ){
p->zLocale = (char *)&p[1];
memcpy(p->zLocale, argv[0], n);
}
*ppTokenizer = (sqlite3_tokenizer *)p;
return SQLITE_OK;
}
/*
** Destroy a tokenizer
*/
static int icuDestroy(sqlite3_tokenizer *pTokenizer){
IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
sqlite3_free(p);
return SQLITE_OK;
}
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is pInput[0..nBytes-1]. A cursor
** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int icuOpen(
sqlite3_tokenizer *pTokenizer, /* The tokenizer */
const char *zInput, /* Input string */
int nInput, /* Length of zInput in bytes */
sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
){
IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
IcuCursor *pCsr;
const int32_t opt = U_FOLD_CASE_DEFAULT;
UErrorCode status = U_ZERO_ERROR;
int nChar;
UChar32 c;
int iInput = 0;
int iOut = 0;
*ppCursor = 0;
if( zInput==0 ){
nInput = 0;
zInput = "";
}else if( nInput<0 ){
nInput = strlen(zInput);
}
nChar = nInput+1;
pCsr = (IcuCursor *)sqlite3_malloc64(
sizeof(IcuCursor) + /* IcuCursor */
((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
(nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
);
if( !pCsr ){
return SQLITE_NOMEM;
}
memset(pCsr, 0, sizeof(IcuCursor));
pCsr->aChar = (UChar *)&pCsr[1];
pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
pCsr->aOffset[iOut] = iInput;
U8_NEXT(zInput, iInput, nInput, c);
while( c>0 ){
int isError = 0;
c = u_foldCase(c, opt);
U16_APPEND(pCsr->aChar, iOut, nChar, c, isError);
if( isError ){
sqlite3_free(pCsr);
return SQLITE_ERROR;
}
pCsr->aOffset[iOut] = iInput;
if( iInput<nInput ){
U8_NEXT(zInput, iInput, nInput, c);
}else{
c = 0;
}
}
pCsr->pIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status);
if( !U_SUCCESS(status) ){
sqlite3_free(pCsr);
return SQLITE_ERROR;
}
pCsr->nChar = iOut;
ubrk_first(pCsr->pIter);
*ppCursor = (sqlite3_tokenizer_cursor *)pCsr;
return SQLITE_OK;
}
/*
** Close a tokenization cursor previously opened by a call to icuOpen().
*/
static int icuClose(sqlite3_tokenizer_cursor *pCursor){
IcuCursor *pCsr = (IcuCursor *)pCursor;
ubrk_close(pCsr->pIter);
sqlite3_free(pCsr->zBuffer);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** Extract the next token from a tokenization cursor.
*/
static int icuNext(
sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
const char **ppToken, /* OUT: *ppToken is the token text */
int *pnBytes, /* OUT: Number of bytes in token */
int *piStartOffset, /* OUT: Starting offset of token */
int *piEndOffset, /* OUT: Ending offset of token */
int *piPosition /* OUT: Position integer of token */
){
IcuCursor *pCsr = (IcuCursor *)pCursor;
int iStart = 0;
int iEnd = 0;
int nByte = 0;
while( iStart==iEnd ){
UChar32 c;
iStart = ubrk_current(pCsr->pIter);
iEnd = ubrk_next(pCsr->pIter);
if( iEnd==UBRK_DONE ){
return SQLITE_DONE;
}
while( iStart<iEnd ){
int iWhite = iStart;
U16_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
if( u_isspace(c) ){
iStart = iWhite;
}else{
break;
}
}
assert(iStart<=iEnd);
}
do {
UErrorCode status = U_ZERO_ERROR;
if( nByte ){
char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte);
if( !zNew ){
return SQLITE_NOMEM;
}
pCsr->zBuffer = zNew;
pCsr->nBuffer = nByte;
}
u_strToUTF8(
pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */
&pCsr->aChar[iStart], iEnd-iStart, /* Input vars */
&status /* Output success/failure */
);
} while( nByte>pCsr->nBuffer );
*ppToken = pCsr->zBuffer;
*pnBytes = nByte;
*piStartOffset = pCsr->aOffset[iStart];
*piEndOffset = pCsr->aOffset[iEnd];
*piPosition = pCsr->iToken++;
return SQLITE_OK;
}
if( eType==RBU_DELETE ){
p->nPhaseOneStep -= p->objiter.nIndex;
}
if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){
pWriter = pIter->pDelete;
}else{
pWriter = pIter->pInsert;
}
for(i=0; i<pIter->nCol; i++){
/* If this is an INSERT into a table b-tree and the table has an
** explicit INTEGER PRIMARY KEY, check that this is not an attempt
** to write a NULL into the IPK column. That is not permitted. */
if( eType==RBU_INSERT
&& pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i]
&& sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL
){
p->rc = SQLITE_MISMATCH;
p->zErrmsg = sqlite3_mprintf("datatype mismatch");
return;
}
if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){
continue;
}
pVal = sqlite3_column_value(pIter->pSelect, i);
p->rc = sqlite3_bind_value(pWriter, i+1, pVal);
if( p->rc ) return;
}
if( pIter->zIdx==0 ){
if( pIter->eType==RBU_PK_VTAB
|| pIter->eType==RBU_PK_NONE
|| (pIter->eType==RBU_PK_EXTERNAL && rbuIsVacuum(p))
){
/* For a virtual table, or a table with no primary key, the
** SELECT statement is:
**
** SELECT <cols>, rbu_control, rbu_rowid FROM ....
**
** Hence column_value(pIter->nCol+1).
*/
assertColumnName(pIter->pSelect, pIter->nCol+1,
rbuIsVacuum(p) ? "rowid" : "rbu_rowid"
);
pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1);
p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal);
}
}
if( p->rc==SQLITE_OK ){
sqlite3_step(pWriter);
p->rc = resetAndCollectError(pWriter, &p->zErrmsg);
}
}
/*
** This function does the work for an sqlite3rbu_step() call.
**
** The object-iterator (p->objiter) currently points to a valid object,
** and the input cursor (p->objiter.pSelect) currently points to a valid
** input row. Perform whatever processing is required and return.
**
** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
** and message is left in the RBU handle and a copy of the error code
** returned.
*/
static int rbuStep(sqlite3rbu *p){
RbuObjIter *pIter = &p->objiter;
const char *zMask = 0;
int eType = rbuStepType(p, &zMask);
if( eType ){
assert( eType==RBU_INSERT || eType==RBU_DELETE
|| eType==RBU_REPLACE || eType==RBU_IDX_DELETE
|| eType==RBU_IDX_INSERT || eType==RBU_UPDATE
);
assert( eType!=RBU_UPDATE || pIter->zIdx==0 );
if( pIter->zIdx==0 && (eType==RBU_IDX_DELETE || eType==RBU_IDX_INSERT) ){
rbuBadControlError(p);
}
else if( eType==RBU_REPLACE ){
if( pIter->zIdx==0 ){
p->nPhaseOneStep += p->objiter.nIndex;
rbuStepOneOp(p, RBU_DELETE);
}
if( p->rc==SQLITE_OK ) rbuStepOneOp(p, RBU_INSERT);
}
else if( eType!=RBU_UPDATE ){
rbuStepOneOp(p, eType);
}
else{
sqlite3_value *pVal;
sqlite3_stmt *pUpdate = 0;
assert( eType==RBU_UPDATE );
p->nPhaseOneStep -= p->objiter.nIndex;
rbuGetUpdateStmt(p, pIter, zMask, &pUpdate);
if( pUpdate ){
int i;
for(i=0; p->rc==SQLITE_OK && i<pIter->nCol; i++){
char c = zMask[pIter->aiSrcOrder[i]];
pVal = sqlite3_column_value(pIter->pSelect, i);
if( pIter->abTblPk[i] || c!='.' ){
p->rc = sqlite3_bind_value(pUpdate, i+1, pVal);
}
}
if( p->rc==SQLITE_OK
&& (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE)
){
/* Bind the rbu_rowid value to column _rowid_ */
assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid");
pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1);
p->rc = sqlite3_bind_value(pUpdate, pIter->nCol+1, pVal);
}
if( p->rc==SQLITE_OK ){
sqlite3_step(pUpdate);
p->rc = resetAndCollectError(pUpdate, &p->zErrmsg);
}
}
}
**
** '/1c2/000+000000' // First page in overflow chain
** '/1c2/000+000001' // Second page in overflow chain
** '/1c2/000+000002' // Third page in overflow chain
**
** If the paths are sorted using the BINARY collation sequence, then
** the overflow pages associated with a cell will appear earlier in the
** sort-order than its child page:
**
** '/1c2/000/' // Left-most child of 451st child of root
*/
static const char zDbstatSchema[] =
"CREATE TABLE x("
" name TEXT," /* 0 Name of table or index */
" path TEXT," /* 1 Path to page from root (NULL for agg) */
" pageno INTEGER," /* 2 Page number (page count for aggregates) */
" pagetype TEXT," /* 3 'internal', 'leaf', 'overflow', or NULL */
" ncell INTEGER," /* 4 Cells on page (0 for overflow) */
" payload INTEGER," /* 5 Bytes of payload on this page */
" unused INTEGER," /* 6 Bytes of unused space on this page */
" mx_payload INTEGER," /* 7 Largest payload size of all cells */
" pgoffset INTEGER," /* 8 Offset of page in file (NULL for agg) */
" pgsize INTEGER," /* 9 Size of the page (sum for aggregate) */
" schema TEXT HIDDEN," /* 10 Database schema being analyzed */
" aggregate BOOLEAN HIDDEN" /* 11 aggregate info for each table */
")"
;
/* Forward reference to data structured used in this module */
typedef struct StatTable StatTable;
typedef struct StatCursor StatCursor;
typedef struct StatPage StatPage;
typedef struct StatCell StatCell;
/* Size information for a single cell within a btree page */
struct StatCell {
int nLocal; /* Bytes of local payload */
u32 iChildPg; /* Child node (or 0 if this is a leaf) */
int nOvfl; /* Entries in aOvfl[] */
u32 *aOvfl; /* Array of overflow page numbers */
int nLastOvfl; /* Bytes of payload on final overflow page */
int iOvfl; /* Iterates through aOvfl[] */
};
/* Size information for a single btree page */
struct StatPage {
u32 iPgno; /* Page number */
u8 *aPg; /* Page buffer from sqlite3_malloc() */
int iCell; /* Current cell */
char *zPath; /* Path to this page */
/* Variables populated by statDecodePage(): */
u8 flags; /* Copy of flags byte */
int nCell; /* Number of cells on page */
int nUnused; /* Number of unused bytes on page */
StatCell *aCell; /* Array of parsed cells */
u32 iRightChildPg; /* Right-child page number (or 0) */
int nMxPayload; /* Largest payload of any cell on the page */
};
/* The cursor for scanning the dbstat virtual table */
struct StatCursor {
sqlite3_vtab_cursor base; /* base class. MUST BE FIRST! */
sqlite3_stmt *pStmt; /* Iterates through set of root pages */
u8 isEof; /* After pStmt has returned SQLITE_DONE */
u8 isAgg; /* Aggregate results for each table */
int iDb; /* Schema used for this query */
StatPage aPage[32]; /* Pages in path to current page */
int iPage; /* Current entry in aPage[] */
/* Values to return. */
u32 iPageno; /* Value of 'pageno' column */
char *zName; /* Value of 'name' column */
char *zPath; /* Value of 'path' column */
char *zPagetype; /* Value of 'pagetype' column */
int nPage; /* Number of pages in current btree */
int nCell; /* Value of 'ncell' column */
int nMxPayload; /* Value of 'mx_payload' column */
i64 nUnused; /* Value of 'unused' column */
i64 nPayload; /* Value of 'payload' column */
i64 iOffset; /* Value of 'pgOffset' column */
i64 szPage; /* Value of 'pgSize' column */
};
/* An instance of the DBSTAT virtual table */
struct StatTable {
sqlite3_vtab base; /* base class. MUST BE FIRST! */
sqlite3 *db; /* Database connection that owns this vtab */
int iDb; /* Index of database to analyze */
};
#ifndef get2byte
# define get2byte(x) ((x)[0]<<8 | (x)[1])
#endif
/*
** Connect to or create a new DBSTAT virtual table.
*/
static int statConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
StatTable *pTab = 0;
int rc = SQLITE_OK;
int iDb;
(void)pAux;
if( argc>=4 ){
Token nm;
sqlite3TokenInit(&nm, (char*)argv[3]);
iDb = sqlite3FindDb(db, &nm);
if( iDb<0 ){
*pzErr = sqlite3_mprintf("no such database: %s", argv[3]);
return SQLITE_ERROR;
}
}else{
iDb = 0;
}
sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pIdxInfo->aConstraint[i].usable==0 ){
/* Force DBSTAT table should always be the right-most table in a join */
return SQLITE_CONSTRAINT;
}
switch( pIdxInfo->aConstraint[i].iColumn ){
case 0: { /* name */
iName = i;
break;
}
case 10: { /* schema */
iSchema = i;
break;
}
case 11: { /* aggregate */
iAgg = i;
break;
}
}
}
i = 0;
if( iSchema>=0 ){
pIdxInfo->aConstraintUsage[iSchema].argvIndex = ++i;
pIdxInfo->aConstraintUsage[iSchema].omit = 1;
pIdxInfo->idxNum |= 0x01;
}
if( iName>=0 ){
pIdxInfo->aConstraintUsage[iName].argvIndex = ++i;
pIdxInfo->idxNum |= 0x02;
}
if( iAgg>=0 ){
pIdxInfo->aConstraintUsage[iAgg].argvIndex = ++i;
pIdxInfo->idxNum |= 0x04;
}
pIdxInfo->estimatedCost = 1.0;
/* Records are always returned in ascending order of (name, path).
** If this will satisfy the client, set the orderByConsumed flag so that
** SQLite does not do an external sort.
*/
if( ( pIdxInfo->nOrderBy==1
&& pIdxInfo->aOrderBy[0].iColumn==0
&& pIdxInfo->aOrderBy[0].desc==0
) ||
( pIdxInfo->nOrderBy==2
&& pIdxInfo->aOrderBy[0].iColumn==0
&& pIdxInfo->aOrderBy[0].desc==0
&& pIdxInfo->aOrderBy[1].iColumn==1
&& pIdxInfo->aOrderBy[1].desc==0
)
){
pIdxInfo->orderByConsumed = 1;
pIdxInfo->idxNum |= 0x08;
}
pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_HEX;
return SQLITE_OK;
}
/*
** Open a new DBSTAT cursor.
*/
static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
StatTable *pTab = (StatTable *)pVTab;
StatCursor *pCsr;
pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor));
if( pCsr==0 ){
return SQLITE_NOMEM_BKPT;
}else{
memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab;
pCsr->iDb = pTab->iDb;
}
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return SQLITE_OK;
}
static void statClearCells(StatPage *p){
int i;
if( p->aCell ){
for(i=0; i<p->nCell; i++){
sqlite3_free(p->aCell[i].aOvfl);
}
sqlite3_free(p->aCell);
}
p->nCell = 0;
p->aCell = 0;
}
static void statClearPage(StatPage *p){
u8 *aPg = p->aPg;
statClearCells(p);
sqlite3_free(p->zPath);
memset(p, 0, sizeof(StatPage));
p->aPg = aPg;
}
static void statResetCsr(StatCursor *pCsr){
int i;
/* In some circumstances, specifically if an OOM has occurred, the call
** to sqlite3_reset() may cause the pager to be reset (emptied). It is
** important that statClearPage() is called to free any page refs before
** this happens. dbsqlfuzz 9ed3e4e3816219d3509d711636c38542bf3f40b1. */
for(i=0; i<ArraySize(pCsr->aPage); i++){
statClearPage(&pCsr->aPage[i]);
sqlite3_free(pCsr->aPage[i].aPg);
pCsr->aPage[i].aPg = 0;
}
sqlite3_reset(pCsr->pStmt);
pCsr->iPage = 0;
sqlite3_free(pCsr->zPath);
pCsr->zPath = 0;
pCsr->isEof = 0;
}
/* Resize the space-used counters inside of the cursor */
static void statResetCounts(StatCursor *pCsr){
pCsr->nCell = 0;
pCsr->nMxPayload = 0;
pCsr->nUnused = 0;
pCsr->nPayload = 0;
pCsr->szPage = 0;
pCsr->nPage = 0;
}
/*
** Close a DBSTAT cursor.
*/
static int statClose(sqlite3_vtab_cursor *pCursor){
StatCursor *pCsr = (StatCursor *)pCursor;
statResetCsr(pCsr);
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** For a single cell on a btree page, compute the number of bytes of
** content (payload) stored on that page. That is to say, compute the
** number of bytes of content not found on overflow pages.
*/
static int getLocalPayload(
int nUsable, /* Usable bytes per page */
u8 flags, /* Page flags */
int nTotal /* Total record (payload) size */
){
int nLocal;
int nMinLocal;
int nMaxLocal;
if( flags==0x0D ){ /* Table leaf node */
nMinLocal = (nUsable - 12) * 32 / 255 - 23;
nMaxLocal = nUsable - 35;
}else{ /* Index interior and leaf nodes */
nMinLocal = (nUsable - 12) * 32 / 255 - 23;
nMaxLocal = (nUsable - 12) * 64 / 255 - 23;
}
nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4);
if( nLocal>nMaxLocal ) nLocal = nMinLocal;
return nLocal;
}
/* Populate the StatPage object with information about the all
** cells found on the page currently under analysis.
*/
static int statDecodePage(Btree *pBt, StatPage *p){
int nUnused;
int iOff;
int nHdr;
int isLeaf;
int szPage;
u8 *aData = p->aPg;
u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];
p->flags = aHdr[0];
if( p->flags==0x0A || p->flags==0x0D ){
isLeaf = 1;
nHdr = 8;
}else if( p->flags==0x05 || p->flags==0x02 ){
isLeaf = 0;
nHdr = 12;
}else{
goto statPageIsCorrupt;
}
if( p->iPgno==1 ) nHdr += 100;
p->nCell = get2byte(&aHdr[3]);
p->nMxPayload = 0;
pCell->iChildPg = sqlite3Get4byte(&aData[iOff]);
iOff += 4;
}
if( p->flags==0x05 ){
/* A table interior node. nPayload==0. */
}else{
u32 nPayload; /* Bytes of payload total (local+overflow) */
int nLocal; /* Bytes of payload stored locally */
iOff += getVarint32(&aData[iOff], nPayload);
if( p->flags==0x0D ){
u64 dummy;
iOff += sqlite3GetVarint(&aData[iOff], &dummy);
}
if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload;
nLocal = getLocalPayload(nUsable, p->flags, nPayload);
if( nLocal<0 ) goto statPageIsCorrupt;
pCell->nLocal = nLocal;
assert( nPayload>=(u32)nLocal );
assert( nLocal<=(nUsable-35) );
if( nPayload>(u32)nLocal ){
int j;
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
if( iOff+nLocal+4>nUsable || nPayload>0x7fffffff ){
goto statPageIsCorrupt;
}
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
pCell->nOvfl = nOvfl;
pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
if( pCell->aOvfl==0 ) return SQLITE_NOMEM_BKPT;
pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]);
for(j=1; j<nOvfl; j++){
int rc;
u32 iPrev = pCell->aOvfl[j-1];
DbPage *pPg = 0;
rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg, 0);
if( rc!=SQLITE_OK ){
assert( pPg==0 );
return rc;
}
pCell->aOvfl[j] = sqlite3Get4byte(sqlite3PagerGetData(pPg));
sqlite3PagerUnref(pPg);
}
}
}
}
}
return SQLITE_OK;
statPageIsCorrupt:
p->flags = 0;
statClearCells(p);
return SQLITE_OK;
}
/*
** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on
** the current value of pCsr->iPageno.
*/
static void statSizeAndOffset(StatCursor *pCsr){
StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab;
Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
Pager *pPager = sqlite3BtreePager(pBt);
sqlite3_file *fd;
sqlite3_int64 x[2];
/* If connected to a ZIPVFS backend, find the page size and
** offset from ZIPVFS.
*/
fd = sqlite3PagerFile(pPager);
x[0] = pCsr->iPageno;
if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
pCsr->iOffset = x[0];
pCsr->szPage += x[1];
}else{
/* Not ZIPVFS: The default page size and offset */
pCsr->szPage += sqlite3BtreeGetPageSize(pBt);
pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
}
}
/*
** Load a copy of the page data for page iPg into the buffer belonging
** to page object pPg. Allocate the buffer if necessary. Return SQLITE_OK
** if successful, or an SQLite error code otherwise.
*/
static int statGetPage(
Btree *pBt, /* Load page from this b-tree */
u32 iPg, /* Page number to load */
StatPage *pPg /* Load page into this object */
){
int pgsz = sqlite3BtreeGetPageSize(pBt);
DbPage *pDbPage = 0;
int rc;
if( pPg->aPg==0 ){
pPg->aPg = (u8*)sqlite3_malloc(pgsz + DBSTAT_PAGE_PADDING_BYTES);
if( pPg->aPg==0 ){
return SQLITE_NOMEM_BKPT;
}
memset(&pPg->aPg[pgsz], 0, DBSTAT_PAGE_PADDING_BYTES);
}
rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPg, &pDbPage, 0);
if( rc==SQLITE_OK ){
const u8 *a = sqlite3PagerGetData(pDbPage);
memcpy(pPg->aPg, a, pgsz);
sqlite3PagerUnref(pDbPage);
}
return rc;
}
/*
** Move a DBSTAT cursor to the next entry. Normally, the next
** entry will be the next page, but in aggregated mode (pCsr->isAgg!=0),
** the next entry is the next btree.
*/
static int statNext(sqlite3_vtab_cursor *pCursor){
int rc;
int nPayload;
char *z;
StatCursor *pCsr = (StatCursor *)pCursor;
StatTable *pTab = (StatTable *)pCursor->pVtab;
Btree *pBt = pTab->db->aDb[pCsr->iDb].pBt;
Pager *pPager = sqlite3BtreePager(pBt);
sqlite3_free(pCsr->zPath);
pCsr->zPath = 0;
statNextRestart:
if( pCsr->iPage<0 ){
/* Start measuring space on the next btree */
statResetCounts(pCsr);
rc = sqlite3_step(pCsr->pStmt);
if( rc==SQLITE_ROW ){
int nPage;
u32 iRoot = (u32)sqlite3_column_int64(pCsr->pStmt, 1);
sqlite3PagerPagecount(pPager, &nPage);
if( nPage==0 ){
pCsr->isEof = 1;
return sqlite3_reset(pCsr->pStmt);
}
rc = statGetPage(pBt, iRoot, &pCsr->aPage[0]);
pCsr->aPage[0].iPgno = iRoot;
pCsr->aPage[0].iCell = 0;
if( !pCsr->isAgg ){
pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
if( z==0 ) rc = SQLITE_NOMEM_BKPT;
}
pCsr->iPage = 0;
pCsr->nPage = 1;
}else{
pCsr->isEof = 1;
return sqlite3_reset(pCsr->pStmt);
}
}else{
/* Continue analyzing the btree previously started */
StatPage *p = &pCsr->aPage[pCsr->iPage];
if( !pCsr->isAgg ) statResetCounts(pCsr);
while( p->iCell<p->nCell ){
StatCell *pCell = &p->aCell[p->iCell];
while( pCell->iOvfl<pCell->nOvfl ){
int nUsable, iOvfl;
sqlite3BtreeEnter(pBt);
nUsable = sqlite3BtreeGetPageSize(pBt) -
sqlite3BtreeGetReserveNoMutex(pBt);
sqlite3BtreeLeave(pBt);
pCsr->nPage++;
statSizeAndOffset(pCsr);
if( pCell->iOvfl<pCell->nOvfl-1 ){
pCsr->nPayload += nUsable - 4;
}else{
pCsr->nPayload += pCell->nLastOvfl;
pCsr->nUnused += nUsable - 4 - pCell->nLastOvfl;
}
iOvfl = pCell->iOvfl;
pCell->iOvfl++;
if( !pCsr->isAgg ){
rc = statGetPage(pBt, p[1].iPgno, &p[1]);
pCsr->nPage++;
p[1].iCell = 0;
if( !pCsr->isAgg ){
p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
if( z==0 ) rc = SQLITE_NOMEM_BKPT;
}
p->iCell++;
}
/* Populate the StatCursor fields with the values to be returned
** by the xColumn() and xRowid() methods.
*/
if( rc==SQLITE_OK ){
int i;
StatPage *p = &pCsr->aPage[pCsr->iPage];
pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
pCsr->iPageno = p->iPgno;
rc = statDecodePage(pBt, p);
if( rc==SQLITE_OK ){
statSizeAndOffset(pCsr);
switch( p->flags ){
case 0x05: /* table internal */
case 0x02: /* index internal */
pCsr->zPagetype = "internal";
break;
case 0x0D: /* table leaf */
case 0x0A: /* index leaf */
pCsr->zPagetype = "leaf";
break;
default:
pCsr->zPagetype = "corrupted";
break;
}
pCsr->nCell += p->nCell;
pCsr->nUnused += p->nUnused;
if( p->nMxPayload>pCsr->nMxPayload ) pCsr->nMxPayload = p->nMxPayload;
if( !pCsr->isAgg ){
pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
if( z==0 ) rc = SQLITE_NOMEM_BKPT;
}
nPayload = 0;
for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal;
}
pCsr->nPayload += nPayload;
/* If computing aggregate space usage by btree, continue with the
** next page. The loop will exit via the return at label-statNext-done
*/
if( pCsr->isAgg ) goto statNextRestart;
}
}
return rc;
}
static int statEof(sqlite3_vtab_cursor *pCursor){
StatCursor *pCsr = (StatCursor *)pCursor;
return pCsr->isEof;
}
/* Initialize a cursor according to the query plan idxNum using the
** arguments in argv[0]. See statBestIndex() for a description of the
** meaning of the bits in idxNum.
*/
static int statFilter(
sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
StatCursor *pCsr = (StatCursor *)pCursor;
StatTable *pTab = (StatTable*)(pCursor->pVtab);
sqlite3_str *pSql; /* Query of btrees to analyze */
char *zSql; /* String value of pSql */
int iArg = 0; /* Count of argv[] parameters used so far */
int rc = SQLITE_OK; /* Result of this operation */
const char *zName = 0; /* Only provide analysis of this table */
(void)argc;
(void)idxStr;
statResetCsr(pCsr);
sqlite3_finalize(pCsr->pStmt);
pCsr->pStmt = 0;
if( idxNum & 0x01 ){
/* schema=? constraint is present. Get its value */
const char *zDbase = (const char*)sqlite3_value_text(argv[iArg++]);
pCsr->iDb = sqlite3FindDbName(pTab->db, zDbase);
if( pCsr->iDb<0 ){
pCsr->iDb = 0;
pCsr->isEof = 1;
return SQLITE_OK;
}
}else{
pCsr->iDb = pTab->iDb;
}
if( idxNum & 0x02 ){
/* name=? constraint is present */
zName = (const char*)sqlite3_value_text(argv[iArg++]);
}
if( idxNum & 0x04 ){
/* aggregate=? constraint is present */
pCsr->isAgg = sqlite3_value_double(argv[iArg++])!=0.0;
}else{
pCsr->isAgg = 0;
}
pSql = sqlite3_str_new(pTab->db);
sqlite3_str_appendf(pSql,
"SELECT * FROM ("
"SELECT 'sqlite_schema' AS name,1 AS rootpage,'table' AS type"
" UNION ALL "
"SELECT name,rootpage,type"
" FROM \"%w\".sqlite_schema WHERE rootpage!=0)",
pTab->db->aDb[pCsr->iDb].zDbSName);
if( zName ){
sqlite3_str_appendf(pSql, "WHERE name=%Q", zName);
}
if( idxNum & 0x08 ){
sqlite3_str_appendf(pSql, " ORDER BY name");
}
zSql = sqlite3_str_finish(pSql);
if( zSql==0 ){
return SQLITE_NOMEM_BKPT;
}else{
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ){
pCsr->iPage = -1;
rc = statNext(pCursor);
}
return rc;
}
static int statColumn(
sqlite3_vtab_cursor *pCursor,
sqlite3_context *ctx,
int i
){
StatCursor *pCsr = (StatCursor *)pCursor;
switch( i ){
case 0: /* name */
sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
break;
case 1: /* path */
if( !pCsr->isAgg ){
sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
}
break;
case 2: /* pageno */
if( pCsr->isAgg ){
sqlite3_result_int64(ctx, pCsr->nPage);
}else{
sqlite3_result_int64(ctx, pCsr->iPageno);
}
break;
case 3: /* pagetype */
if( !pCsr->isAgg ){
sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
}
break;
case 4: /* ncell */
sqlite3_result_int64(ctx, pCsr->nCell);
break;
case 5: /* payload */
sqlite3_result_int64(ctx, pCsr->nPayload);
break;
case 6: /* unused */
sqlite3_result_int64(ctx, pCsr->nUnused);
break;
case 7: /* mx_payload */
sqlite3_result_int64(ctx, pCsr->nMxPayload);
break;
case 8: /* pgoffset */
if( !pCsr->isAgg ){
sqlite3_result_int64(ctx, pCsr->iOffset);
}
break;
case 9: /* pgsize */
sqlite3_result_int64(ctx, pCsr->szPage);
break;
case 10: { /* schema */
sqlite3 *db = sqlite3_context_db_handle(ctx);
int iDb = pCsr->iDb;
sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC);
break;
}
default: { /* aggregate */
sqlite3_result_int(ctx, pCsr->isAgg);
break;
}
}
return SQLITE_OK;
}
static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
StatCursor *pCsr = (StatCursor *)pCursor;
*pRowid = pCsr->iPageno;
return SQLITE_OK;
}
/*
** Invoke this routine to register the "dbstat" virtual table module
*/
SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){
static sqlite3_module dbstat_module = {
0, /* iVersion */
statConnect, /* xCreate */
statConnect, /* xConnect */
statBestIndex, /* xBestIndex */
statDisconnect, /* xDisconnect */
statDisconnect, /* xDestroy */
statOpen, /* xOpen - open a cursor */
statClose, /* xClose - close a cursor */
statFilter, /* xFilter - configure scan constraints */
statNext, /* xNext - advance a cursor */
statEof, /* xEof - check for end of scan */
statColumn, /* xColumn - read data */
statRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
}
#elif defined(SQLITE_ENABLE_DBSTAT_VTAB)
SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; }
#endif /* SQLITE_ENABLE_DBSTAT_VTAB */
/************** End of dbstat.c **********************************************/
/************** Begin file dbpage.c ******************************************/
/*
** 2017-10-11
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains an implementation of the "sqlite_dbpage" virtual table.
**
** The sqlite_dbpage virtual table is used to read or write whole raw
** pages of the database file. The pager interface is used so that
** uncommitted changes and changes recorded in the WAL file are correctly
** retrieved.
**
** Usage example:
**
** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123;
**
** This is an eponymous virtual table so it does not need to be created before
** use. The optional argument to the sqlite_dbpage() table name is the
** schema for the database file that is to be read. The default schema is
** "main".
**
** The data field of sqlite_dbpage table can be updated. The new
** value must be a BLOB which is the correct page size, otherwise the
** update fails. INSERT operations also work, and operate as if they
** where REPLACE. The size of the database can be extended by INSERT-ing
** new pages on the end.
**
** Rows may not be deleted. However, doing an INSERT to page number N
** with NULL page data causes the N-th page and all subsequent pages to be
** deleted and the database to be truncated.
*/
/* #include "sqliteInt.h" ** Requires access to internal data structures ** */
#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
typedef struct DbpageTable DbpageTable;
typedef struct DbpageCursor DbpageCursor;
struct DbpageCursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
Pgno pgno; /* Current page number */
Pgno mxPgno; /* Last page to visit on this scan */
Pager *pPager; /* Pager being read/written */
DbPage *pPage1; /* Page 1 of the database */
int iDb; /* Index of database to analyze */
int szPage; /* Size of each page in bytes */
};
struct DbpageTable {
sqlite3_vtab base; /* Base class. Must be first */
sqlite3 *db; /* The database */
int iDbTrunc; /* Database to truncate */
Pgno pgnoTrunc; /* Size to truncate to */
};
/* Columns */
#define DBPAGE_COLUMN_PGNO 0
#define DBPAGE_COLUMN_DATA 1
#define DBPAGE_COLUMN_SCHEMA 2
/*
** Connect to or create a dbpagevfs virtual table.
*/
static int dbpageConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
DbpageTable *pTab = 0;
int rc = SQLITE_OK;
(void)pAux;
(void)argc;
(void)argv;
(void)pzErr;
sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
sqlite3_vtab_config(db, SQLITE_VTAB_USES_ALL_SCHEMAS);
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
if( rc==SQLITE_OK ){
pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable));
if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
}
assert( rc==SQLITE_OK || pTab==0 );
if( rc==SQLITE_OK ){
memset(pTab, 0, sizeof(DbpageTable));
pTab->db = db;
}
*ppVtab = (sqlite3_vtab*)pTab;
return rc;
}
/*
** Disconnect from or destroy a dbpagevfs virtual table.
*/
**
** 0 schema=main, full table scan
** 1 schema=main, pgno=?1
** 2 schema=?1, full table scan
** 3 schema=?1, pgno=?2
*/
static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int i;
int iPlan = 0;
(void)tab;
/* If there is a schema= constraint, it must be honored. Report a
** ridiculously large estimated cost if the schema= constraint is
** unavailable
*/
for(i=0; i<pIdxInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue;
if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( !p->usable ){
/* No solution. */
return SQLITE_CONSTRAINT;
}
iPlan = 2;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
pIdxInfo->aConstraintUsage[i].omit = 1;
break;
}
/* If we reach this point, it means that either there is no schema=
** constraint (in which case we use the "main" schema) or else the
** schema constraint was accepted. Lower the estimated cost accordingly
*/
pIdxInfo->estimatedCost = 1.0e6;
/* Check for constraints against pgno */
for(i=0; i<pIdxInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
pIdxInfo->estimatedRows = 1;
pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
pIdxInfo->estimatedCost = 1.0;
pIdxInfo->aConstraintUsage[i].argvIndex = iPlan ? 2 : 1;
pIdxInfo->aConstraintUsage[i].omit = 1;
iPlan |= 1;
break;
}
}
pIdxInfo->idxNum = iPlan;
if( pIdxInfo->nOrderBy>=1
&& pIdxInfo->aOrderBy[0].iColumn<=0
&& pIdxInfo->aOrderBy[0].desc==0
){
pIdxInfo->orderByConsumed = 1;
}
return SQLITE_OK;
}
/*
** Open a new dbpagevfs cursor.
*/
static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
DbpageCursor *pCsr;
pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor));
if( pCsr==0 ){
return SQLITE_NOMEM_BKPT;
}else{
memset(pCsr, 0, sizeof(DbpageCursor));
pCsr->base.pVtab = pVTab;
pCsr->pgno = 0;
}
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return SQLITE_OK;
}
/*
** Close a dbpagevfs cursor.
*/
static int dbpageClose(sqlite3_vtab_cursor *pCursor){
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** Move a dbpagevfs cursor to the next entry in the file.
*/
static int dbpageNext(sqlite3_vtab_cursor *pCursor){
int rc = SQLITE_OK;
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
pCsr->pgno++;
return rc;
}
static int dbpageEof(sqlite3_vtab_cursor *pCursor){
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
return pCsr->pgno > pCsr->mxPgno;
}
/*
** idxNum:
**
** 0 schema=main, full table scan
** 1 schema=main, pgno=?1
** 2 schema=?1, full table scan
** 3 schema=?1, pgno=?2
**
** idxStr is not used
*/
static int dbpageFilter(
sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
DbpageTable *pTab = (DbpageTable *)pCursor->pVtab;
int rc;
sqlite3 *db = pTab->db;
Btree *pBt;
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(argc);
/* Default setting is no rows of result */
pCsr->pgno = 1;
pCsr->mxPgno = 0;
if( idxNum & 2 ){
const char *zSchema;
assert( argc>=1 );
zSchema = (const char*)sqlite3_value_text(argv[0]);
pCsr->iDb = sqlite3FindDbName(db, zSchema);
if( pCsr->iDb<0 ) return SQLITE_OK;
}else{
pCsr->iDb = 0;
}
pBt = db->aDb[pCsr->iDb].pBt;
if( NEVER(pBt==0) ) return SQLITE_OK;
pCsr->pPager = sqlite3BtreePager(pBt);
pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
if( idxNum & 1 ){
assert( argc>(idxNum>>1) );
pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
pCsr->pgno = 1;
pCsr->mxPgno = 0;
}else{
pCsr->mxPgno = pCsr->pgno;
}
}else{
assert( pCsr->pgno==1 );
}
if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0);
return rc;
}
static int dbpageColumn(
sqlite3_vtab_cursor *pCursor,
sqlite3_context *ctx,
int i
){
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
int rc = SQLITE_OK;
switch( i ){
case 0: { /* pgno */
sqlite3_result_int64(ctx, (sqlite3_int64)pCsr->pgno);
break;
}
case 1: { /* data */
DbPage *pDbPage = 0;
if( pCsr->pgno==(Pgno)((PENDING_BYTE/pCsr->szPage)+1) ){
/* The pending byte page. Assume it is zeroed out. Attempting to
** request this page from the page is an SQLITE_CORRUPT error. */
sqlite3_result_zeroblob(ctx, pCsr->szPage);
}else{
rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
if( rc==SQLITE_OK ){
sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
SQLITE_TRANSIENT);
}
sqlite3PagerUnref(pDbPage);
}
break;
}
default: { /* schema */
sqlite3 *db = sqlite3_context_db_handle(ctx);
sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC);
break;
}
}
return rc;
}
static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
*pRowid = pCsr->pgno;
return SQLITE_OK;
}
/*
** Open write transactions. Since we do not know in advance which database
** files will be written by the sqlite_dbpage virtual table, start a write
** transaction on them all.
**
** Return SQLITE_OK if successful, or an SQLite error code otherwise.
*/
static int dbpageBeginTrans(DbpageTable *pTab){
sqlite3 *db = pTab->db;
int rc = SQLITE_OK;
int i;
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
}
return rc;
}
static int dbpageUpdate(
sqlite3_vtab *pVtab,
int argc,
sqlite3_value **argv,
sqlite_int64 *pRowid
){
DbpageTable *pTab = (DbpageTable *)pVtab;
Pgno pgno;
DbPage *pDbPage = 0;
int rc = SQLITE_OK;
char *zErr = 0;
int iDb;
Btree *pBt;
Pager *pPager;
int szPage;
int isInsert;
(void)pRowid;
if( pTab->db->flags & SQLITE_Defensive ){
zErr = "read-only";
goto update_fail;
}
if( argc==1 ){
zErr = "cannot delete";
goto update_fail;
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
pgno = (Pgno)sqlite3_value_int64(argv[2]);
isInsert = 1;
}else{
pgno = (Pgno)sqlite3_value_int64(argv[0]);
if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
zErr = "cannot insert";
goto update_fail;
}
isInsert = 0;
}
memcpy(aPage, pData, szPage);
pTab->pgnoTrunc = 0;
}
}
if( rc!=SQLITE_OK ){
pTab->pgnoTrunc = 0;
}
sqlite3PagerUnref(pDbPage);
return rc;
update_fail:
pTab->pgnoTrunc = 0;
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
return SQLITE_ERROR;
}
static int dbpageBegin(sqlite3_vtab *pVtab){
DbpageTable *pTab = (DbpageTable *)pVtab;
pTab->pgnoTrunc = 0;
return SQLITE_OK;
}
/* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT
*/
static int dbpageSync(sqlite3_vtab *pVtab){
DbpageTable *pTab = (DbpageTable *)pVtab;
if( pTab->pgnoTrunc>0 ){
Btree *pBt = pTab->db->aDb[pTab->iDbTrunc].pBt;
Pager *pPager = sqlite3BtreePager(pBt);
sqlite3BtreeEnter(pBt);
if( pTab->pgnoTrunc<sqlite3BtreeLastPage(pBt) ){
sqlite3PagerTruncateImage(pPager, pTab->pgnoTrunc);
}
sqlite3BtreeLeave(pBt);
}
pTab->pgnoTrunc = 0;
return SQLITE_OK;
}
/* Cancel any pending truncate.
*/
static int dbpageRollbackTo(sqlite3_vtab *pVtab, int notUsed1){
DbpageTable *pTab = (DbpageTable *)pVtab;
pTab->pgnoTrunc = 0;
(void)notUsed1;
return SQLITE_OK;
}
/*
** Invoke this routine to register the "dbpage" virtual table module
*/
SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){
static sqlite3_module dbpage_module = {
2, /* iVersion */
dbpageConnect, /* xCreate */
dbpageConnect, /* xConnect */
dbpageBestIndex, /* xBestIndex */
dbpageDisconnect, /* xDisconnect */
dbpageDisconnect, /* xDestroy */
dbpageOpen, /* xOpen - open a cursor */
dbpageClose, /* xClose - close a cursor */
dbpageFilter, /* xFilter - configure scan constraints */
dbpageNext, /* xNext - advance a cursor */
dbpageEof, /* xEof - check for end of scan */
dbpageColumn, /* xColumn - read data */
dbpageRowid, /* xRowid - read data */
dbpageUpdate, /* xUpdate */
dbpageBegin, /* xBegin */
dbpageSync, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
dbpageRollbackTo, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0);
}
#elif defined(SQLITE_ENABLE_DBPAGE_VTAB)
SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; }
#endif /* SQLITE_ENABLE_DBSTAT_VTAB */
/************** End of dbpage.c **********************************************/
/************** Begin file carray.c ******************************************/
/*
** 2016-06-29
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements a table-valued-function that
** returns the values in a C-language array.
** Examples:
**
** SELECT * FROM carray($ptr,5)
**
** The query above returns 5 integers contained in a C-language array
** at the address $ptr. $ptr is a pointer to the array of integers.
** The pointer value must be assigned to $ptr using the
** sqlite3_bind_pointer() interface with a pointer type of "carray".
** For example:
**
** static int aX[] = { 53, 9, 17, 2231, 4, 99 };
** int i = sqlite3_bind_parameter_index(pStmt, "$ptr");
** sqlite3_bind_pointer(pStmt, i, aX, "carray", 0);
**
** There is an optional third parameter to determine the datatype of
** the C-language array. Allowed values of the third parameter are
** 'int32', 'int64', 'double', 'char*', 'struct iovec'. Example:
**
** SELECT * FROM carray($ptr,10,'char*');
**
** The default value of the third parameter is 'int32'.
**
** HOW IT WORKS
**
** The carray "function" is really a virtual table with the
** following schema:
**
** CREATE TABLE carray(
** value,
** pointer HIDDEN,
** count HIDDEN,
** ctype TEXT HIDDEN
** );
**
** If the hidden columns "pointer" and "count" are unconstrained, then
** the virtual table has no rows. Otherwise, the virtual table interprets
** the integer value of "pointer" as a pointer to the array and "count"
** as the number of elements in the array. The virtual table steps through
** the array, element by element.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_CARRAY)
/* #include "sqliteInt.h" */
#if defined(_WIN32) || defined(__RTP__) || defined(_WRS_KERNEL)
struct iovec {
void *iov_base;
size_t iov_len;
};
#else
# include <sys/uio.h>
#endif
/*
** Names of allowed datatypes
*/
static const char *azCarrayType[] = {
"int32", "int64", "double", "char*", "struct iovec"
};
/*
** Structure used to hold the sqlite3_carray_bind() information
*/
typedef struct carray_bind carray_bind;
struct carray_bind {
void *aData; /* The data */
int nData; /* Number of elements */
int mFlags; /* Control flags */
void (*xDel)(void*); /* Destructor for aData */
};
/* carray_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/
typedef struct carray_cursor carray_cursor;
struct carray_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3_int64 iRowid; /* The rowid */
void *pPtr; /* Pointer to the array of values */
sqlite3_int64 iCnt; /* Number of integers in the array */
unsigned char eType; /* One of the CARRAY_type values */
};
/*
** The carrayConnect() method is invoked to create a new
** carray_vtab that describes the carray virtual table.
**
** Think of this routine as the constructor for carray_vtab objects.
**
** All this routine needs to do is:
**
** (1) Allocate the carray_vtab object and initialize all fields.
**
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
** result set of queries against carray will look like.
*/
static int carrayConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
sqlite3_vtab *pNew;
int rc;
/* Column numbers */
#define CARRAY_COLUMN_VALUE 0
#define CARRAY_COLUMN_POINTER 1
#define CARRAY_COLUMN_COUNT 2
#define CARRAY_COLUMN_CTYPE 3
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(value,pointer hidden,count hidden,ctype hidden)");
if( rc==SQLITE_OK ){
pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
}
return rc;
}
/*
** This method is the destructor for carray_cursor objects.
*/
static int carrayDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** Constructor for a new carray_cursor object.
*/
static int carrayOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
carray_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Destructor for a carray_cursor.
*/
static int carrayClose(sqlite3_vtab_cursor *cur){
sqlite3_free(cur);
return SQLITE_OK;
}
/*
** Advance a carray_cursor to its next row of output.
*/
static int carrayNext(sqlite3_vtab_cursor *cur){
carray_cursor *pCur = (carray_cursor*)cur;
pCur->iRowid++;
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the carray_cursor
** is currently pointing.
*/
static int carrayColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
carray_cursor *pCur = (carray_cursor*)cur;
sqlite3_int64 x = 0;
switch( i ){
case CARRAY_COLUMN_POINTER: return SQLITE_OK;
case CARRAY_COLUMN_COUNT: x = pCur->iCnt; break;
case CARRAY_COLUMN_CTYPE: {
sqlite3_result_text(ctx, azCarrayType[pCur->eType], -1, SQLITE_STATIC);
return SQLITE_OK;
}
default: {
switch( pCur->eType ){
case CARRAY_INT32: {
int *p = (int*)pCur->pPtr;
sqlite3_result_int(ctx, p[pCur->iRowid-1]);
return SQLITE_OK;
}
case CARRAY_INT64: {
sqlite3_int64 *p = (sqlite3_int64*)pCur->pPtr;
sqlite3_result_int64(ctx, p[pCur->iRowid-1]);
return SQLITE_OK;
}
case CARRAY_DOUBLE: {
double *p = (double*)pCur->pPtr;
sqlite3_result_double(ctx, p[pCur->iRowid-1]);
return SQLITE_OK;
}
case CARRAY_TEXT: {
const char **p = (const char**)pCur->pPtr;
sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT);
return SQLITE_OK;
}
default: {
const struct iovec *p = (struct iovec*)pCur->pPtr;
assert( pCur->eType==CARRAY_BLOB );
sqlite3_result_blob(ctx, p[pCur->iRowid-1].iov_base,
(int)p[pCur->iRowid-1].iov_len, SQLITE_TRANSIENT);
return SQLITE_OK;
}
}
}
}
sqlite3_result_int64(ctx, x);
return SQLITE_OK;
}
/*
** Return the rowid for the current row. In this implementation, the
** rowid is the same as the output value.
*/
static int carrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
carray_cursor *pCur = (carray_cursor*)cur;
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int carrayEof(sqlite3_vtab_cursor *cur){
carray_cursor *pCur = (carray_cursor*)cur;
return pCur->iRowid>pCur->iCnt;
}
/*
** This method is called to "rewind" the carray_cursor object back
** to the first row of output.
*/
static int carrayFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
carray_cursor *pCur = (carray_cursor *)pVtabCursor;
pCur->pPtr = 0;
pCur->iCnt = 0;
switch( idxNum ){
case 1: {
carray_bind *pBind = sqlite3_value_pointer(argv[0], "carray-bind");
if( pBind==0 ) break;
pCur->pPtr = pBind->aData;
pCur->iCnt = pBind->nData;
pCur->eType = pBind->mFlags & 0x07;
break;
}
case 2:
case 3: {
pCur->pPtr = sqlite3_value_pointer(argv[0], "carray");
pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0;
if( idxNum<3 ){
pCur->eType = CARRAY_INT32;
}else{
unsigned char i;
const char *zType = (const char*)sqlite3_value_text(argv[2]);
for(i=0; i<sizeof(azCarrayType)/sizeof(azCarrayType[0]); i++){
if( sqlite3_stricmp(zType, azCarrayType[i])==0 ) break;
}
if( i>=sizeof(azCarrayType)/sizeof(azCarrayType[0]) ){
pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
"unknown datatype: %Q", zType);
return SQLITE_ERROR;
}else{
pCur->eType = i;
}
}
break;
}
}
pCur->iRowid = 1;
return SQLITE_OK;
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the carray virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
**
** In this implementation idxNum is used to represent the
** query plan. idxStr is unused.
**
** idxNum is:
**
** 1 If only the pointer= constraint exists. In this case, the
** parameter must be bound using sqlite3_carray_bind().
**
** 2 if the pointer= and count= constraints exist.
**
** 3 if the ctype= constraint also exists.
**
** idxNum is 0 otherwise and carray becomes an empty table.
*/
static int carrayBestIndex(
sqlite3_vtab *tab,
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pConstraint->iColumn>=0 ) seen |= 1 << pConstraint->iColumn;
if( pConstraint->usable==0 ) continue;
switch( pConstraint->iColumn ){
case CARRAY_COLUMN_POINTER:
ptrIdx = i;
break;
case CARRAY_COLUMN_COUNT:
cntIdx = i;
break;
case CARRAY_COLUMN_CTYPE:
ctypeIdx = i;
break;
}
}
if( ptrIdx>=0 ){
pIdxInfo->aConstraintUsage[ptrIdx].argvIndex = 1;
pIdxInfo->aConstraintUsage[ptrIdx].omit = 1;
pIdxInfo->estimatedCost = (double)1;
pIdxInfo->estimatedRows = 100;
pIdxInfo->idxNum = 1;
if( cntIdx>=0 ){
pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2;
pIdxInfo->aConstraintUsage[cntIdx].omit = 1;
pIdxInfo->idxNum = 2;
if( ctypeIdx>=0 ){
pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3;
pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1;
pIdxInfo->idxNum = 3;
}else if( seen & (1<<CARRAY_COLUMN_CTYPE) ){
/* In a three-argument carray(), we need to know the value of all
** three arguments */
return SQLITE_CONSTRAINT;
}
}else if( seen & (1<<CARRAY_COLUMN_COUNT) ){
/* In a two-argument carray(), we need to know the value of both
** arguments */
return SQLITE_CONSTRAINT;
}
}else{
pIdxInfo->estimatedCost = (double)2147483647;
pIdxInfo->estimatedRows = 2147483647;
pIdxInfo->idxNum = 0;
}
return SQLITE_OK;
}
/*
** This following structure defines all the methods for the
** carray virtual table.
*/
static sqlite3_module carrayModule = {
0, /* iVersion */
0, /* xCreate */
carrayConnect, /* xConnect */
carrayBestIndex, /* xBestIndex */
carrayDisconnect, /* xDisconnect */
0, /* xDestroy */
carrayOpen, /* xOpen - open a cursor */
carrayClose, /* xClose - close a cursor */
carrayFilter, /* xFilter - configure scan constraints */
carrayNext, /* xNext - advance a cursor */
carrayEof, /* xEof - check for end of scan */
carrayColumn, /* xColumn - read data */
carrayRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadow */
0 /* xIntegrity */
};
/*
** Destructor for the carray_bind object
*/
static void carrayBindDel(void *pPtr){
carray_bind *p = (carray_bind*)pPtr;
if( p->xDel!=SQLITE_STATIC ){
p->xDel(p->aData);
}
sqlite3_free(p);
}
/*
** Invoke this interface in order to bind to the single-argument
** version of CARRAY().
*/
SQLITE_API int sqlite3_carray_bind(
sqlite3_stmt *pStmt,
int idx,
void *aData,
int nData,
int mFlags,
void (*xDestroy)(void*)
){
carray_bind *pNew = 0;
int i;
int rc = SQLITE_OK;
/* Ensure that the mFlags value is acceptable. */
assert( CARRAY_INT32==0 && CARRAY_INT64==1 && CARRAY_DOUBLE==2 );
assert( CARRAY_TEXT==3 && CARRAY_BLOB==4 );
if( mFlags<CARRAY_INT32 || mFlags>CARRAY_BLOB ){
rc = SQLITE_ERROR;
goto carray_bind_error;
}
pNew = sqlite3_malloc64(sizeof(*pNew));
if( pNew==0 ){
rc = SQLITE_NOMEM;
goto carray_bind_error;
}
pNew->nData = nData;
pNew->mFlags = mFlags;
return (h % nBucket);
}
/*
** Arguments aLeft and aRight are pointers to change records for table pTab.
** This function returns true if the two records apply to the same row (i.e.
** have the same values stored in the primary key columns), or false
** otherwise.
*/
static int sessionChangeEqual(
SessionTable *pTab, /* Table used for PK definition */
int bLeftPkOnly, /* True if aLeft[] contains PK fields only */
u8 *aLeft, /* Change record */
int bRightPkOnly, /* True if aRight[] contains PK fields only */
u8 *aRight /* Change record */
){
u8 *a1 = aLeft; /* Cursor to iterate through aLeft */
u8 *a2 = aRight; /* Cursor to iterate through aRight */
int iCol; /* Used to iterate through table columns */
for(iCol=0; iCol<pTab->nCol; iCol++){
if( pTab->abPK[iCol] ){
int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
if( n1!=n2 || memcmp(a1, a2, n1) ){
return 0;
}
a1 += n1;
a2 += n2;
}else{
if( bLeftPkOnly==0 ) a1 += sessionSerialLen(a1);
if( bRightPkOnly==0 ) a2 += sessionSerialLen(a2);
}
}
return 1;
}
/*
** Arguments aLeft and aRight both point to buffers containing change
** records with nCol columns. This function "merges" the two records into
** a single records which is written to the buffer at *paOut. *paOut is
** then set to point to one byte after the last byte written before
** returning.
**
** The merging of records is done as follows: For each column, if the
** aRight record contains a value for the column, copy the value from
** their. Otherwise, if aLeft contains a value, copy it. If neither
** record contains a value for a given column, then neither does the
** output record.
*/
static void sessionMergeRecord(
u8 **paOut,
int nCol,
u8 *aLeft,
u8 *aRight
){
u8 *a1 = aLeft; /* Cursor used to iterate through aLeft */
u8 *a2 = aRight; /* Cursor used to iterate through aRight */
u8 *aOut = *paOut; /* Output cursor */
int iCol; /* Used to iterate from 0 to nCol */
for(iCol=0; iCol<nCol; iCol++){
int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
if( *a2 ){
memcpy(aOut, a2, n2);
aOut += n2;
}else{
memcpy(aOut, a1, n1);
aOut += n1;
}
a1 += n1;
a2 += n2;
}
*paOut = aOut;
}
/*
** This is a helper function used by sessionMergeUpdate().
**
** When this function is called, both *paOne and *paTwo point to a value
** within a change record. Before it returns, both have been advanced so
** as to point to the next value in the record.
**
** If, when this function is called, *paTwo points to a valid value (i.e.
** *paTwo[0] is not 0x00 - the "no value" placeholder), a copy of the *paTwo
** pointer is returned and *pnVal is set to the number of bytes in the
** serialized value. Otherwise, a copy of *paOne is returned and *pnVal
** set to the number of bytes in the value at *paOne. If *paOne points
** to the "no value" placeholder, *pnVal is set to 1. In other words:
**
** if( *paTwo is valid ) return *paTwo;
** return *paOne;
**
*/
static u8 *sessionMergeValue(
u8 **paOne, /* IN/OUT: Left-hand buffer pointer */
u8 **paTwo, /* IN/OUT: Right-hand buffer pointer */
int *pnVal /* OUT: Bytes in returned value */
){
u8 *a1 = *paOne;
u8 *a2 = *paTwo;
u8 *pRet = 0;
int n1;
assert( a1 );
if( a2 ){
int n2 = sessionSerialLen(a2);
if( *a2 ){
*pnVal = n2;
pRet = a2;
}
*paTwo = &a2[n2];
}
n1 = sessionSerialLen(a1);
if( pRet==0 ){
*pnVal = n1;
if( *p=='\'' ){
p++;
if( *p!='\'' ) break;
}
p++;
if( *p==0 ) p = 0;
}
break;
default:
/* maybe a number */
if( *p=='+' || *p=='-' ) p++;
while( fts5_isdigit(*p) ) p++;
/* At this point, if the literal was an integer, the parse is
** finished. Or, if it is a floating point value, it may continue
** with either a decimal point or an 'E' character. */
if( *p=='.' && fts5_isdigit(p[1]) ){
p += 2;
while( fts5_isdigit(*p) ) p++;
}
if( p==pIn ) p = 0;
break;
}
return p;
}
/*
** The first character of the string pointed to by argument z is guaranteed
** to be an open-quote character (see function fts5_isopenquote()).
**
** This function searches for the corresponding close-quote character within
** the string and, if found, dequotes the string in place and adds a new
** nul-terminator byte.
**
** If the close-quote is found, the value returned is the byte offset of
** the character immediately following it. Or, if the close-quote is not
** found, -1 is returned. If -1 is returned, the buffer is left in an
** undefined state.
*/
static int fts5Dequote(char *z){
char q;
int iIn = 1;
int iOut = 0;
q = z[0];
/* Set stack variable q to the close-quote character */
assert( q=='[' || q=='\'' || q=='"' || q=='`' );
if( q=='[' ) q = ']';
while( z[iIn] ){
if( z[iIn]==q ){
if( z[iIn+1]!=q ){
/* Character iIn was the close quote. */
iIn++;
break;
}else{
/* Character iIn and iIn+1 form an escaped quote character. Skip
** the input cursor past both and copy a single quote character
** to the output buffer. */
iIn += 2;
z[iOut++] = q;
}
}else{
z[iOut++] = z[iIn++];
}
}
z[iOut] = '\0';
return iIn;
}
/*
** Convert an SQL-style quoted string into a normal string by removing
** the quote characters. The conversion is done in-place. If the
** input does not begin with a quote character, then this routine
** is a no-op.
**
** Examples:
**
** "abc" becomes abc
** 'xyz' becomes xyz
** [pqr] becomes pqr
** `mno` becomes mno
*/
static void sqlite3Fts5Dequote(char *z){
char quote; /* Quote character (if any ) */
assert( 0==fts5_iswhitespace(z[0]) );
quote = z[0];
if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
fts5Dequote(z);
}
}
struct Fts5Enum {
const char *zName;
int eVal;
};
typedef struct Fts5Enum Fts5Enum;
static int fts5ConfigSetEnum(
const Fts5Enum *aEnum,
const char *zEnum,
int *peVal
){
int nEnum = (int)strlen(zEnum);
int i;
int iVal = -1;
for(i=0; aEnum[i].zName; i++){
if( sqlite3_strnicmp(aEnum[i].zName, zEnum, nEnum)==0 ){
if( iVal>=0 ) return SQLITE_ERROR;
iVal = aEnum[i].eVal;
}
}
*peVal = iVal;
int nEmpty; /* Number of contiguous term-less nodes */
int nDlidx; /* Allocated size of aDlidx[] array */
Fts5DlidxWriter *aDlidx; /* Array of Fts5DlidxWriter objects */
/* Values to insert into the %_idx table */
Fts5Buffer btterm; /* Next term to insert into %_idx table */
int iBtPage; /* Page number corresponding to btterm */
};
typedef struct Fts5CResult Fts5CResult;
struct Fts5CResult {
u16 iFirst; /* aSeg[] index of firstest iterator */
u8 bTermEq; /* True if the terms are equal */
};
/*
** Object for iterating through a single segment, visiting each term/rowid
** pair in the segment.
**
** pSeg:
** The segment to iterate through.
**
** iLeafPgno:
** Current leaf page number within segment.
**
** iLeafOffset:
** Byte offset within the current leaf that is the first byte of the
** position list data (one byte passed the position-list size field).
**
** pLeaf:
** Buffer containing current leaf page data. Set to NULL at EOF.
**
** iTermLeafPgno, iTermLeafOffset:
** Leaf page number containing the last term read from the segment. And
** the offset immediately following the term data.
**
** flags:
** Mask of FTS5_SEGITER_XXX values. Interpreted as follows:
**
** FTS5_SEGITER_ONETERM:
** If set, set the iterator to point to EOF after the current doclist
** has been exhausted. Do not proceed to the next term in the segment.
**
** FTS5_SEGITER_REVERSE:
** This flag is only ever set if FTS5_SEGITER_ONETERM is also set. If
** it is set, iterate through rowid in descending order instead of the
** default ascending order.
**
** iRowidOffset/nRowidOffset/aRowidOffset:
** These are used if the FTS5_SEGITER_REVERSE flag is set.
**
** For each rowid on the page corresponding to the current term, the
** corresponding aRowidOffset[] entry is set to the byte offset of the
** start of the "position-list-size" field within the page.
**
** iTermIdx:
** Index of current term on iTermLeafPgno.
**
** apTombstone/nTombstone:
** These are used for contentless_delete=1 tables only. When the cursor
** is first allocated, the apTombstone[] array is allocated so that it
** is large enough for all tombstones hash pages associated with the
** segment. The pages themselves are loaded lazily from the database as
** they are required.
*/
struct Fts5SegIter {
Fts5StructureSegment *pSeg; /* Segment to iterate through */
int flags; /* Mask of configuration flags */
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
i64 iLeafOffset; /* Byte offset within current leaf */
Fts5TombstoneArray *pTombArray; /* Array of tombstone pages */
/* Next method */
void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
/* The page and offset from which the current term was read. The offset
** is the offset of the first rowid in the current doclist. */
int iTermLeafPgno;
int iTermLeafOffset;
int iPgidxOff; /* Next offset in pgidx */
int iEndofDoclist;
/* The following are only used if the FTS5_SEGITER_REVERSE flag is set. */
int iRowidOffset; /* Current entry in aRowidOffset[] */
int nRowidOffset; /* Allocated size of aRowidOffset[] array */
int *aRowidOffset; /* Array of offset to rowid fields */
Fts5DlidxIter *pDlidx; /* If there is a doclist-index */
/* Variables populated based on current entry. */
Fts5Buffer term; /* Current term */
i64 iRowid; /* Current rowid */
int nPos; /* Number of bytes in current position list */
u8 bDel; /* True if the delete flag is set */
};
static int fts5IndexCorruptRowid(Fts5Index *pIdx, i64 iRowid){
pIdx->rc = FTS5_CORRUPT;
sqlite3Fts5ConfigErrmsg(pIdx->pConfig,
"fts5: corruption found reading blob %lld from table \"%s\"",
iRowid, pIdx->pConfig->zName
);
return SQLITE_CORRUPT_VTAB;
}
#define FTS5_CORRUPT_ROWID(pIdx, iRowid) fts5IndexCorruptRowid(pIdx, iRowid)
static int fts5IndexCorruptIter(Fts5Index *pIdx, Fts5SegIter *pIter){
pIdx->rc = FTS5_CORRUPT;
sqlite3Fts5ConfigErrmsg(pIdx->pConfig,
"fts5: corruption on page %d, segment %d, table \"%s\"",
pIter->iLeafPgno, pIter->pSeg->iSegid, pIdx->pConfig->zName
);
return SQLITE_CORRUPT_VTAB;
}
#define FTS5_CORRUPT_ITER(pIdx, pIter) fts5IndexCorruptIter(pIdx, pIter)
static int fts5IndexCorruptIdx(Fts5Index *pIdx){
fts5BufferFree(&term);
}
decode_out:
sqlite3_free(a);
if( rc==SQLITE_OK ){
sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
}else{
sqlite3_result_error_code(pCtx, rc);
}
fts5BufferFree(&s);
}
#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
/*
** The implementation of user-defined scalar function fts5_rowid().
*/
static void fts5RowidFunction(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args (always 2) */
sqlite3_value **apVal /* Function arguments */
){
const char *zArg;
if( nArg==0 ){
sqlite3_result_error(pCtx, "should be: fts5_rowid(subject, ....)", -1);
}else{
zArg = (const char*)sqlite3_value_text(apVal[0]);
if( 0==sqlite3_stricmp(zArg, "segment") ){
i64 iRowid;
int segid, pgno;
if( nArg!=3 ){
sqlite3_result_error(pCtx,
"should be: fts5_rowid('segment', segid, pgno))", -1
);
}else{
segid = sqlite3_value_int(apVal[1]);
pgno = sqlite3_value_int(apVal[2]);
iRowid = FTS5_SEGMENT_ROWID(segid, pgno);
sqlite3_result_int64(pCtx, iRowid);
}
}else{
sqlite3_result_error(pCtx,
"first arg to fts5_rowid() must be 'segment'" , -1
);
}
}
}
#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
typedef struct Fts5StructVtab Fts5StructVtab;
struct Fts5StructVtab {
sqlite3_vtab base;
};
typedef struct Fts5StructVcsr Fts5StructVcsr;
struct Fts5StructVcsr {
sqlite3_vtab_cursor base;
Fts5Structure *pStruct;
int iLevel;
int iSeg;
int iRowid;
};
/*
** Create a new fts5_structure() table-valued function.
*/
static int fts5structConnectMethod(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
Fts5StructVtab *pNew = 0;
int rc = SQLITE_OK;
rc = sqlite3_declare_vtab(db,
"CREATE TABLE xyz("
"level, segment, merge, segid, leaf1, leaf2, loc1, loc2, "
"npgtombstone, nentrytombstone, nentry, struct HIDDEN);"
);
if( rc==SQLITE_OK ){
pNew = sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
}
*ppVtab = (sqlite3_vtab*)pNew;
return rc;
}
/*
** We must have a single struct=? constraint that will be passed through
** into the xFilter method. If there is no valid struct=? constraint,
** then return an SQLITE_CONSTRAINT error.
*/
static int fts5structBestIndexMethod(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i;
int rc = SQLITE_CONSTRAINT;
struct sqlite3_index_constraint *p;
pIdxInfo->estimatedCost = (double)100;
pIdxInfo->estimatedRows = 100;
pIdxInfo->idxNum = 0;
for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
if( p->usable==0 ) continue;
if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==11 ){
rc = SQLITE_OK;
pIdxInfo->aConstraintUsage[i].omit = 1;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
break;
}
}
return rc;
}
/*
** This method is the destructor for bytecodevtab objects.
*/
static int fts5structDisconnectMethod(sqlite3_vtab *pVtab){
Fts5StructVtab *p = (Fts5StructVtab*)pVtab;
sqlite3_free(p);
return SQLITE_OK;
}
/*
** Constructor for a new bytecodevtab_cursor object.
*/
static int fts5structOpenMethod(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
int rc = SQLITE_OK;
Fts5StructVcsr *pNew = 0;
pNew = sqlite3Fts5MallocZero(&rc, sizeof(*pNew));
*ppCsr = (sqlite3_vtab_cursor*)pNew;
return SQLITE_OK;
}
/*
** Destructor for a bytecodevtab_cursor.
*/
static int fts5structCloseMethod(sqlite3_vtab_cursor *cur){
Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
fts5StructureRelease(pCsr->pStruct);
sqlite3_free(pCsr);
return SQLITE_OK;
}
/*
** Advance a bytecodevtab_cursor to its next row of output.
*/
static int fts5structNextMethod(sqlite3_vtab_cursor *cur){
Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
Fts5Structure *p = pCsr->pStruct;
assert( pCsr->pStruct );
pCsr->iSeg++;
pCsr->iRowid++;
while( pCsr->iLevel<p->nLevel && pCsr->iSeg>=p->aLevel[pCsr->iLevel].nSeg ){
pCsr->iLevel++;
pCsr->iSeg = 0;
}
if( pCsr->iLevel>=p->nLevel ){
fts5StructureRelease(pCsr->pStruct);
pCsr->pStruct = 0;
}
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int fts5structEofMethod(sqlite3_vtab_cursor *cur){
Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
return pCsr->pStruct==0;
}
static int fts5structRowidMethod(
sqlite3_vtab_cursor *cur,
sqlite_int64 *piRowid
){
Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
*piRowid = pCsr->iRowid;
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the bytecodevtab_cursor
** is currently pointing.
*/
static int fts5structColumnMethod(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
Fts5StructVcsr *pCsr = (Fts5StructVcsr*)cur;
Fts5Structure *p = pCsr->pStruct;
Fts5StructureSegment *pSeg = &p->aLevel[pCsr->iLevel].aSeg[pCsr->iSeg];
switch( i ){
case 0: /* level */
sqlite3_result_int(ctx, pCsr->iLevel);
break;
case 1: /* segment */
sqlite3_result_int(ctx, pCsr->iSeg);
break;
case 2: /* merge */
sqlite3_result_int(ctx, pCsr->iSeg < p->aLevel[pCsr->iLevel].nMerge);
break;
case 3: /* segid */
sqlite3_result_int(ctx, pSeg->iSegid);
break;
case 4: /* leaf1 */
sqlite3_result_int(ctx, pSeg->pgnoFirst);
break;
case 5: /* leaf2 */
sqlite3_result_int(ctx, pSeg->pgnoLast);
break;
case 6: /* origin1 */
sqlite3_result_int64(ctx, pSeg->iOrigin1);
break;
case 7: /* origin2 */
sqlite3_result_int64(ctx, pSeg->iOrigin2);
break;
case 8: /* npgtombstone */
sqlite3_result_int(ctx, pSeg->nPgTombstone);
break;
case 9: /* nentrytombstone */
sqlite3_result_int64(ctx, pSeg->nEntryTombstone);
break;
case 10: /* nentry */
sqlite3_result_int64(ctx, pSeg->nEntry);
break;
}
return SQLITE_OK;
}
/*
** Initialize a cursor.
**
** idxNum==0 means show all subprograms
** idxNum==1 means show only the main bytecode and omit subprograms.
*/
static int fts5structFilterMethod(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
Fts5StructVcsr *pCsr = (Fts5StructVcsr *)pVtabCursor;
int rc = SQLITE_OK;
const u8 *aBlob = 0;
int nBlob = 0;
assert( argc==1 );
fts5StructureRelease(pCsr->pStruct);
pCsr->pStruct = 0;
nBlob = sqlite3_value_bytes(argv[0]);
aBlob = (const u8*)sqlite3_value_blob(argv[0]);
rc = fts5StructureDecode(aBlob, nBlob, 0, &pCsr->pStruct);
if( rc==SQLITE_OK ){
pCsr->iLevel = 0;
pCsr->iRowid = 0;
pCsr->iSeg = -1;
rc = fts5structNextMethod(pVtabCursor);
}
return rc;
}
#endif /* SQLITE_TEST || SQLITE_FTS5_DEBUG */
/*
** This is called as part of registering the FTS5 module with database
** connection db. It registers several user-defined scalar functions useful
** with FTS5.
**
** If successful, SQLITE_OK is returned. If an error occurs, some other
** SQLite error code is returned instead.
*/
static int sqlite3Fts5IndexInit(sqlite3 *db){
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
int rc = sqlite3_create_function(
db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5_decode_none", 2,
SQLITE_UTF8, (void*)db, fts5DecodeFunction, 0, 0
);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0
);
}
if( rc==SQLITE_OK ){
static const sqlite3_module fts5structure_module = {
0, /* iVersion */
0, /* xCreate */
fts5structConnectMethod, /* xConnect */
** structures should not be corrupt. Otherwise, true. If it is false, extra
** assert() conditions in the fts5 code are activated - conditions that are
** only true if it is guaranteed that the fts5 database is not corrupt.
*/
#ifdef SQLITE_DEBUG
SQLITE_API int sqlite3_fts5_may_be_corrupt = 1;
#endif
typedef struct Fts5Auxdata Fts5Auxdata;
typedef struct Fts5Auxiliary Fts5Auxiliary;
typedef struct Fts5Cursor Fts5Cursor;
typedef struct Fts5FullTable Fts5FullTable;
typedef struct Fts5Sorter Fts5Sorter;
typedef struct Fts5TokenizerModule Fts5TokenizerModule;
/*
** NOTES ON TRANSACTIONS:
**
** SQLite invokes the following virtual table methods as transactions are
** opened and closed by the user:
**
** xBegin(): Start of a new transaction.
** xSync(): Initial part of two-phase commit.
** xCommit(): Final part of two-phase commit.
** xRollback(): Rollback the transaction.
**
** Anything that is required as part of a commit that may fail is performed
** in the xSync() callback. Current versions of SQLite ignore any errors
** returned by xCommit().
**
** And as sub-transactions are opened/closed:
**
** xSavepoint(int S): Open savepoint S.
** xRelease(int S): Commit and close savepoint S.
** xRollbackTo(int S): Rollback to start of savepoint S.
**
** During a write-transaction the fts5_index.c module may cache some data
** in-memory. It is flushed to disk whenever xSync(), xRelease() or
** xSavepoint() is called. And discarded whenever xRollback() or xRollbackTo()
** is called.
**
** Additionally, if SQLITE_DEBUG is defined, an instance of the following
** structure is used to record the current transaction state. This information
** is not required, but it is used in the assert() statements executed by
** function fts5CheckTransactionState() (see below).
*/
struct Fts5TransactionState {
int eState; /* 0==closed, 1==open, 2==synced */
int iSavepoint; /* Number of open savepoints (0 -> none) */
};
/*
** A single object of this type is allocated when the FTS5 module is
** registered with a database handle. It is used to store pointers to
** all registered FTS5 extensions - tokenizers and auxiliary functions.
*/
struct Fts5Global {
fts5_api api; /* User visible part of object (see fts5.h) */
sqlite3 *db; /* Associated database connection */
i64 iNextId; /* Used to allocate unique cursor ids */
Fts5Auxiliary *pAux; /* First in list of all aux. functions */
Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */
Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */
Fts5Cursor *pCsr; /* First in list of all open cursors */
u32 aLocaleHdr[4];
};
/*
** Size of header on fts5_locale() values. And macro to access a buffer
** containing a copy of the header from an Fts5Config pointer.
*/
#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
#define FTS5_INSTTOKEN_SUBTYPE 73
/*
** Each auxiliary function registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pAux list.
*/
struct Fts5Auxiliary {
Fts5Global *pGlobal; /* Global context for this function */
char *zFunc; /* Function name (nul-terminated) */
void *pUserData; /* User-data pointer */
fts5_extension_function xFunc; /* Callback function */
void (*xDestroy)(void*); /* Destructor function */
Fts5Auxiliary *pNext; /* Next registered auxiliary function */
};
/*
** Each tokenizer module registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pTok list.
**
** bV2Native:
** True if the tokenizer was registered using xCreateTokenizer_v2(), false
** for xCreateTokenizer(). If this variable is true, then x2 is populated
** with the routines as supplied by the caller and x1 contains synthesized
** wrapper routines. In this case the user-data pointer passed to
** x1.xCreate should be a pointer to the Fts5TokenizerModule structure,
** not a copy of pUserData.
**
** Of course, if bV2Native is false, then x1 contains the real routines and
** x2 the synthesized ones. In this case a pointer to the Fts5TokenizerModule
** object should be passed to x2.xCreate.
**
** The synthesized wrapper routines are necessary for xFindTokenizer(_v2)
** calls.
*/
struct Fts5TokenizerModule {
char *zName; /* Name of tokenizer */
void *pUserData; /* User pointer passed to xCreate() */
int bV2Native; /* True if v2 native tokenizer */
fts5_tokenizer x1; /* Tokenizer functions */
fts5_tokenizer_v2 x2; /* V2 tokenizer functions */
void (*xDestroy)(void*); /* Destructor function */
Fts5TokenizerModule *pNext; /* Next registered tokenizer module */
};
struct Fts5FullTable {
Fts5Table p; /* Public class members from fts5Int.h */
Fts5Storage *pStorage; /* Document store */
Fts5Global *pGlobal; /* Global (connection wide) data */
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
int iSavepoint; /* Successful xSavepoint()+1 */
#ifdef SQLITE_DEBUG
struct Fts5TransactionState ts;
#endif
};
struct Fts5MatchPhrase {
Fts5Buffer *pPoslist; /* Pointer to current poslist */
int nTerm; /* Size of phrase in terms */
};
/*
** pStmt:
** SELECT rowid, <fts> FROM <fts> ORDER BY +rank;
**
** aIdx[]:
** There is one entry in the aIdx[] array for each phrase in the query,
** the value of which is the offset within aPoslist[] following the last
** byte of the position list for the corresponding phrase.
*/
struct Fts5Sorter {
sqlite3_stmt *pStmt;
i64 iRowid; /* Current rowid */
const u8 *aPoslist; /* Position lists for current row */
int nIdx; /* Number of entries in aIdx[] */
int aIdx[FLEXARRAY]; /* Offsets into aPoslist for current row */
};
/* Size (int bytes) of an Fts5Sorter object with N indexes */
#define SZ_FTS5SORTER(N) (offsetof(Fts5Sorter,nIdx)+((N+2)/2)*sizeof(i64))
/*
** Virtual-table cursor object.
**
** iSpecial:
** If this is a 'special' query (refer to function fts5SpecialMatch()),
** then this variable contains the result of the query.
**
** iFirstRowid, iLastRowid:
** These variables are only used for FTS5_PLAN_MATCH cursors. Assuming the
** cursor iterates in ascending order of rowids, iFirstRowid is the lower
** limit of rowids to return, and iLastRowid the upper. In other words, the
** WHERE clause in the user's query might have been:
**
** <tbl> MATCH <expr> AND rowid BETWEEN $iFirstRowid AND $iLastRowid
**
** If the cursor iterates in descending order of rowid, iFirstRowid
** is the upper limit (i.e. the "first" rowid visited) and iLastRowid
** the lower.
*/
struct Fts5Cursor {
sqlite3_vtab_cursor base; /* Base class used by SQLite core */
Fts5Cursor *pNext; /* Next cursor in Fts5Cursor.pCsr list */
int *aColumnSize; /* Values for xColumnSize() */
i64 iCsrId; /* Cursor id */
/* Zero from this point onwards on cursor reset */
int ePlan; /* FTS5_PLAN_XXX value */
int bDesc; /* True for "ORDER BY rowid DESC" queries */
i64 iFirstRowid; /* Return no rowids earlier than this */
i64 iLastRowid; /* Return no rowids later than this */
sqlite3_stmt *pStmt; /* Statement used to read %_content */
Fts5Expr *pExpr; /* Expression for MATCH queries */
Fts5Sorter *pSorter; /* Sorter for "ORDER BY rank" queries */
int csrflags; /* Mask of cursor flags (see below) */
i64 iSpecial; /* Result of special query */
/* "rank" function. Populated on demand from vtab.xColumn(). */
char *zRank; /* Custom rank function */
char *zRankArgs; /* Custom rank function args */
Fts5Auxiliary *pRank; /* Rank callback (or NULL) */
int nRankArg; /* Number of trailing arguments for rank() */
sqlite3_value **apRankArg; /* Array of trailing arguments */
sqlite3_stmt *pRankArgStmt; /* Origin of objects in apRankArg[] */
/* Auxiliary data storage */
Fts5Auxiliary *pAux; /* Currently executing extension function */
Fts5Auxdata *pAuxdata; /* First in linked list of saved aux-data */
/* Cache used by auxiliary API functions xInst() and xInstCount() */
Fts5PoslistReader *aInstIter; /* One for each phrase */
int nInstAlloc; /* Size of aInst[] array (entries / 3) */
int nInstCount; /* Number of phrase instances */
int *aInst; /* 3 integers per phrase instance */
};
/*
** Bits that make up the "idxNum" parameter passed indirectly by
** xBestIndex() to xFilter().
*/
#define FTS5_BI_MATCH 0x0001 /* <tbl> MATCH ? */
#define FTS5_BI_RANK 0x0002 /* rank MATCH ? */
#define FTS5_BI_ROWID_EQ 0x0004 /* rowid == ? */
#define FTS5_BI_ROWID_LE 0x0008 /* rowid <= ? */
#define FTS5_BI_ROWID_GE 0x0010 /* rowid >= ? */
#define FTS5_BI_ORDER_RANK 0x0020
#define FTS5_BI_ORDER_ROWID 0x0040
#define FTS5_BI_ORDER_DESC 0x0080
/*
** Values for Fts5Cursor.csrflags
*/
#define FTS5CSR_EOF 0x01
#define FTS5CSR_REQUIRE_CONTENT 0x02
#define FTS5CSR_REQUIRE_DOCSIZE 0x04
#define FTS5CSR_REQUIRE_INST 0x08
#define FTS5CSR_FREE_ZRANK 0x10
#define FTS5CSR_REQUIRE_RESEEK 0x20
#define FTS5CSR_REQUIRE_POSLIST 0x40
#define BitFlagAllTest(x,y) (((x) & (y))==(y))
#define BitFlagTest(x,y) (((x) & (y))!=0)
/*
** Macros to Set(), Clear() and Test() cursor flags.
*/
#define CsrFlagSet(pCsr, flag) ((pCsr)->csrflags |= (flag))
#define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag))
#define CsrFlagTest(pCsr, flag) ((pCsr)->csrflags & (flag))
struct Fts5Auxdata {
Fts5Auxiliary *pAux; /* Extension to which this belongs */
void *pPtr; /* Pointer value */
void(*xDelete)(void*); /* Destructor */
Fts5Auxdata *pNext; /* Next object in linked list */
};
#ifdef SQLITE_DEBUG
#define FTS5_BEGIN 1
#define FTS5_SYNC 2
#define FTS5_COMMIT 3
#define FTS5_ROLLBACK 4
#define FTS5_SAVEPOINT 5
#define FTS5_RELEASE 6
#define FTS5_ROLLBACKTO 7
static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
switch( op ){
case FTS5_BEGIN:
assert( p->ts.eState==0 );
p->ts.eState = 1;
p->ts.iSavepoint = -1;
break;
case FTS5_SYNC:
assert( p->ts.eState==1 || p->ts.eState==2 );
p->ts.eState = 2;
break;
case FTS5_COMMIT:
assert( p->ts.eState==2 );
p->ts.eState = 0;
break;
case FTS5_ROLLBACK:
assert( p->ts.eState==1 || p->ts.eState==2 || p->ts.eState==0 );
p->ts.eState = 0;
break;
case FTS5_SAVEPOINT:
assert( p->ts.eState>=1 );
assert( iSavepoint>=0 );
assert( iSavepoint>=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint;
break;
case FTS5_RELEASE:
assert( p->ts.eState>=1 );
assert( iSavepoint>=0 );
assert( iSavepoint<=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint-1;
break;
case FTS5_ROLLBACKTO:
assert( p->ts.eState>=1 );
assert( iSavepoint>=-1 );
);
}
/* Call sqlite3_declare_vtab() */
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
}
/* Load the initial configuration */
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie-1);
}
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
rc = sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, (int)1);
}
if( rc==SQLITE_OK ){
rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
}
if( pConfig ) pConfig->pzErrmsg = 0;
if( rc!=SQLITE_OK ){
fts5FreeVtab(pTab);
pTab = 0;
}else if( bCreate ){
fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
}
*ppVTab = (sqlite3_vtab*)pTab;
return rc;
}
/*
** The xConnect() and xCreate() methods for the virtual table. All the
** work is done in function fts5InitVtab().
*/
static int fts5ConnectMethod(
sqlite3 *db, /* Database connection */
void *pAux, /* Pointer to tokenizer hash table */
int argc, /* Number of elements in argv array */
const char * const *argv, /* xCreate/xConnect argument array */
sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
char **pzErr /* OUT: sqlite3_malloc'd error message */
){
return fts5InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr);
}
static int fts5CreateMethod(
sqlite3 *db, /* Database connection */
void *pAux, /* Pointer to tokenizer hash table */
int argc, /* Number of elements in argv array */
const char * const *argv, /* xCreate/xConnect argument array */
sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */
char **pzErr /* OUT: sqlite3_malloc'd error message */
){
return fts5InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
}
/*
** The different query plans.
*/
#define FTS5_PLAN_MATCH 1 /* (<tbl> MATCH ?) */
#define FTS5_PLAN_SOURCE 2 /* A source cursor for SORTED_MATCH */
#define FTS5_PLAN_SPECIAL 3 /* An internal query */
#define FTS5_PLAN_SORTED_MATCH 4 /* (<tbl> MATCH ? ORDER BY rank) */
#define FTS5_PLAN_SCAN 5 /* No usable constraint */
#define FTS5_PLAN_ROWID 6 /* (rowid = ?) */
/*
** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
** extension is currently being used by a version of SQLite too old to
** support index-info flags. In that case this function is a no-op.
*/
static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
#if SQLITE_VERSION_NUMBER>=3008012
#ifndef SQLITE_CORE
if( sqlite3_libversion_number()>=3008012 )
#endif
{
pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
}
#endif
}
static void fts5SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
#if SQLITE_VERSION_NUMBER>=3008002
#ifndef SQLITE_CORE
if( sqlite3_libversion_number()>=3008002 )
#endif
{
pIdxInfo->estimatedRows = nRow;
}
#endif
}
static int fts5UsePatternMatch(
Fts5Config *pConfig,
struct sqlite3_index_constraint *p
){
assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
if( pConfig->t.ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
return 1;
}
if( pConfig->t.ePattern==FTS5_PATTERN_LIKE
&& (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
){
return 1;
}
return 0;
}
/*
** Implementation of the xBestIndex method for FTS5 tables. Within the
** WHERE constraint, it searches for the following:
**
** 1. A MATCH constraint against the table column.
** 2. A MATCH constraint against the "rank" column.
** 3. A MATCH constraint against some other column.
** 4. An == constraint against the rowid column.
** 5. A < or <= constraint against the rowid column.
** 6. A > or >= constraint against the rowid column.
**
bSeenGt = 1;
}
}
}
}
idxStr[iIdxStr] = '\0';
/* Set idxFlags flags for the ORDER BY clause
**
** Note that tokendata=1 tables cannot currently handle "ORDER BY rowid DESC".
*/
if( pInfo->nOrderBy==1 ){
int iSort = pInfo->aOrderBy[0].iColumn;
if( iSort==(pConfig->nCol+1) && nSeenMatch>0 ){
idxFlags |= FTS5_BI_ORDER_RANK;
}else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
idxFlags |= FTS5_BI_ORDER_ROWID;
}
if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){
pInfo->orderByConsumed = 1;
if( pInfo->aOrderBy[0].desc ){
idxFlags |= FTS5_BI_ORDER_DESC;
}
}
}
/* Calculate the estimated cost based on the flags set in idxFlags. */
if( bSeenEq ){
pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0;
fts5SetUniqueFlag(pInfo);
fts5SetEstimatedRows(pInfo, 1);
}else{
if( bSeenLt && bSeenGt ){
pInfo->estimatedCost = nSeenMatch ? 5000.0 : 750000.0;
}else if( bSeenLt || bSeenGt ){
pInfo->estimatedCost = nSeenMatch ? 7500.0 : 2250000.0;
}else{
pInfo->estimatedCost = nSeenMatch ? 10000.0 : 3000000.0;
}
for(i=1; i<nSeenMatch; i++){
pInfo->estimatedCost *= 0.4;
}
fts5SetEstimatedRows(pInfo, (i64)(pInfo->estimatedCost / 4.0));
}
pInfo->idxNum = idxFlags;
return SQLITE_OK;
}
static int fts5NewTransaction(Fts5FullTable *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
}
return sqlite3Fts5StorageReset(pTab->pStorage);
}
/*
** Implementation of xOpen method.
*/
static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
Fts5FullTable *pTab = (Fts5FullTable*)pVTab;
Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = 0; /* New cursor object */
sqlite3_int64 nByte; /* Bytes of space to allocate */
int rc; /* Return code */
rc = fts5NewTransaction(pTab);
if( rc==SQLITE_OK ){
nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
pCsr = (Fts5Cursor*)sqlite3_malloc64(nByte);
if( pCsr ){
Fts5Global *pGlobal = pTab->pGlobal;
memset(pCsr, 0, (size_t)nByte);
pCsr->aColumnSize = (int*)&pCsr[1];
pCsr->pNext = pGlobal->pCsr;
pGlobal->pCsr = pCsr;
pCsr->iCsrId = ++pGlobal->iNextId;
}else{
rc = SQLITE_NOMEM;
}
}
*ppCsr = (sqlite3_vtab_cursor*)pCsr;
return rc;
}
static int fts5StmtType(Fts5Cursor *pCsr){
if( pCsr->ePlan==FTS5_PLAN_SCAN ){
return (pCsr->bDesc) ? FTS5_STMT_SCAN_DESC : FTS5_STMT_SCAN_ASC;
}
return FTS5_STMT_LOOKUP;
}
/*
** This function is called after the cursor passed as the only argument
** is moved to point at a different row. It clears all cached data
** specific to the previous row stored by the cursor object.
*/
static void fts5CsrNewrow(Fts5Cursor *pCsr){
CsrFlagSet(pCsr,
FTS5CSR_REQUIRE_CONTENT
| FTS5CSR_REQUIRE_DOCSIZE
| FTS5CSR_REQUIRE_INST
| FTS5CSR_REQUIRE_POSLIST
);
}
static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
Fts5Auxdata *pData;
Fts5Auxdata *pNext;
sqlite3_free(pCsr->aInstIter);
sqlite3_free(pCsr->aInst);
if( pCsr->pStmt ){
int eStmt = fts5StmtType(pCsr);
sqlite3Fts5StorageStmtRelease(pTab->pStorage, eStmt, pCsr->pStmt);
}
if( pCsr->pSorter ){
Fts5Sorter *pSorter = pCsr->pSorter;
sqlite3_finalize(pSorter->pStmt);
sqlite3_free(pSorter);
}
if( pCsr->ePlan!=FTS5_PLAN_SOURCE ){
sqlite3Fts5ExprFree(pCsr->pExpr);
}
for(pData=pCsr->pAuxdata; pData; pData=pNext){
pNext = pData->pNext;
if( pData->xDelete ) pData->xDelete(pData->pPtr);
sqlite3_free(pData);
}
sqlite3_finalize(pCsr->pRankArgStmt);
sqlite3_free(pCsr->apRankArg);
if( CsrFlagTest(pCsr, FTS5CSR_FREE_ZRANK) ){
sqlite3_free(pCsr->zRank);
sqlite3_free(pCsr->zRankArgs);
}
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr));
}
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
if( pCursor ){
Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
Fts5Cursor **pp;
fts5FreeCursorComponents(pCsr);
/* Remove the cursor from the Fts5Global.pCsr list */
for(pp=&pTab->pGlobal->pCsr; (*pp)!=pCsr; pp=&(*pp)->pNext);
*pp = pCsr->pNext;
sqlite3_free(pCsr);
}
return SQLITE_OK;
}
static int fts5SorterNext(Fts5Cursor *pCsr){
Fts5Sorter *pSorter = pCsr->pSorter;
int rc;
rc = sqlite3_step(pSorter->pStmt);
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT);
}else if( rc==SQLITE_ROW ){
const u8 *a;
const u8 *aBlob;
int nBlob;
int i;
int iOff = 0;
rc = SQLITE_OK;
pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
nBlob = sqlite3_column_bytes(pSorter->pStmt, 1);
aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1);
/* nBlob==0 in detail=none mode. */
if( nBlob>0 ){
for(i=0; i<(pSorter->nIdx-1); i++){
int iVal;
a += fts5GetVarint32(a, iVal);
iOff += iVal;
pSorter->aIdx[i] = iOff;
}
pSorter->aIdx[i] = &aBlob[nBlob] - a;
pSorter->aPoslist = a;
}
fts5CsrNewrow(pCsr);
}
return rc;
}
/*
** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
** open on table pTab.
*/
static void fts5TripCursors(Fts5FullTable *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->ePlan==FTS5_PLAN_MATCH
&& pCsr->base.pVtab==(sqlite3_vtab*)pTab
){
CsrFlagSet(pCsr, FTS5CSR_REQUIRE_RESEEK);
}
}
}
/*
** If the REQUIRE_RESEEK flag is set on the cursor passed as the first
** argument, close and reopen all Fts5IndexIter iterators that the cursor
** is using. Then attempt to move the cursor to a rowid equal to or laster
** (in the cursors sort order - ASC or DESC) than the current rowid.
**
** If the new rowid is not equal to the old, set output parameter *pbSkip
** to 1 before returning. Otherwise, leave it unchanged.
**
** Return SQLITE_OK if successful or if no reseek was required, or an
** error code if an error occurred.
*/
static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
int rc = SQLITE_OK;
assert( *pbSkip==0 );
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int bDesc = pCsr->bDesc;
i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
rc = sqlite3Fts5ExprFirst(
pCsr->pExpr, pTab->p.pIndex, iRowid, pCsr->iLastRowid, bDesc
);
if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
*pbSkip = 1;
}
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK);
fts5CsrNewrow(pCsr);
if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
CsrFlagSet(pCsr, FTS5CSR_EOF);
*pbSkip = 1;
}
}
return rc;
}
/*
** Advance the cursor to the next row in the table that matches the
** search criteria.
**
** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned
** even if we reach end-of-file. The fts5EofMethod() will be called
** subsequently to determine whether or not an EOF was hit.
*/
static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc;
assert( (pCsr->ePlan<3)==
(pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE)
);
assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) );
/* If this cursor uses FTS5_PLAN_MATCH and this is a tokendata=1 table,
** clear any token mappings accumulated at the fts5_index.c level. In
** other cases, specifically FTS5_PLAN_SOURCE and FTS5_PLAN_SORTED_MATCH,
** we need to retain the mappings for the entire query. */
if( pCsr->ePlan==FTS5_PLAN_MATCH
&& ((Fts5Table*)pCursor->pVtab)->pConfig->bTokendata
){
sqlite3Fts5ExprClearTokens(pCsr->pExpr);
}
if( pCsr->ePlan<3 ){
int bSkip = 0;
if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc;
rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid);
CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr));
fts5CsrNewrow(pCsr);
}else{
switch( pCsr->ePlan ){
case FTS5_PLAN_SPECIAL: {
CsrFlagSet(pCsr, FTS5CSR_EOF);
rc = SQLITE_OK;
break;
}
case FTS5_PLAN_SORTED_MATCH: {
rc = fts5SorterNext(pCsr);
break;
}
default: {
Fts5Config *pConfig = ((Fts5Table*)pCursor->pVtab)->pConfig;
pConfig->bLock++;
rc = sqlite3_step(pCsr->pStmt);
pConfig->bLock--;
if( rc!=SQLITE_ROW ){
CsrFlagSet(pCsr, FTS5CSR_EOF);
rc = sqlite3_reset(pCsr->pStmt);
if( rc!=SQLITE_OK ){
pCursor->pVtab->zErrMsg = sqlite3_mprintf(
"%s", sqlite3_errmsg(pConfig->db)
);
}
}else{
rc = SQLITE_OK;
CsrFlagSet(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
}
break;
}
}
}
return rc;
}
static int fts5PrepareStatement(
sqlite3_stmt **ppStmt,
Fts5Config *pConfig,
const char *zFmt,
...
){
*pnLoc = nLoc - FTS5_LOCALE_HDR_SIZE;
*ppText = &p[nLoc+1];
*pnText = n - nLoc - 1;
return SQLITE_OK;
}
/*
** Argument pVal is the text of a full-text search expression. It may or
** may not have been wrapped by fts5_locale(). This function extracts
** the text of the expression, and sets output variable (*pzText) to
** point to a nul-terminated buffer containing the expression.
**
** If pVal was an fts5_locale() value, then sqlite3Fts5SetLocale() is called
** to set the tokenizer to use the specified locale.
**
** If output variable (*pbFreeAndReset) is set to true, then the caller
** is required to (a) call sqlite3Fts5ClearLocale() to reset the tokenizer
** locale, and (b) call sqlite3_free() to free (*pzText).
*/
static int fts5ExtractExprText(
Fts5Config *pConfig, /* Fts5 configuration */
sqlite3_value *pVal, /* Value to extract expression text from */
char **pzText, /* OUT: nul-terminated buffer of text */
int *pbFreeAndReset /* OUT: Free (*pzText) and clear locale */
){
int rc = SQLITE_OK;
if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
const char *pText = 0;
int nText = 0;
const char *pLoc = 0;
int nLoc = 0;
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
*pzText = sqlite3Fts5Mprintf(&rc, "%.*s", nText, pText);
if( rc==SQLITE_OK ){
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
}
*pbFreeAndReset = 1;
}else{
*pzText = (char*)sqlite3_value_text(pVal);
*pbFreeAndReset = 0;
}
return rc;
}
/*
** This is the xFilter interface for the virtual table. See
** the virtual table xFilter method documentation for additional
** information.
**
** There are three possible query strategies:
**
** 1. Full-text search using a MATCH operator.
** 2. A by-rowid lookup.
** 3. A full-table scan.
*/
static int fts5FilterMethod(
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
int idxNum, /* Strategy index */
const char *idxStr, /* Unused */
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK; /* Error code */
int bDesc; /* True if ORDER BY [rank|rowid] DESC */
int bOrderByRank; /* True if ORDER BY rank */
sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
int iCol; /* Column on LHS of MATCH operator */
char **pzErrmsg = pConfig->pzErrmsg;
int bPrefixInsttoken = pConfig->bPrefixInsttoken;
int i;
int iIdxStr = 0;
Fts5Expr *pExpr = 0;
assert( pConfig->bLock==0 );
if( pCsr->ePlan ){
fts5FreeCursorComponents(pCsr);
memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
}
assert( pCsr->pStmt==0 );
assert( pCsr->pExpr==0 );
assert( pCsr->csrflags==0 );
assert( pCsr->pRank==0 );
assert( pCsr->zRank==0 );
assert( pCsr->zRankArgs==0 );
assert( pTab->pSortCsr==0 || nVal==0 );
assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Decode the arguments passed through to this function. */
for(i=0; i<nVal; i++){
switch( idxStr[iIdxStr++] ){
case 'r':
pRank = apVal[i];
break;
case 'M': {
char *zText = 0;
int bFreeAndReset = 0;
int bInternal = 0;
rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
if( rc!=SQLITE_OK ) goto filter_out;
if( zText==0 ) zText = "";
if( sqlite3_value_subtype(apVal[i])==FTS5_INSTTOKEN_SUBTYPE ){
pConfig->bPrefixInsttoken = 1;
}
iCol = 0;
do{
iCol = iCol*10 + (idxStr[iIdxStr]-'0');
iIdxStr++;
}while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
if( zText[0]=='*' ){
/* The user has issued a query of the form "MATCH '*...'". This
** indicates that the MATCH expression is not a full text query,
** but a request for an internal parameter. */
rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
bInternal = 1;
}else{
char **pzErr = &pTab->p.base.zErrMsg;
rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
pExpr = 0;
}
}
if( bFreeAndReset ){
sqlite3_free(zText);
sqlite3Fts5ClearLocale(pConfig);
}
if( bInternal || rc!=SQLITE_OK ) goto filter_out;
break;
}
case 'L':
case 'G': {
int bGlob = (idxStr[iIdxStr-1]=='G');
const char *zText = (const char*)sqlite3_value_text(apVal[i]);
iCol = 0;
do{
iCol = iCol*10 + (idxStr[iIdxStr]-'0');
iIdxStr++;
}while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
if( zText ){
rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
pExpr = 0;
}
if( rc!=SQLITE_OK ) goto filter_out;
break;
}
case '=':
pRowidEq = apVal[i];
break;
case '<':
pRowidLe = apVal[i];
break;
default: assert( idxStr[iIdxStr-1]=='>' );
pRowidGe = apVal[i];
break;
}
}
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
/* Set the cursor upper and lower rowid limits. Only some strategies
** actually use them. This is ok, as the xBestIndex() method leaves the
** sqlite3_index_constraint.omit flag clear for range constraints
** on the rowid field. */
if( pRowidEq ){
pRowidLe = pRowidGe = pRowidEq;
}
if( bDesc ){
pCsr->iFirstRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64);
pCsr->iLastRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
}else{
pCsr->iLastRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64);
pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64);
}
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
if( rc!=SQLITE_OK ) goto filter_out;
if( pTab->pSortCsr ){
/* If pSortCsr is non-NULL, then this call is being made as part of
** processing for a "... MATCH <expr> ORDER BY rank" query (ePlan is
** set to FTS5_PLAN_SORTED_MATCH). pSortCsr is the cursor that will
** return results to the user for this query. The current cursor
** (pCursor) is used to execute the query issued by function
** fts5CursorFirstSorted() above. */
assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 );
assert( nVal==0 && bOrderByRank==0 && bDesc==0 );
assert( pCsr->iLastRowid==LARGEST_INT64 );
assert( pCsr->iFirstRowid==SMALLEST_INT64 );
if( pTab->pSortCsr->bDesc ){
pCsr->iLastRowid = pTab->pSortCsr->iFirstRowid;
pCsr->iFirstRowid = pTab->pSortCsr->iLastRowid;
}else{
pCsr->iLastRowid = pTab->pSortCsr->iLastRowid;
pCsr->iFirstRowid = pTab->pSortCsr->iFirstRowid;
}
pCsr->ePlan = FTS5_PLAN_SOURCE;
pCsr->pExpr = pTab->pSortCsr->pExpr;
rc = fts5CursorFirst(pTab, pCsr, bDesc);
}else if( pCsr->pExpr ){
assert( rc==SQLITE_OK );
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
if( rc==SQLITE_OK ){
if( bOrderByRank ){
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
}else{
pCsr->ePlan = FTS5_PLAN_MATCH;
rc = fts5CursorFirst(pTab, pCsr, bDesc);
}
}
}else if( pConfig->zContent==0 ){
fts5SetVtabError(pTab,"%s: table does not support scanning",pConfig->zName);
rc = SQLITE_ERROR;
}else{
/* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
** by rowid (ePlan==FTS5_PLAN_ROWID). */
pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
rc = sqlite3Fts5StorageStmt(
pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
);
if( rc==SQLITE_OK ){
if( pRowidEq!=0 ){
assert( pCsr->ePlan==FTS5_PLAN_ROWID );
sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
}else{
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
}
rc = fts5NextMethod(pCursor);
}
}
filter_out:
sqlite3Fts5ExprFree(pExpr);
pConfig->pzErrmsg = pzErrmsg;
pConfig->bPrefixInsttoken = bPrefixInsttoken;
return rc;
}
/*
** This is the xEof method of the virtual table. SQLite calls this
** routine to find out if it has reached the end of a result set.
*/
static int fts5EofMethod(sqlite3_vtab_cursor *pCursor){
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
return (CsrFlagTest(pCsr, FTS5CSR_EOF) ? 1 : 0);
}
/*
** Return the rowid that the cursor currently points to.
*/
static i64 fts5CursorRowid(Fts5Cursor *pCsr){
assert( pCsr->ePlan==FTS5_PLAN_MATCH
|| pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
|| pCsr->ePlan==FTS5_PLAN_SOURCE
|| pCsr->ePlan==FTS5_PLAN_SCAN
|| pCsr->ePlan==FTS5_PLAN_ROWID
);
if( pCsr->pSorter ){
return pCsr->pSorter->iRowid;
}else if( pCsr->ePlan>=FTS5_PLAN_SCAN ){
return sqlite3_column_int64(pCsr->pStmt, 0);
}else{
return sqlite3Fts5ExprRowid(pCsr->pExpr);
}
}
/*
** This is the xRowid method. The SQLite core calls this routine to
** retrieve the rowid for the current row of the result set. fts5
** exposes %_content.rowid as the rowid for the virtual table. The
** rowid should be written to *pRowid.
*/
static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int ePlan = pCsr->ePlan;
assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
if( ePlan==FTS5_PLAN_SPECIAL ){
*pRowid = 0;
}else{
*pRowid = fts5CursorRowid(pCsr);
}
return SQLITE_OK;
}
/*
** If the cursor requires seeking (bSeekRequired flag is set), seek it.
** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise.
**
** If argument bErrormsg is true and an error occurs, an error message may
** be left in sqlite3_vtab.zErrMsg.
*/
static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
int rc = SQLITE_OK;
/* If the cursor does not yet have a statement handle, obtain one now. */
if( pCsr->pStmt==0 ){
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int eStmt = fts5StmtType(pCsr);
rc = sqlite3Fts5StorageStmt(
pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->p.base.zErrMsg:0)
);
assert( rc!=SQLITE_OK || pTab->p.base.zErrMsg==0 );
assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
}
if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
assert( pCsr->pExpr );
sqlite3_reset(pCsr->pStmt);
sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr));
pTab->pConfig->bLock++;
rc = sqlite3_step(pCsr->pStmt);
pTab->pConfig->bLock--;
if( rc==SQLITE_ROW ){
rc = SQLITE_OK;
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT);
}else{
rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK ){
rc = FTS5_CORRUPT;
fts5SetVtabError((Fts5FullTable*)pTab,
"fts5: missing row %lld from content table %s",
fts5CursorRowid(pCsr),
pTab->pConfig->zContent
);
}else if( pTab->pConfig->pzErrmsg ){
fts5SetVtabError((Fts5FullTable*)pTab,
"%s", sqlite3_errmsg(pTab->pConfig->db)
);
}
}
}
return rc;
}
/*
** This function is called to handle an FTS INSERT command. In other words,
** an INSERT statement of the form:
**
** INSERT INTO fts(fts) VALUES($pCmd)
** INSERT INTO fts(fts, rank) VALUES($pCmd, $pVal)
**
** Argument pVal is the value assigned to column "fts" by the INSERT
** statement. This function returns SQLITE_OK if successful, or an SQLite
** error code if an error occurs.
**
** The commands implemented by this function are documented in the "Special
** INSERT Directives" section of the documentation. It should be updated if
** more commands are added to this function.
*/
static int fts5SpecialInsert(
Fts5FullTable *pTab, /* Fts5 table object */
const char *zCmd, /* Text inserted into table-name column */
sqlite3_value *pVal /* Value inserted into rank column */
){
}
if( bSeenIndex==0 && bRowidModified==0 ){
*pbContent = 1;
}else{
if( bSeenIndexNC || pConfig->bContentlessDelete==0 ){
rc = SQLITE_ERROR;
sqlite3Fts5ConfigErrmsg(pConfig,
(pConfig->bContentlessDelete ?
"%s a subset of columns on fts5 contentless-delete table: %s" :
"%s contentless fts5 table: %s")
, "cannot UPDATE", pConfig->zName
);
}
}
return rc;
}
/*
** This function is the implementation of the xUpdate callback used by
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
** inserted, updated or deleted.
**
** A delete specifies a single argument - the rowid of the row to remove.
**
** Update and insert operations pass:
**
** 1. The "old" rowid, or NULL.
** 2. The "new" rowid.
** 3. Values for each of the nCol matchable columns.
** 4. Values for the two hidden columns (<tablename> and "rank").
*/
static int fts5UpdateMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
int nArg, /* Size of argument array */
sqlite3_value **apVal, /* Array of arguments */
sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
){
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
Fts5Config *pConfig = pTab->p.pConfig;
int eType0; /* value_type() of apVal[0] */
int rc = SQLITE_OK; /* Return code */
/* A transaction must be open when this is called. */
assert( pTab->ts.eState==1 || pTab->ts.eState==2 );
assert( pVtab->zErrMsg==0 );
assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER
|| sqlite3_value_type(apVal[0])==SQLITE_NULL
);
assert( pTab->p.pConfig->pzErrmsg==0 );
if( pConfig->pgsz==0 ){
rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie);
if( rc!=SQLITE_OK ) return rc;
}
pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Put any active cursors into REQUIRE_SEEK state. */
fts5TripCursors(pTab);
eType0 = sqlite3_value_type(apVal[0]);
if( eType0==SQLITE_NULL
&& sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL
){
/* A "special" INSERT op. These are handled separately. */
const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]);
if( pConfig->eContent!=FTS5_CONTENT_NORMAL
&& 0==sqlite3_stricmp("delete", z)
){
if( pConfig->bContentlessDelete ){
fts5SetVtabError(pTab,
"'delete' may not be used with a contentless_delete=1 table"
);
rc = SQLITE_ERROR;
}else{
rc = fts5SpecialDelete(pTab, apVal);
}
}else{
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
}
}else{
/* A regular INSERT, UPDATE or DELETE statement. The trick here is that
** any conflict on the rowid value must be detected before any
** modifications are made to the database file. There are 4 cases:
**
** 1) DELETE
** 2) UPDATE (rowid not modified)
** 3) UPDATE (rowid modified)
** 4) INSERT
**
** Cases 3 and 4 may violate the rowid constraint.
*/
int eConflict = SQLITE_ABORT;
if( pConfig->eContent==FTS5_CONTENT_NORMAL || pConfig->bContentlessDelete ){
eConflict = sqlite3_vtab_on_conflict(pConfig->db);
}
assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
assert( nArg!=1 || eType0==SQLITE_INTEGER );
/* DELETE */
if( nArg==1 ){
/* It is only possible to DELETE from a contentless table if the
** contentless_delete=1 flag is set. */
if( fts5IsContentless(pTab, 1) && pConfig->bContentlessDelete==0 ){
fts5SetVtabError(pTab,
"cannot DELETE from contentless fts5 table: %s", pConfig->zName
);
rc = SQLITE_ERROR;
}else{
i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);
}
}
/* INSERT or UPDATE */
else{
int eType1 = sqlite3_value_numeric_type(apVal[1]);
int iCol,
const char **ppText,
int *pnText
){
sqlite3_value *pVal = sqlite3_column_value(pStmt, iCol+1);
const char *pLoc = 0;
int nLoc = 0;
int rc = SQLITE_OK;
if( pConfig->bLocale
&& pConfig->eContent==FTS5_CONTENT_EXTERNAL
&& sqlite3Fts5IsLocaleValue(pConfig, pVal)
){
rc = sqlite3Fts5DecodeLocaleValue(pVal, ppText, pnText, &pLoc, &nLoc);
}else{
*ppText = (const char*)sqlite3_value_text(pVal);
*pnText = sqlite3_value_bytes(pVal);
if( pConfig->bLocale && pConfig->eContent==FTS5_CONTENT_NORMAL ){
pLoc = (const char*)sqlite3_column_text(pStmt, iCol+1+pConfig->nCol);
nLoc = sqlite3_column_bytes(pStmt, iCol+1+pConfig->nCol);
}
}
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
return rc;
}
static int fts5ApiColumnText(
Fts5Context *pCtx,
int iCol,
const char **pz,
int *pn
){
int rc = SQLITE_OK;
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
if( iCol<0 || iCol>=pTab->pConfig->nCol ){
rc = SQLITE_RANGE;
}else if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab), 0) ){
*pz = 0;
*pn = 0;
}else{
rc = fts5SeekCursor(pCsr, 0);
if( rc==SQLITE_OK ){
rc = fts5TextFromStmt(pTab->pConfig, pCsr->pStmt, iCol, pz, pn);
sqlite3Fts5ClearLocale(pTab->pConfig);
}
}
return rc;
}
/*
** This is called by various API functions - xInst, xPhraseFirst,
** xPhraseFirstColumn etc. - to obtain the position list for phrase iPhrase
** of the current row. This function works for both detail=full tables (in
** which case the position-list was read from the fts index) or for other
** detail= modes if the row content is available.
*/
static int fts5CsrPoslist(
Fts5Cursor *pCsr, /* Fts5 cursor object */
int iPhrase, /* Phrase to find position list for */
const u8 **pa, /* OUT: Pointer to position list buffer */
int *pn /* OUT: Size of (*pa) in bytes */
){
Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
int rc = SQLITE_OK;
int bLive = (pCsr->pSorter==0);
if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){
rc = SQLITE_RANGE;
}else if( pConfig->eDetail!=FTS5_DETAIL_FULL
&& fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1)
){
*pa = 0;
*pn = 0;
return SQLITE_OK;
}else if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
Fts5PoslistPopulator *aPopulator;
int i;
aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
if( aPopulator==0 ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK ){
rc = fts5SeekCursor(pCsr, 0);
}
for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
const char *z = 0;
int n = 0;
rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprPopulatePoslists(
pConfig, pCsr->pExpr, aPopulator, i, z, n
);
}
sqlite3Fts5ClearLocale(pConfig);
}
sqlite3_free(aPopulator);
if( pCsr->pSorter ){
sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
}
}
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
}
if( rc==SQLITE_OK ){
if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
Fts5Sorter *pSorter = pCsr->pSorter;
int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
*pn = pSorter->aIdx[iPhrase] - i1;
*pa = &pSorter->aPoslist[i1];
}else{
*pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
}
}else{
*pa = 0;
*pn = 0;
}
Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
if( pConfig->bColumnsize ){
i64 iRowid = fts5CursorRowid(pCsr);
rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
}else if( !pConfig->zContent || pConfig->eContent==FTS5_CONTENT_UNINDEXED ){
int i;
for(i=0; i<pConfig->nCol; i++){
if( pConfig->abUnindexed[i]==0 ){
pCsr->aColumnSize[i] = -1;
}
}
}else{
int i;
rc = fts5SeekCursor(pCsr, 0);
for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
if( pConfig->abUnindexed[i]==0 ){
const char *z = 0;
int n = 0;
pCsr->aColumnSize[i] = 0;
rc = fts5TextFromStmt(pConfig, pCsr->pStmt, i, &z, &n);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_AUX,
z, n, (void*)&pCsr->aColumnSize[i], fts5ColumnSizeCb
);
}
sqlite3Fts5ClearLocale(pConfig);
}
}
}
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
}
if( iCol<0 ){
int i;
*pnToken = 0;
for(i=0; i<pConfig->nCol; i++){
*pnToken += pCsr->aColumnSize[i];
}
}else if( iCol<pConfig->nCol ){
*pnToken = pCsr->aColumnSize[iCol];
}else{
*pnToken = 0;
rc = SQLITE_RANGE;
}
return rc;
}
/*
** Implementation of the xSetAuxdata() method.
*/
static int fts5ApiSetAuxdata(
Fts5Context *pCtx, /* Fts5 context */
void *pPtr, /* Pointer to save as auxdata */
void(*xDelete)(void*) /* Destructor for pPtr (or NULL) */
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Auxdata *pData;
/* Search through the cursors list of Fts5Auxdata objects for one that
** corresponds to the currently executing auxiliary function. */
for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){
if( pData->pAux==pCsr->pAux ) break;
}
if( pData ){
if( pData->xDelete ){
pData->xDelete(pData->pPtr);
}
}else{
int rc = SQLITE_OK;
pData = (Fts5Auxdata*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Auxdata));
if( pData==0 ){
if( xDelete ) xDelete(pPtr);
return rc;
}
pData->pAux = pCsr->pAux;
pData->pNext = pCsr->pAuxdata;
pCsr->pAuxdata = pData;
}
pData->xDelete = xDelete;
pData->pPtr = pPtr;
return SQLITE_OK;
}
static void *fts5ApiGetAuxdata(Fts5Context *pCtx, int bClear){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Auxdata *pData;
void *pRet = 0;
for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){
if( pData->pAux==pCsr->pAux ) break;
}
if( pData ){
pRet = pData->pPtr;
if( bClear ){
pData->pPtr = 0;
pData->xDelete = 0;
}
}
return pRet;
}
static void fts5ApiPhraseNext(
Fts5Context *pCtx,
Fts5PhraseIter *pIter,
int *piCol, int *piOff
){
if( pIter->a>=pIter->b ){
*piCol = -1;
*piOff = -1;
}else{
int iVal;
pIter->a += fts5GetVarint32(pIter->a, iVal);
if( iVal==1 ){
/* Avoid returning a (*piCol) value that is too large for the table,
** even if the position-list is corrupt. The caller might not be
&& 0==fts5IsContentless((Fts5FullTable*)pCsr->base.pVtab, 1)
&& pConfig->bLocale
){
rc = fts5SeekCursor(pCsr, 0);
if( rc==SQLITE_OK ){
const char *zDummy = 0;
int nDummy = 0;
rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &zDummy, &nDummy);
if( rc==SQLITE_OK ){
*pzLocale = pConfig->t.pLocale;
*pnLocale = pConfig->t.nLocale;
}
sqlite3Fts5ClearLocale(pConfig);
}
}
return rc;
}
static const Fts5ExtensionApi sFts5Api = {
4, /* iVersion */
fts5ApiUserData,
fts5ApiColumnCount,
fts5ApiRowCount,
fts5ApiColumnTotalSize,
fts5ApiTokenize,
fts5ApiPhraseCount,
fts5ApiPhraseSize,
fts5ApiInstCount,
fts5ApiInst,
fts5ApiRowid,
fts5ApiColumnText,
fts5ApiColumnSize,
fts5ApiQueryPhrase,
fts5ApiSetAuxdata,
fts5ApiGetAuxdata,
fts5ApiPhraseFirst,
fts5ApiPhraseNext,
fts5ApiPhraseFirstColumn,
fts5ApiPhraseNextColumn,
fts5ApiQueryToken,
fts5ApiInstToken,
fts5ApiColumnLocale,
fts5ApiTokenize_v2
};
/*
** Implementation of API function xQueryPhrase().
*/
static int fts5ApiQueryPhrase(
Fts5Context *pCtx,
int iPhrase,
void *pUserData,
int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int rc;
Fts5Cursor *pNew = 0;
rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew);
if( rc==SQLITE_OK ){
pNew->ePlan = FTS5_PLAN_MATCH;
pNew->iFirstRowid = SMALLEST_INT64;
pNew->iLastRowid = LARGEST_INT64;
pNew->base.pVtab = (sqlite3_vtab*)pTab;
rc = sqlite3Fts5ExprClonePhrase(pCsr->pExpr, iPhrase, &pNew->pExpr);
}
if( rc==SQLITE_OK ){
for(rc = fts5CursorFirst(pTab, pNew, 0);
rc==SQLITE_OK && CsrFlagTest(pNew, FTS5CSR_EOF)==0;
rc = fts5NextMethod((sqlite3_vtab_cursor*)pNew)
){
rc = xCallback(&sFts5Api, (Fts5Context*)pNew, pUserData);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
break;
}
}
}
fts5CloseMethod((sqlite3_vtab_cursor*)pNew);
return rc;
}
static void fts5ApiInvoke(
Fts5Auxiliary *pAux,
Fts5Cursor *pCsr,
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( pCsr->pAux==0 );
assert( pCsr->ePlan!=FTS5_PLAN_SPECIAL );
pCsr->pAux = pAux;
pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
pCsr->pAux = 0;
}
static Fts5Cursor *fts5CursorFromCsrid(Fts5Global *pGlobal, i64 iCsrId){
Fts5Cursor *pCsr;
for(pCsr=pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->iCsrId==iCsrId ) break;
}
return pCsr;
}
/*
** Parameter zFmt is a printf() style formatting string. This function
** formats it using the trailing arguments and returns the result as
** an error message to the context passed as the first argument.
*/
static void fts5ResultError(sqlite3_context *pCtx, const char *zFmt, ...){
char *zErr = 0;
va_list ap;
va_start(ap, zFmt);
zErr = sqlite3_vmprintf(zFmt, ap);
sqlite3_result_error(pCtx, zErr, -1);
sqlite3_free(zErr);
va_end(ap);
}
static void fts5ApiCallback(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Fts5Auxiliary *pAux;
Fts5Cursor *pCsr;
i64 iCsrId;
assert( argc>=1 );
pAux = (Fts5Auxiliary*)sqlite3_user_data(context);
iCsrId = sqlite3_value_int64(argv[0]);
pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
if( pCsr==0 || (pCsr->ePlan==0 || pCsr->ePlan==FTS5_PLAN_SPECIAL) ){
fts5ResultError(context, "no such cursor: %lld", iCsrId);
}else{
sqlite3_vtab *pTab = pCsr->base.pVtab;
fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
sqlite3_free(pTab->zErrMsg);
pTab->zErrMsg = 0;
}
}
/*
** Given cursor id iId, return a pointer to the corresponding Fts5Table
** object. Or NULL If the cursor id does not exist.
*/
static Fts5Table *sqlite3Fts5TableFromCsrid(
Fts5Global *pGlobal, /* FTS5 global context for db handle */
i64 iCsrId /* Id of cursor to find */
){
Fts5Cursor *pCsr;
pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
if( pCsr ){
return (Fts5Table*)pCsr->base.pVtab;
}
return 0;
}
/*
** Return a "position-list blob" corresponding to the current position of
** cursor pCsr via sqlite3_result_blob(). A position-list blob contains
** the current position-list for each phrase in the query associated with
** cursor pCsr.
**
** A position-list blob begins with (nPhrase-1) varints, where nPhrase is
** the number of phrases in the query. Following the varints are the
** concatenated position lists for each phrase, in order.
**
** The first varint (if it exists) contains the size of the position list
** for phrase 0. The second (same disclaimer) contains the size of position
** list 1. And so on. There is no size field for the final position list,
** as it can be derived from the total size of the blob.
*/
static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){
int i;
int rc = SQLITE_OK;
int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
Fts5Buffer val;
memset(&val, 0, sizeof(Fts5Buffer));
switch( ((Fts5Table*)(pCsr->base.pVtab))->pConfig->eDetail ){
case FTS5_DETAIL_FULL:
/* Append the varints */
for(i=0; i<(nPhrase-1); i++){
const u8 *dummy;
int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
}
/* Append the position lists */
for(i=0; i<nPhrase; i++){
const u8 *pPoslist;
int nPoslist;
nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
}
break;
case FTS5_DETAIL_COLUMNS:
/* Append the varints */
for(i=0; rc==SQLITE_OK && i<(nPhrase-1); i++){
const u8 *dummy;
int nByte;
rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &dummy, &nByte);
sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
}
/* Append the position lists */
for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
const u8 *pPoslist;
int nPoslist;
rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &pPoslist, &nPoslist);
sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
}
break;
default:
break;
}
sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
return rc;
}
/*
** This is the xColumn method, called by SQLite to request a value from
** the row that the supplied cursor currently points to.
*/
static int fts5ColumnMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK;
assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
if( pCsr->ePlan==FTS5_PLAN_SPECIAL ){
if( iCol==pConfig->nCol ){
sqlite3_result_int64(pCtx, pCsr->iSpecial);
}
}else
if( iCol==pConfig->nCol ){
/* User is requesting the value of the special column with the same name
** as the table. Return the cursor integer id number. This value is only
** useful in that it may be passed as the first argument to an FTS5
** auxiliary function. */
sqlite3_result_int64(pCtx, pCsr->iCsrId);
}else if( iCol==pConfig->nCol+1 ){
/* The value of the "rank" column. */
if( pCsr->ePlan==FTS5_PLAN_SOURCE ){
fts5PoslistBlob(pCtx, pCsr);
}else if(
pCsr->ePlan==FTS5_PLAN_MATCH
|| pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
){
if( pCsr->pRank || SQLITE_OK==(rc = fts5FindRankFunction(pCsr)) ){
fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg);
}
}
}else{
if( !sqlite3_vtab_nochange(pCtx) && pConfig->eContent!=FTS5_CONTENT_NONE ){
pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
rc = fts5SeekCursor(pCsr, 1);
if( rc==SQLITE_OK ){
sqlite3_value *pVal = sqlite3_column_value(pCsr->pStmt, iCol+1);
if( pConfig->bLocale
&& pConfig->eContent==FTS5_CONTENT_EXTERNAL
&& sqlite3Fts5IsLocaleValue(pConfig, pVal)
){
const char *z = 0;
int n = 0;
rc = fts5TextFromStmt(pConfig, pCsr->pStmt, iCol, &z, &n);
if( rc==SQLITE_OK ){
sqlite3_result_text(pCtx, z, n, SQLITE_TRANSIENT);
}
sqlite3Fts5ClearLocale(pConfig);
}else{
sqlite3_result_value(pCtx, pVal);
}
}
pConfig->pzErrmsg = 0;
}
}
return rc;
}
/*
** This routine implements the xFindFunction method for the FTS3
** virtual table.
*/
static int fts5FindFunctionMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
int nUnused, /* Number of SQL function arguments */
const char *zName, /* Name of SQL function */
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
void **ppArg /* OUT: User data for *pxFunc */
){
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
Fts5Auxiliary *pAux;
if( iVal<(1 << 28) ) return 4;
return 5;
}
/*
** 2015 May 08
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This is an SQLite virtual table module implementing direct access to an
** existing FTS5 index. The module may create several different types of
** tables:
**
** col:
** CREATE TABLE vocab(term, col, doc, cnt, PRIMARY KEY(term, col));
**
** One row for each term/column combination. The value of $doc is set to
** the number of fts5 rows that contain at least one instance of term
** $term within column $col. Field $cnt is set to the total number of
** instances of term $term in column $col (in any row of the fts5 table).
**
** row:
** CREATE TABLE vocab(term, doc, cnt, PRIMARY KEY(term));
**
** One row for each term in the database. The value of $doc is set to
** the number of fts5 rows that contain at least one instance of term
** $term. Field $cnt is set to the total number of instances of term
** $term in the database.
**
** instance:
** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY(<all-fields>));
**
** One row for each term instance in the database.
*/
/* #include "fts5Int.h" */
typedef struct Fts5VocabTable Fts5VocabTable;
typedef struct Fts5VocabCursor Fts5VocabCursor;
struct Fts5VocabTable {
sqlite3_vtab base;
char *zFts5Tbl; /* Name of fts5 table */
char *zFts5Db; /* Db containing fts5 table */
sqlite3 *db; /* Database handle */
Fts5Global *pGlobal; /* FTS5 global object for this database */
int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
unsigned bBusy; /* True if busy */
};
struct Fts5VocabCursor {
sqlite3_vtab_cursor base;
sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
Fts5Table *pFts5; /* Associated FTS5 table */
int bEof; /* True if this cursor is at EOF */
Fts5IndexIter *pIter; /* Term/rowid iterator object */
void *pStruct; /* From sqlite3Fts5StructureRef() */
int nLeTerm; /* Size of zLeTerm in bytes */
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
int colUsed; /* Copy of sqlite3_index_info.colUsed */
/* These are used by 'col' tables only */
int iCol;
i64 *aCnt;
i64 *aDoc;
/* Output values used by all tables. */
i64 rowid; /* This table's current rowid value */
Fts5Buffer term; /* Current value of 'term' column */
/* Output values Used by 'instance' tables only */
i64 iInstPos;
int iInstOff;
};
#define FTS5_VOCAB_COL 0
#define FTS5_VOCAB_ROW 1
#define FTS5_VOCAB_INSTANCE 2
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
/*
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
*/
#define FTS5_VOCAB_TERM_EQ 0x0100
#define FTS5_VOCAB_TERM_GE 0x0200
#define FTS5_VOCAB_TERM_LE 0x0400
#define FTS5_VOCAB_COLUSED_MASK 0xFF
/*
** Translate a string containing an fts5vocab table type to an
** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
** value and return SQLITE_OK. Otherwise, set *pzErr to an error message
** and return SQLITE_ERROR.
*/
static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){
int rc = SQLITE_OK;
char *zCopy = sqlite3Fts5Strndup(&rc, zType, -1);
if( rc==SQLITE_OK ){
sqlite3Fts5Dequote(zCopy);
if( sqlite3_stricmp(zCopy, "col")==0 ){
*peType = FTS5_VOCAB_COL;
}else
if( sqlite3_stricmp(zCopy, "row")==0 ){
*peType = FTS5_VOCAB_ROW;
}else
if( sqlite3_stricmp(zCopy, "instance")==0 ){
*peType = FTS5_VOCAB_INSTANCE;
}else
int iTermGe = -1;
int iTermLe = -1;
int idxNum = (int)pInfo->colUsed;
int nArg = 0;
UNUSED_PARAM(pUnused);
assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed );
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
if( p->usable==0 ) continue;
if( p->iColumn==0 ){ /* term column */
if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i;
if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i;
if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i;
if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i;
if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i;
}
}
if( iTermEq>=0 ){
idxNum |= FTS5_VOCAB_TERM_EQ;
pInfo->aConstraintUsage[iTermEq].argvIndex = ++nArg;
pInfo->estimatedCost = 100;
}else{
pInfo->estimatedCost = 1000000;
if( iTermGe>=0 ){
idxNum |= FTS5_VOCAB_TERM_GE;
pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg;
pInfo->estimatedCost = pInfo->estimatedCost / 2;
}
if( iTermLe>=0 ){
idxNum |= FTS5_VOCAB_TERM_LE;
pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg;
pInfo->estimatedCost = pInfo->estimatedCost / 2;
}
}
/* This virtual table always delivers results in ascending order of
** the "term" column (column 0). So if the user has requested this
** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the
** sqlite3_index_info.orderByConsumed flag to tell the core the results
** are already in sorted order. */
if( pInfo->nOrderBy==1
&& pInfo->aOrderBy[0].iColumn==0
&& pInfo->aOrderBy[0].desc==0
){
pInfo->orderByConsumed = 1;
}
pInfo->idxNum = idxNum;
return SQLITE_OK;
}
/*
** Implementation of xOpen method.
*/
static int fts5VocabOpenMethod(
sqlite3_vtab *pVTab,
sqlite3_vtab_cursor **ppCsr
){
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
Fts5Table *pFts5 = 0;
Fts5VocabCursor *pCsr = 0;
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
char *zSql = 0;
if( pTab->bBusy ){
pVTab->zErrMsg = sqlite3_mprintf(
"recursive definition for %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
);
return SQLITE_ERROR;
}
zSql = sqlite3Fts5Mprintf(&rc,
"SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
pTab->zFts5Tbl, pTab->zFts5Db, pTab->zFts5Tbl, pTab->zFts5Tbl
);
if( zSql ){
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
}
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pStmt==0 );
if( rc==SQLITE_ERROR ) rc = SQLITE_OK;
pTab->bBusy = 1;
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
i64 iId = sqlite3_column_int64(pStmt, 0);
pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId);
}
pTab->bBusy = 0;
if( rc==SQLITE_OK ){
if( pFts5==0 ){
rc = sqlite3_finalize(pStmt);
pStmt = 0;
if( rc==SQLITE_OK ){
pVTab->zErrMsg = sqlite3_mprintf(
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
);
rc = SQLITE_ERROR;
}
}else{
rc = sqlite3Fts5FlushToDisk(pFts5);
}
}
if( rc==SQLITE_OK ){
i64 nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
}
if( pCsr ){
pCsr->pFts5 = pFts5;
pCsr->pStmt = pStmt;
pCsr->aCnt = (i64*)&pCsr[1];
pCsr->aDoc = &pCsr->aCnt[pFts5->pConfig->nCol];
}else{
sqlite3_finalize(pStmt);
}
*ppCsr = (sqlite3_vtab_cursor*)pCsr;
return rc;
}
/*
** Restore cursor pCsr to the state it was in immediately after being
** created by the xOpen() method.
*/
static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
int nCol = pCsr->pFts5->pConfig->nCol;
pCsr->rowid = 0;
sqlite3Fts5IterClose(pCsr->pIter);
sqlite3Fts5StructureRelease(pCsr->pStruct);
pCsr->pStruct = 0;
pCsr->pIter = 0;
sqlite3_free(pCsr->zLeTerm);
pCsr->nLeTerm = -1;
pCsr->zLeTerm = 0;
pCsr->bEof = 0;
pCsr->iCol = 0;
pCsr->iInstPos = 0;
pCsr->iInstOff = 0;
pCsr->colUsed = 0;
memset(pCsr->aCnt, 0, sizeof(i64)*nCol);
memset(pCsr->aDoc, 0, sizeof(i64)*nCol);
}
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
fts5VocabResetCursor(pCsr);
sqlite3Fts5BufferFree(&pCsr->term);
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr);
return SQLITE_OK;
}
static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
int rc = SQLITE_OK;
if( sqlite3Fts5IterEof(pCsr->pIter) ){
pCsr->bEof = 1;
}else{
const char *zTerm;
int nTerm;
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
if( pCsr->nLeTerm>=0 ){
int nCmp = MIN(nTerm, pCsr->nLeTerm);
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
pCsr->bEof = 1;
}
}
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
}
return rc;
}
static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
int eDetail = pCsr->pFts5->pConfig->eDetail;
int rc = SQLITE_OK;
Fts5IndexIter *pIter = pCsr->pIter;
i64 *pp = &pCsr->iInstPos;
int *po = &pCsr->iInstOff;
assert( sqlite3Fts5IterEof(pIter)==0 );
assert( pCsr->bEof==0 );
while( eDetail==FTS5_DETAIL_NONE
|| sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
){
pCsr->iInstPos = 0;
pCsr->iInstOff = 0;
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
if( rc==SQLITE_OK ){
rc = fts5VocabInstanceNewTerm(pCsr);
if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break;
}
if( rc ){
pCsr->bEof = 1;
break;
}
}
return rc;
}
/*
** Advance the cursor to the next row in the table.
*/
static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
int nCol = pCsr->pFts5->pConfig->nCol;
int rc;
rc = sqlite3Fts5StructureTest(pCsr->pFts5->pIndex, pCsr->pStruct);
if( rc!=SQLITE_OK ) return rc;
pCsr->rowid++;
if( pTab->eType==FTS5_VOCAB_INSTANCE ){
return fts5VocabInstanceNext(pCsr);
}
if( pTab->eType==FTS5_VOCAB_COL ){
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
if( pCsr->aDoc[pCsr->iCol] ) break;
}
}
if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){
if( sqlite3Fts5IterEof(pCsr->pIter) ){
pCsr->bEof = 1;
}else{
const char *zTerm;
int nTerm;
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
assert( nTerm>=0 );
if( pCsr->nLeTerm>=0 ){
int nCmp = MIN(nTerm, pCsr->nLeTerm);
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
pCsr->bEof = 1;
return SQLITE_OK;
}
}
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
memset(pCsr->aCnt, 0, nCol * sizeof(i64));
memset(pCsr->aDoc, 0, nCol * sizeof(i64));
pCsr->iCol = 0;
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
while( rc==SQLITE_OK ){
int eDetail = pCsr->pFts5->pConfig->eDetail;
const u8 *pPos; int nPos; /* Position list */
i64 iPos = 0; /* 64-bit position read from poslist */
int iOff = 0; /* Current offset within position list */
pPos = pCsr->pIter->pData;
nPos = pCsr->pIter->nData;
switch( pTab->eType ){
case FTS5_VOCAB_ROW:
/* Do not bother counting the number of instances if the "cnt"
** column is not being read (according to colUsed). */
if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){
while( iPos<nPos ){
u32 ii;
fts5FastGetVarint32(pPos, iPos, ii);
if( ii>=nCol ){
rc = FTS5_CORRUPT;
break;
}
pCsr->aDoc[ii]++;
iCol = ii;
}
pCsr->aCnt[ii]++;
}
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
assert_nc( iPos>=0 && iPos<nCol );
if( iPos>=nCol ){
rc = FTS5_CORRUPT;
break;
}
pCsr->aDoc[iPos]++;
}
}else{
assert( eDetail==FTS5_DETAIL_NONE );
pCsr->aDoc[0]++;
}
break;
default:
assert( pTab->eType==FTS5_VOCAB_INSTANCE );
break;
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
}
if( pTab->eType==FTS5_VOCAB_INSTANCE ) break;
if( rc==SQLITE_OK ){
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
if( nTerm!=pCsr->term.n
|| (nTerm>0 && memcmp(zTerm, pCsr->term.p, nTerm))
){
break;
}
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
}
}
}
}
if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
for(/* noop */; pCsr->iCol<nCol && pCsr->aDoc[pCsr->iCol]==0; pCsr->iCol++);
if( pCsr->iCol==nCol ){
rc = FTS5_CORRUPT;
}
}
return rc;
}
/*
** This is the xFilter implementation for the virtual table.
*/
static int fts5VocabFilterMethod(
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
int idxNum, /* Strategy index */
const char *zUnused, /* Unused */
int nUnused, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
int eType = pTab->eType;
int rc = SQLITE_OK;
int iVal = 0;
int f = FTS5INDEX_QUERY_SCAN;
const char *zTerm = 0;
int nTerm = 0;
sqlite3_value *pEq = 0;
sqlite3_value *pGe = 0;
sqlite3_value *pLe = 0;
UNUSED_PARAM2(zUnused, nUnused);
fts5VocabResetCursor(pCsr);
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK);
if( pEq ){
zTerm = (const char *)sqlite3_value_text(pEq);
nTerm = sqlite3_value_bytes(pEq);
f = FTS5INDEX_QUERY_NOTOKENDATA;
}else{
if( pGe ){
zTerm = (const char *)sqlite3_value_text(pGe);
nTerm = sqlite3_value_bytes(pGe);
}
if( pLe ){
const char *zCopy = (const char *)sqlite3_value_text(pLe);
if( zCopy==0 ) zCopy = "";
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
if( pCsr->zLeTerm==0 ){
rc = SQLITE_NOMEM;
}else{
memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1);
}
}
}
if( rc==SQLITE_OK ){
Fts5Index *pIndex = pCsr->pFts5->pIndex;
rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
if( rc==SQLITE_OK ){
pCsr->pStruct = sqlite3Fts5StructureRef(pIndex);
}
}
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
rc = fts5VocabInstanceNewTerm(pCsr);
}
if( rc==SQLITE_OK && !pCsr->bEof
&& (eType!=FTS5_VOCAB_INSTANCE
|| pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE)
){
rc = fts5VocabNextMethod(pCursor);
}
return rc;
}
/*
** This is the xEof method of the virtual table. SQLite calls this
** routine to find out if it has reached the end of a result set.
*/
static int fts5VocabEofMethod(sqlite3_vtab_cursor *pCursor){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
return pCsr->bEof;
}
static int fts5VocabColumnMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
int eDetail = pCsr->pFts5->pConfig->eDetail;
int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
i64 iVal = 0;
if( iCol==0 ){
sqlite3_result_text(
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
);
}else if( eType==FTS5_VOCAB_COL ){
assert( iCol==1 || iCol==2 || iCol==3 );
if( iCol==1 ){
if( eDetail!=FTS5_DETAIL_NONE ){
const char *z = pCsr->pFts5->pConfig->azCol[pCsr->iCol];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
}else if( iCol==2 ){
iVal = pCsr->aDoc[pCsr->iCol];
}else{
iVal = pCsr->aCnt[pCsr->iCol];
}
}else if( eType==FTS5_VOCAB_ROW ){
assert( iCol==1 || iCol==2 );
if( iCol==1 ){
iVal = pCsr->aDoc[0];
}else{
iVal = pCsr->aCnt[0];
}
}else{
assert( eType==FTS5_VOCAB_INSTANCE );
switch( iCol ){
case 1:
sqlite3_result_int64(pCtx, pCsr->pIter->iRowid);
break;
case 2: {
int ii = -1;
if( eDetail==FTS5_DETAIL_FULL ){
ii = FTS5_POS2COLUMN(pCsr->iInstPos);
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
ii = (int)pCsr->iInstPos;
}
if( ii>=0 && ii<pCsr->pFts5->pConfig->nCol ){
const char *z = pCsr->pFts5->pConfig->azCol[ii];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
break;
}
default: {
assert( iCol==3 );
if( eDetail==FTS5_DETAIL_FULL ){
int ii = FTS5_POS2OFFSET(pCsr->iInstPos);
sqlite3_result_int(pCtx, ii);
}
break;
}
}
}
if( iVal>0 ) sqlite3_result_int64(pCtx, iVal);
return SQLITE_OK;
}
/*
** This is the xRowid method. The SQLite core calls this routine to
** retrieve the rowid for the current row of the result set. The
** rowid should be written to *pRowid.
*/
static int fts5VocabRowidMethod(
sqlite3_vtab_cursor *pCursor,
sqlite_int64 *pRowid
){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
*pRowid = pCsr->rowid;
return SQLITE_OK;
}
static int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
static const sqlite3_module fts5Vocab = {
/* iVersion */ 2,
/* xCreate */ fts5VocabCreateMethod,
/* xConnect */ fts5VocabConnectMethod,
/* xBestIndex */ fts5VocabBestIndexMethod,
/* xDisconnect */ fts5VocabDisconnectMethod,
/* xDestroy */ fts5VocabDestroyMethod,
/* xOpen */ fts5VocabOpenMethod,
/* xClose */ fts5VocabCloseMethod,
/* xFilter */ fts5VocabFilterMethod,
/* xNext */ fts5VocabNextMethod,
/* xEof */ fts5VocabEofMethod,
/* xColumn */ fts5VocabColumnMethod,
/* xRowid */ fts5VocabRowidMethod,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindFunction */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0,
/* xIntegrity */ 0
};
void *p = (void*)pGlobal;
return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0);
}
/* Here ends the fts5.c composite file. */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
/************** End of fts5.c ************************************************/
/************** Begin file stmt.c ********************************************/
/*
** 2017-05-31
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file demonstrates an eponymous virtual table that returns information
** about all prepared statements for the database connection.
**
** Usage example:
**
** .load ./stmt
** .mode line
** .header on
** SELECT * FROM stmt;
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB)
#if !defined(SQLITEINT_H)
/* #include "sqlite3ext.h" */
#endif
SQLITE_EXTENSION_INIT1
/* #include <assert.h> */
/* #include <string.h> */
#ifndef SQLITE_OMIT_VIRTUALTABLE
#define STMT_NUM_INTEGER_COLUMN 10
typedef struct StmtRow StmtRow;
struct StmtRow {
sqlite3_int64 iRowid; /* Rowid value */
char *zSql; /* column "sql" */
int aCol[STMT_NUM_INTEGER_COLUMN+1]; /* all other column values */
StmtRow *pNext; /* Next row to return */
};
/* stmt_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a stmt virtual table
*/
typedef struct stmt_vtab stmt_vtab;
struct stmt_vtab {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this stmt vtab */
};
/* stmt_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/
typedef struct stmt_cursor stmt_cursor;
struct stmt_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this cursor */
StmtRow *pRow; /* Current row */
};
/*
** The stmtConnect() method is invoked to create a new
** stmt_vtab that describes the stmt virtual table.
**
** Think of this routine as the constructor for stmt_vtab objects.
**
** All this routine needs to do is:
**
** (1) Allocate the stmt_vtab object and initialize all fields.
**
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
** result set of queries against stmt will look like.
*/
static int stmtConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
stmt_vtab *pNew;
int rc;
/* Column numbers */
#define STMT_COLUMN_SQL 0 /* SQL for the statement */
#define STMT_COLUMN_NCOL 1 /* Number of result columns */
#define STMT_COLUMN_RO 2 /* True if read-only */
#define STMT_COLUMN_BUSY 3 /* True if currently busy */
#define STMT_COLUMN_NSCAN 4 /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
#define STMT_COLUMN_NSORT 5 /* SQLITE_STMTSTATUS_SORT */
#define STMT_COLUMN_NAIDX 6 /* SQLITE_STMTSTATUS_AUTOINDEX */
#define STMT_COLUMN_NSTEP 7 /* SQLITE_STMTSTATUS_VM_STEP */
#define STMT_COLUMN_REPREP 8 /* SQLITE_STMTSTATUS_REPREPARE */
#define STMT_COLUMN_RUN 9 /* SQLITE_STMTSTATUS_RUN */
#define STMT_COLUMN_MEM 10 /* SQLITE_STMTSTATUS_MEMUSED */
(void)pAux;
(void)argc;
(void)argv;
(void)pzErr;
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
"reprep,run,mem)");
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc64( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
pNew->db = db;
}
return rc;
}
/*
** This method is the destructor for stmt_cursor objects.
*/
static int stmtDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** Constructor for a new stmt_cursor object.
*/
static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
stmt_cursor *pCur;
pCur = sqlite3_malloc64( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = ((stmt_vtab*)p)->db;
*ppCursor = &pCur->base;
return SQLITE_OK;
}
static void stmtCsrReset(stmt_cursor *pCur){
StmtRow *pRow = 0;
StmtRow *pNext = 0;
for(pRow=pCur->pRow; pRow; pRow=pNext){
pNext = pRow->pNext;
sqlite3_free(pRow);
}
pCur->pRow = 0;
}
/*
** Destructor for a stmt_cursor.
*/
static int stmtClose(sqlite3_vtab_cursor *cur){
stmtCsrReset((stmt_cursor*)cur);
sqlite3_free(cur);
return SQLITE_OK;
}
/*
** Advance a stmt_cursor to its next row of output.
*/
static int stmtNext(sqlite3_vtab_cursor *cur){
stmt_cursor *pCur = (stmt_cursor*)cur;
StmtRow *pNext = pCur->pRow->pNext;
sqlite3_free(pCur->pRow);
pCur->pRow = pNext;
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the stmt_cursor
** is currently pointing.
*/
static int stmtColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
stmt_cursor *pCur = (stmt_cursor*)cur;
StmtRow *pRow = pCur->pRow;
if( i==STMT_COLUMN_SQL ){
sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT);
}else{
sqlite3_result_int(ctx, pRow->aCol[i]);
}
return SQLITE_OK;
}
/*
** Return the rowid for the current row. In this implementation, the
** rowid is the same as the output value.
*/
static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
stmt_cursor *pCur = (stmt_cursor*)cur;
*pRowid = pCur->pRow->iRowid;
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int stmtEof(sqlite3_vtab_cursor *cur){
stmt_cursor *pCur = (stmt_cursor*)cur;
return pCur->pRow==0;
}
/*
** This method is called to "rewind" the stmt_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to stmtColumn() or stmtRowid() or
** stmtEof().
*/
static int stmtFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
stmt_cursor *pCur = (stmt_cursor *)pVtabCursor;
sqlite3_stmt *p = 0;
sqlite3_int64 iRowid = 1;
StmtRow **ppRow = 0;
(void)idxNum;
(void)idxStr;
(void)argc;
(void)argv;
stmtCsrReset(pCur);
ppRow = &pCur->pRow;
for(p=sqlite3_next_stmt(pCur->db, 0); p; p=sqlite3_next_stmt(pCur->db, p)){
const char *zSql = sqlite3_sql(p);
sqlite3_int64 nSql = zSql ? strlen(zSql)+1 : 0;
StmtRow *pNew = (StmtRow*)sqlite3_malloc64(sizeof(StmtRow) + nSql);
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(StmtRow));
if( zSql ){
pNew->zSql = (char*)&pNew[1];
memcpy(pNew->zSql, zSql, nSql);
}
pNew->aCol[STMT_COLUMN_NCOL] = sqlite3_column_count(p);
pNew->aCol[STMT_COLUMN_RO] = sqlite3_stmt_readonly(p);
pNew->aCol[STMT_COLUMN_BUSY] = sqlite3_stmt_busy(p);
pNew->aCol[STMT_COLUMN_NSCAN] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_FULLSCAN_STEP, 0
);
pNew->aCol[STMT_COLUMN_NSORT] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_SORT, 0
);
pNew->aCol[STMT_COLUMN_NAIDX] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_AUTOINDEX, 0
);
pNew->aCol[STMT_COLUMN_NSTEP] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_VM_STEP, 0
);
pNew->aCol[STMT_COLUMN_REPREP] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_REPREPARE, 0
);
pNew->aCol[STMT_COLUMN_RUN] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_RUN, 0
);
pNew->aCol[STMT_COLUMN_MEM] = sqlite3_stmt_status(
p, SQLITE_STMTSTATUS_MEMUSED, 0
);
pNew->iRowid = iRowid++;
*ppRow = pNew;
ppRow = &pNew->pNext;
}
return SQLITE_OK;
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the stmt virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int stmtBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
(void)tab;
pIdxInfo->estimatedCost = (double)500;
pIdxInfo->estimatedRows = 500;
return SQLITE_OK;
}
/*
** This following structure defines all the methods for the
** stmt virtual table.
*/
static sqlite3_module stmtModule = {
0, /* iVersion */
0, /* xCreate */
stmtConnect, /* xConnect */
stmtBestIndex, /* xBestIndex */
stmtDisconnect, /* xDisconnect */
0, /* xDestroy */
stmtOpen, /* xOpen - open a cursor */
stmtClose, /* xClose - close a cursor */
stmtFilter, /* xFilter - configure scan constraints */
stmtNext, /* xNext - advance a cursor */
stmtEof, /* xEof - check for end of scan */
stmtColumn, /* xColumn - read data */
stmtRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
0, /* xShadowName */
0 /* xIntegrity */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3 *db){
int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_VIRTUALTABLE
rc = sqlite3_create_module(db, "sqlite_stmt", &stmtModule, 0);
#endif
return rc;
}
#ifndef SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
SQLITE_API int sqlite3_stmt_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
#ifndef SQLITE_OMIT_VIRTUALTABLE
rc = sqlite3StmtVtabInit(db);
#endif
return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
#endif /* SQLITE_AMALGAMATION */
/************************** End of sqlite3.c ******************************/
( run in 2.172 seconds using v1.01-cache-2.11-cpan-e1769b4cff6 )