Import SQLite 3.34.0 sources
This commit is contained in:
684
shell.c
684
shell.c
@@ -571,8 +571,6 @@ static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
|
|||||||
int i;
|
int i;
|
||||||
int n;
|
int n;
|
||||||
int aw = w<0 ? -w : w;
|
int aw = w<0 ? -w : w;
|
||||||
char zBuf[1000];
|
|
||||||
if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
|
|
||||||
for(i=n=0; zUtf[i]; i++){
|
for(i=n=0; zUtf[i]; i++){
|
||||||
if( (zUtf[i]&0xc0)!=0x80 ){
|
if( (zUtf[i]&0xc0)!=0x80 ){
|
||||||
n++;
|
n++;
|
||||||
@@ -5315,6 +5313,444 @@ int sqlite3_ieee_init(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/************************* End ../ext/misc/ieee754.c ********************/
|
/************************* End ../ext/misc/ieee754.c ********************/
|
||||||
|
/************************* Begin ../ext/misc/series.c ******************/
|
||||||
|
/*
|
||||||
|
** 2015-08-18
|
||||||
|
**
|
||||||
|
** 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 how to create a table-valued-function using
|
||||||
|
** a virtual table. This demo implements the generate_series() function
|
||||||
|
** which gives similar results to the eponymous function in PostgreSQL.
|
||||||
|
** Examples:
|
||||||
|
**
|
||||||
|
** SELECT * FROM generate_series(0,100,5);
|
||||||
|
**
|
||||||
|
** The query above returns integers from 0 through 100 counting by steps
|
||||||
|
** of 5.
|
||||||
|
**
|
||||||
|
** SELECT * FROM generate_series(0,100);
|
||||||
|
**
|
||||||
|
** Integers from 0 through 100 with a step size of 1.
|
||||||
|
**
|
||||||
|
** SELECT * FROM generate_series(20) LIMIT 10;
|
||||||
|
**
|
||||||
|
** Integers 20 through 29.
|
||||||
|
**
|
||||||
|
** HOW IT WORKS
|
||||||
|
**
|
||||||
|
** The generate_series "function" is really a virtual table with the
|
||||||
|
** following schema:
|
||||||
|
**
|
||||||
|
** CREATE TABLE generate_series(
|
||||||
|
** value,
|
||||||
|
** start HIDDEN,
|
||||||
|
** stop HIDDEN,
|
||||||
|
** step HIDDEN
|
||||||
|
** );
|
||||||
|
**
|
||||||
|
** Function arguments in queries against this virtual table are translated
|
||||||
|
** into equality constraints against successive hidden columns. In other
|
||||||
|
** words, the following pairs of queries are equivalent to each other:
|
||||||
|
**
|
||||||
|
** SELECT * FROM generate_series(0,100,5);
|
||||||
|
** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5;
|
||||||
|
**
|
||||||
|
** SELECT * FROM generate_series(0,100);
|
||||||
|
** SELECT * FROM generate_series WHERE start=0 AND stop=100;
|
||||||
|
**
|
||||||
|
** SELECT * FROM generate_series(20) LIMIT 10;
|
||||||
|
** SELECT * FROM generate_series WHERE start=20 LIMIT 10;
|
||||||
|
**
|
||||||
|
** The generate_series virtual table implementation leaves the xCreate method
|
||||||
|
** set to NULL. This means that it is not possible to do a CREATE VIRTUAL
|
||||||
|
** TABLE command with "generate_series" as the USING argument. Instead, there
|
||||||
|
** is a single generate_series virtual table that is always available without
|
||||||
|
** having to be created first.
|
||||||
|
**
|
||||||
|
** The xBestIndex method looks for equality constraints against the hidden
|
||||||
|
** start, stop, and step columns, and if present, it uses those constraints
|
||||||
|
** to bound the sequence of generated values. If the equality constraints
|
||||||
|
** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step.
|
||||||
|
** xBestIndex returns a small cost when both start and stop are available,
|
||||||
|
** and a very large cost if either start or stop are unavailable. This
|
||||||
|
** encourages the query planner to order joins such that the bounds of the
|
||||||
|
** series are well-defined.
|
||||||
|
*/
|
||||||
|
/* #include "sqlite3ext.h" */
|
||||||
|
SQLITE_EXTENSION_INIT1
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
|
|
||||||
|
|
||||||
|
/* series_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 series_cursor series_cursor;
|
||||||
|
struct series_cursor {
|
||||||
|
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||||
|
int isDesc; /* True to count down rather than up */
|
||||||
|
sqlite3_int64 iRowid; /* The rowid */
|
||||||
|
sqlite3_int64 iValue; /* Current value ("value") */
|
||||||
|
sqlite3_int64 mnValue; /* Mimimum value ("start") */
|
||||||
|
sqlite3_int64 mxValue; /* Maximum value ("stop") */
|
||||||
|
sqlite3_int64 iStep; /* Increment ("step") */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The seriesConnect() method is invoked to create a new
|
||||||
|
** series_vtab that describes the generate_series virtual table.
|
||||||
|
**
|
||||||
|
** Think of this routine as the constructor for series_vtab objects.
|
||||||
|
**
|
||||||
|
** All this routine needs to do is:
|
||||||
|
**
|
||||||
|
** (1) Allocate the series_vtab object and initialize all fields.
|
||||||
|
**
|
||||||
|
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
|
||||||
|
** result set of queries against generate_series will look like.
|
||||||
|
*/
|
||||||
|
static int seriesConnect(
|
||||||
|
sqlite3 *db,
|
||||||
|
void *pUnused,
|
||||||
|
int argcUnused, const char *const*argvUnused,
|
||||||
|
sqlite3_vtab **ppVtab,
|
||||||
|
char **pzErrUnused
|
||||||
|
){
|
||||||
|
sqlite3_vtab *pNew;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Column numbers */
|
||||||
|
#define SERIES_COLUMN_VALUE 0
|
||||||
|
#define SERIES_COLUMN_START 1
|
||||||
|
#define SERIES_COLUMN_STOP 2
|
||||||
|
#define SERIES_COLUMN_STEP 3
|
||||||
|
|
||||||
|
(void)pUnused;
|
||||||
|
(void)argcUnused;
|
||||||
|
(void)argvUnused;
|
||||||
|
(void)pzErrUnused;
|
||||||
|
rc = sqlite3_declare_vtab(db,
|
||||||
|
"CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
|
||||||
|
if( pNew==0 ) return SQLITE_NOMEM;
|
||||||
|
memset(pNew, 0, sizeof(*pNew));
|
||||||
|
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This method is the destructor for series_cursor objects.
|
||||||
|
*/
|
||||||
|
static int seriesDisconnect(sqlite3_vtab *pVtab){
|
||||||
|
sqlite3_free(pVtab);
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Constructor for a new series_cursor object.
|
||||||
|
*/
|
||||||
|
static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
|
||||||
|
series_cursor *pCur;
|
||||||
|
(void)pUnused;
|
||||||
|
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 series_cursor.
|
||||||
|
*/
|
||||||
|
static int seriesClose(sqlite3_vtab_cursor *cur){
|
||||||
|
sqlite3_free(cur);
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Advance a series_cursor to its next row of output.
|
||||||
|
*/
|
||||||
|
static int seriesNext(sqlite3_vtab_cursor *cur){
|
||||||
|
series_cursor *pCur = (series_cursor*)cur;
|
||||||
|
if( pCur->isDesc ){
|
||||||
|
pCur->iValue -= pCur->iStep;
|
||||||
|
}else{
|
||||||
|
pCur->iValue += pCur->iStep;
|
||||||
|
}
|
||||||
|
pCur->iRowid++;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return values of columns for the row at which the series_cursor
|
||||||
|
** is currently pointing.
|
||||||
|
*/
|
||||||
|
static int seriesColumn(
|
||||||
|
sqlite3_vtab_cursor *cur, /* The cursor */
|
||||||
|
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
||||||
|
int i /* Which column to return */
|
||||||
|
){
|
||||||
|
series_cursor *pCur = (series_cursor*)cur;
|
||||||
|
sqlite3_int64 x = 0;
|
||||||
|
switch( i ){
|
||||||
|
case SERIES_COLUMN_START: x = pCur->mnValue; break;
|
||||||
|
case SERIES_COLUMN_STOP: x = pCur->mxValue; break;
|
||||||
|
case SERIES_COLUMN_STEP: x = pCur->iStep; break;
|
||||||
|
default: x = pCur->iValue; break;
|
||||||
|
}
|
||||||
|
sqlite3_result_int64(ctx, x);
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the rowid for the current row. In this implementation, the
|
||||||
|
** first row returned is assigned rowid value 1, and each subsequent
|
||||||
|
** row a value 1 more than that of the previous.
|
||||||
|
*/
|
||||||
|
static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||||
|
series_cursor *pCur = (series_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 seriesEof(sqlite3_vtab_cursor *cur){
|
||||||
|
series_cursor *pCur = (series_cursor*)cur;
|
||||||
|
if( pCur->isDesc ){
|
||||||
|
return pCur->iValue < pCur->mnValue;
|
||||||
|
}else{
|
||||||
|
return pCur->iValue > pCur->mxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* True to cause run-time checking of the start=, stop=, and/or step=
|
||||||
|
** parameters. The only reason to do this is for testing the
|
||||||
|
** constraint checking logic for virtual tables in the SQLite core.
|
||||||
|
*/
|
||||||
|
#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
|
||||||
|
# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This method is called to "rewind" the series_cursor object back
|
||||||
|
** to the first row of output. This method is always called at least
|
||||||
|
** once prior to any call to seriesColumn() or seriesRowid() or
|
||||||
|
** seriesEof().
|
||||||
|
**
|
||||||
|
** The query plan selected by seriesBestIndex is passed in the idxNum
|
||||||
|
** parameter. (idxStr is not used in this implementation.) idxNum
|
||||||
|
** is a bitmask showing which constraints are available:
|
||||||
|
**
|
||||||
|
** 1: start=VALUE
|
||||||
|
** 2: stop=VALUE
|
||||||
|
** 4: step=VALUE
|
||||||
|
**
|
||||||
|
** Also, if bit 8 is set, that means that the series should be output
|
||||||
|
** in descending order rather than in ascending order.
|
||||||
|
**
|
||||||
|
** This routine should initialize the cursor and position it so that it
|
||||||
|
** is pointing at the first row, or pointing off the end of the table
|
||||||
|
** (so that seriesEof() will return true) if the table is empty.
|
||||||
|
*/
|
||||||
|
static int seriesFilter(
|
||||||
|
sqlite3_vtab_cursor *pVtabCursor,
|
||||||
|
int idxNum, const char *idxStrUnused,
|
||||||
|
int argc, sqlite3_value **argv
|
||||||
|
){
|
||||||
|
series_cursor *pCur = (series_cursor *)pVtabCursor;
|
||||||
|
int i = 0;
|
||||||
|
(void)idxStrUnused;
|
||||||
|
if( idxNum & 1 ){
|
||||||
|
pCur->mnValue = sqlite3_value_int64(argv[i++]);
|
||||||
|
}else{
|
||||||
|
pCur->mnValue = 0;
|
||||||
|
}
|
||||||
|
if( idxNum & 2 ){
|
||||||
|
pCur->mxValue = sqlite3_value_int64(argv[i++]);
|
||||||
|
}else{
|
||||||
|
pCur->mxValue = 0xffffffff;
|
||||||
|
}
|
||||||
|
if( idxNum & 4 ){
|
||||||
|
pCur->iStep = sqlite3_value_int64(argv[i++]);
|
||||||
|
if( pCur->iStep<1 ) pCur->iStep = 1;
|
||||||
|
}else{
|
||||||
|
pCur->iStep = 1;
|
||||||
|
}
|
||||||
|
for(i=0; i<argc; i++){
|
||||||
|
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
|
||||||
|
/* If any of the constraints have a NULL value, then return no rows.
|
||||||
|
** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
|
||||||
|
pCur->mnValue = 1;
|
||||||
|
pCur->mxValue = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( idxNum & 8 ){
|
||||||
|
pCur->isDesc = 1;
|
||||||
|
pCur->iValue = pCur->mxValue;
|
||||||
|
if( pCur->iStep>0 ){
|
||||||
|
pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
pCur->isDesc = 0;
|
||||||
|
pCur->iValue = pCur->mnValue;
|
||||||
|
}
|
||||||
|
pCur->iRowid = 1;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** SQLite will invoke this method one or more times while planning a query
|
||||||
|
** that uses the generate_series 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.
|
||||||
|
**
|
||||||
|
** The query plan is represented by bits in idxNum:
|
||||||
|
**
|
||||||
|
** (1) start = $value -- constraint exists
|
||||||
|
** (2) stop = $value -- constraint exists
|
||||||
|
** (4) step = $value -- constraint exists
|
||||||
|
** (8) output in descending order
|
||||||
|
*/
|
||||||
|
static int seriesBestIndex(
|
||||||
|
sqlite3_vtab *tabUnused,
|
||||||
|
sqlite3_index_info *pIdxInfo
|
||||||
|
){
|
||||||
|
int i, j; /* Loop over constraints */
|
||||||
|
int idxNum = 0; /* The query plan bitmask */
|
||||||
|
int unusableMask = 0; /* Mask of unusable constraints */
|
||||||
|
int nArg = 0; /* Number of arguments that seriesFilter() expects */
|
||||||
|
int aIdx[3]; /* Constraints on start, stop, and step */
|
||||||
|
const struct sqlite3_index_constraint *pConstraint;
|
||||||
|
|
||||||
|
/* This implementation assumes that the start, stop, and step columns
|
||||||
|
** are the last three columns in the virtual table. */
|
||||||
|
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
|
||||||
|
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
|
||||||
|
(void)tabUnused;
|
||||||
|
aIdx[0] = aIdx[1] = aIdx[2] = -1;
|
||||||
|
pConstraint = pIdxInfo->aConstraint;
|
||||||
|
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||||
|
int iCol; /* 0 for start, 1 for stop, 2 for step */
|
||||||
|
int iMask; /* bitmask for those column */
|
||||||
|
if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
|
||||||
|
iCol = pConstraint->iColumn - SERIES_COLUMN_START;
|
||||||
|
assert( iCol>=0 && iCol<=2 );
|
||||||
|
iMask = 1 << iCol;
|
||||||
|
if( pConstraint->usable==0 ){
|
||||||
|
unusableMask |= iMask;
|
||||||
|
continue;
|
||||||
|
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||||
|
idxNum |= iMask;
|
||||||
|
aIdx[iCol] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(i=0; i<3; i++){
|
||||||
|
if( (j = aIdx[i])>=0 ){
|
||||||
|
pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
|
||||||
|
pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( (unusableMask & ~idxNum)!=0 ){
|
||||||
|
/* The start, stop, and step columns are inputs. Therefore if there
|
||||||
|
** are unusable constraints on any of start, stop, or step then
|
||||||
|
** this plan is unusable */
|
||||||
|
return SQLITE_CONSTRAINT;
|
||||||
|
}
|
||||||
|
if( (idxNum & 3)==3 ){
|
||||||
|
/* Both start= and stop= boundaries are available. This is the
|
||||||
|
** the preferred case */
|
||||||
|
pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
|
||||||
|
pIdxInfo->estimatedRows = 1000;
|
||||||
|
if( pIdxInfo->nOrderBy==1 ){
|
||||||
|
if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
|
||||||
|
pIdxInfo->orderByConsumed = 1;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
/* If either boundary is missing, we have to generate a huge span
|
||||||
|
** of numbers. Make this case very expensive so that the query
|
||||||
|
** planner will work hard to avoid it. */
|
||||||
|
pIdxInfo->estimatedRows = 2147483647;
|
||||||
|
}
|
||||||
|
pIdxInfo->idxNum = idxNum;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This following structure defines all the methods for the
|
||||||
|
** generate_series virtual table.
|
||||||
|
*/
|
||||||
|
static sqlite3_module seriesModule = {
|
||||||
|
0, /* iVersion */
|
||||||
|
0, /* xCreate */
|
||||||
|
seriesConnect, /* xConnect */
|
||||||
|
seriesBestIndex, /* xBestIndex */
|
||||||
|
seriesDisconnect, /* xDisconnect */
|
||||||
|
0, /* xDestroy */
|
||||||
|
seriesOpen, /* xOpen - open a cursor */
|
||||||
|
seriesClose, /* xClose - close a cursor */
|
||||||
|
seriesFilter, /* xFilter - configure scan constraints */
|
||||||
|
seriesNext, /* xNext - advance a cursor */
|
||||||
|
seriesEof, /* xEof - check for end of scan */
|
||||||
|
seriesColumn, /* xColumn - read data */
|
||||||
|
seriesRowid, /* 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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#endif
|
||||||
|
int sqlite3_series_init(
|
||||||
|
sqlite3 *db,
|
||||||
|
char **pzErrMsg,
|
||||||
|
const sqlite3_api_routines *pApi
|
||||||
|
){
|
||||||
|
int rc = SQLITE_OK;
|
||||||
|
SQLITE_EXTENSION_INIT2(pApi);
|
||||||
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
|
if( sqlite3_libversion_number()<3008012 ){
|
||||||
|
*pzErrMsg = sqlite3_mprintf(
|
||||||
|
"generate_series() requires SQLite 3.8.12 or later");
|
||||||
|
return SQLITE_ERROR;
|
||||||
|
}
|
||||||
|
rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
|
||||||
|
#endif
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************* End ../ext/misc/series.c ********************/
|
||||||
#ifdef SQLITE_HAVE_ZLIB
|
#ifdef SQLITE_HAVE_ZLIB
|
||||||
/************************* Begin ../ext/misc/zipfile.c ******************/
|
/************************* Begin ../ext/misc/zipfile.c ******************/
|
||||||
/*
|
/*
|
||||||
@@ -5842,14 +6278,16 @@ static int zipfileAppendData(
|
|||||||
const u8 *aWrite,
|
const u8 *aWrite,
|
||||||
int nWrite
|
int nWrite
|
||||||
){
|
){
|
||||||
size_t n;
|
if( nWrite>0 ){
|
||||||
fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
|
size_t n = nWrite;
|
||||||
n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
|
fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
|
||||||
if( (int)n!=nWrite ){
|
n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
|
||||||
pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
|
if( (int)n!=nWrite ){
|
||||||
return SQLITE_ERROR;
|
pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
|
||||||
|
return SQLITE_ERROR;
|
||||||
|
}
|
||||||
|
pTab->szCurrent += nWrite;
|
||||||
}
|
}
|
||||||
pTab->szCurrent += nWrite;
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8494,6 +8932,7 @@ static int idxGetTableInfo(
|
|||||||
IdxTable *pNew = 0;
|
IdxTable *pNew = 0;
|
||||||
int rc, rc2;
|
int rc, rc2;
|
||||||
char *pCsr = 0;
|
char *pCsr = 0;
|
||||||
|
int nPk = 0;
|
||||||
|
|
||||||
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
|
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
|
||||||
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
|
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
|
||||||
@@ -8504,6 +8943,7 @@ static int idxGetTableInfo(
|
|||||||
);
|
);
|
||||||
nByte += 1 + STRLEN(zCol);
|
nByte += 1 + STRLEN(zCol);
|
||||||
nCol++;
|
nCol++;
|
||||||
|
nPk += (sqlite3_column_int(p1, 5)>0);
|
||||||
}
|
}
|
||||||
rc2 = sqlite3_reset(p1);
|
rc2 = sqlite3_reset(p1);
|
||||||
if( rc==SQLITE_OK ) rc = rc2;
|
if( rc==SQLITE_OK ) rc = rc2;
|
||||||
@@ -8523,7 +8963,7 @@ static int idxGetTableInfo(
|
|||||||
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
|
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
|
||||||
int nCopy = STRLEN(zCol) + 1;
|
int nCopy = STRLEN(zCol) + 1;
|
||||||
pNew->aCol[nCol].zName = pCsr;
|
pNew->aCol[nCol].zName = pCsr;
|
||||||
pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
|
pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
|
||||||
memcpy(pCsr, zCol, nCopy);
|
memcpy(pCsr, zCol, nCopy);
|
||||||
pCsr += nCopy;
|
pCsr += nCopy;
|
||||||
|
|
||||||
@@ -10771,6 +11211,8 @@ struct ShellState {
|
|||||||
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
|
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
|
||||||
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
|
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
|
||||||
#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
|
#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
|
||||||
|
#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
|
||||||
|
#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Macros for testing and setting shellFlgs
|
** Macros for testing and setting shellFlgs
|
||||||
@@ -13291,19 +13733,25 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
|
|||||||
const char *zType;
|
const char *zType;
|
||||||
const char *zSql;
|
const char *zSql;
|
||||||
ShellState *p = (ShellState *)pArg;
|
ShellState *p = (ShellState *)pArg;
|
||||||
|
int dataOnly;
|
||||||
|
int noSys;
|
||||||
|
|
||||||
UNUSED_PARAMETER(azNotUsed);
|
UNUSED_PARAMETER(azNotUsed);
|
||||||
if( nArg!=3 || azArg==0 ) return 0;
|
if( nArg!=3 || azArg==0 ) return 0;
|
||||||
zTable = azArg[0];
|
zTable = azArg[0];
|
||||||
zType = azArg[1];
|
zType = azArg[1];
|
||||||
zSql = azArg[2];
|
zSql = azArg[2];
|
||||||
|
dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
|
||||||
|
noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
|
||||||
|
|
||||||
if( strcmp(zTable, "sqlite_sequence")==0 ){
|
if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
|
||||||
raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
|
if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
|
||||||
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
|
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
|
||||||
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
|
if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
|
||||||
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
|
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
|
||||||
return 0;
|
return 0;
|
||||||
|
}else if( dataOnly ){
|
||||||
|
/* no-op */
|
||||||
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
|
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
|
||||||
char *zIns;
|
char *zIns;
|
||||||
if( !p->writableSchema ){
|
if( !p->writableSchema ){
|
||||||
@@ -13476,8 +13924,10 @@ static const char *(azHelp[]) = {
|
|||||||
".dbinfo ?DB? Show status information about the database",
|
".dbinfo ?DB? Show status information about the database",
|
||||||
".dump ?TABLE? Render database content as SQL",
|
".dump ?TABLE? Render database content as SQL",
|
||||||
" Options:",
|
" Options:",
|
||||||
" --preserve-rowids Include ROWID values in the output",
|
" --data-only Output only INSERT statements",
|
||||||
" --newlines Allow unescaped newline characters in output",
|
" --newlines Allow unescaped newline characters in output",
|
||||||
|
" --nosys Omit system tables (ex: \"sqlite_stat1\")",
|
||||||
|
" --preserve-rowids Include ROWID values in the output",
|
||||||
" TABLE is a LIKE pattern for the tables to dump",
|
" TABLE is a LIKE pattern for the tables to dump",
|
||||||
" Additional LIKE patterns can be given in subsequent arguments",
|
" Additional LIKE patterns can be given in subsequent arguments",
|
||||||
".echo on|off Turn command echo on or off",
|
".echo on|off Turn command echo on or off",
|
||||||
@@ -13602,8 +14052,9 @@ static const char *(azHelp[]) = {
|
|||||||
".save FILE Write in-memory database into FILE",
|
".save FILE Write in-memory database into FILE",
|
||||||
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
|
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
|
||||||
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
|
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
|
||||||
" Options:",
|
" Options:",
|
||||||
" --indent Try to pretty-print the schema",
|
" --indent Try to pretty-print the schema",
|
||||||
|
" --nosys Omit objects whose names start with \"sqlite_\"",
|
||||||
".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
|
".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
|
||||||
" Options:",
|
" Options:",
|
||||||
" --init Create a new SELFTEST table",
|
" --init Create a new SELFTEST table",
|
||||||
@@ -14012,6 +14463,20 @@ static void shellIdQuote(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
|
||||||
|
*/
|
||||||
|
static void shellUSleepFunc(
|
||||||
|
sqlite3_context *context,
|
||||||
|
int argcUnused,
|
||||||
|
sqlite3_value **argv
|
||||||
|
){
|
||||||
|
int sleep = sqlite3_value_int(argv[0]);
|
||||||
|
(void)argcUnused;
|
||||||
|
sqlite3_sleep(sleep/1000);
|
||||||
|
sqlite3_result_int(context, sleep);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Scalar function "shell_escape_crnl" used by the .recover command.
|
** Scalar function "shell_escape_crnl" used by the .recover command.
|
||||||
** The argument passed to this function is the output of built-in
|
** The argument passed to this function is the output of built-in
|
||||||
@@ -14176,6 +14641,7 @@ static void open_db(ShellState *p, int openFlags){
|
|||||||
sqlite3_uint_init(p->db, 0, 0);
|
sqlite3_uint_init(p->db, 0, 0);
|
||||||
sqlite3_decimal_init(p->db, 0, 0);
|
sqlite3_decimal_init(p->db, 0, 0);
|
||||||
sqlite3_ieee_init(p->db, 0, 0);
|
sqlite3_ieee_init(p->db, 0, 0);
|
||||||
|
sqlite3_series_init(p->db, 0, 0);
|
||||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
||||||
sqlite3_dbdata_init(p->db, 0, 0);
|
sqlite3_dbdata_init(p->db, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
@@ -14195,6 +14661,8 @@ static void open_db(ShellState *p, int openFlags){
|
|||||||
shellInt32, 0, 0);
|
shellInt32, 0, 0);
|
||||||
sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
|
sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
|
||||||
shellIdQuote, 0, 0);
|
shellIdQuote, 0, 0);
|
||||||
|
sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
|
||||||
|
shellUSleepFunc, 0, 0);
|
||||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||||
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
|
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
|
||||||
editFunc, 0, 0);
|
editFunc, 0, 0);
|
||||||
@@ -17169,21 +17637,41 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
}else
|
}else
|
||||||
|
|
||||||
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
|
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
|
||||||
ShellState data;
|
char **azName = 0;
|
||||||
char *zErrMsg = 0;
|
int nName = 0;
|
||||||
|
sqlite3_stmt *pStmt;
|
||||||
|
int i;
|
||||||
open_db(p, 0);
|
open_db(p, 0);
|
||||||
memcpy(&data, p, sizeof(data));
|
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
|
||||||
data.showHeader = 0;
|
if( rc ){
|
||||||
data.cMode = data.mode = MODE_List;
|
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
|
||||||
sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
|
|
||||||
data.cnt = 0;
|
|
||||||
sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
|
|
||||||
callback, &data, &zErrMsg);
|
|
||||||
if( zErrMsg ){
|
|
||||||
utf8_printf(stderr,"Error: %s\n", zErrMsg);
|
|
||||||
sqlite3_free(zErrMsg);
|
|
||||||
rc = 1;
|
rc = 1;
|
||||||
|
}else{
|
||||||
|
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||||
|
const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
|
||||||
|
const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
|
||||||
|
azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
|
||||||
|
if( azName==0 ){ shell_out_of_memory(); /* Does not return */ }
|
||||||
|
azName[nName*2] = strdup(zSchema);
|
||||||
|
azName[nName*2+1] = strdup(zFile);
|
||||||
|
nName++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
sqlite3_finalize(pStmt);
|
||||||
|
for(i=0; i<nName; i++){
|
||||||
|
int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
|
||||||
|
int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
|
||||||
|
const char *z = azName[i*2+1];
|
||||||
|
utf8_printf(p->out, "%s: %s %s%s\n",
|
||||||
|
azName[i*2],
|
||||||
|
z && z[0] ? z : "\"\"",
|
||||||
|
bRdonly ? "r/o" : "r/w",
|
||||||
|
eTxn==SQLITE_TXN_NONE ? "" :
|
||||||
|
eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
|
||||||
|
free(azName[i*2]);
|
||||||
|
free(azName[i*2+1]);
|
||||||
|
}
|
||||||
|
sqlite3_free(azName);
|
||||||
}else
|
}else
|
||||||
|
|
||||||
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
|
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
|
||||||
@@ -17242,7 +17730,9 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
int i;
|
int i;
|
||||||
int savedShowHeader = p->showHeader;
|
int savedShowHeader = p->showHeader;
|
||||||
int savedShellFlags = p->shellFlgs;
|
int savedShellFlags = p->shellFlgs;
|
||||||
ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
|
ShellClearFlag(p,
|
||||||
|
SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
|
||||||
|
|SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
|
||||||
for(i=1; i<nArg; i++){
|
for(i=1; i<nArg; i++){
|
||||||
if( azArg[i][0]=='-' ){
|
if( azArg[i][0]=='-' ){
|
||||||
const char *z = azArg[i]+1;
|
const char *z = azArg[i]+1;
|
||||||
@@ -17261,6 +17751,12 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
if( strcmp(z,"newlines")==0 ){
|
if( strcmp(z,"newlines")==0 ){
|
||||||
ShellSetFlag(p, SHFLG_Newlines);
|
ShellSetFlag(p, SHFLG_Newlines);
|
||||||
}else
|
}else
|
||||||
|
if( strcmp(z,"data-only")==0 ){
|
||||||
|
ShellSetFlag(p, SHFLG_DumpDataOnly);
|
||||||
|
}else
|
||||||
|
if( strcmp(z,"nosys")==0 ){
|
||||||
|
ShellSetFlag(p, SHFLG_DumpNoSys);
|
||||||
|
}else
|
||||||
{
|
{
|
||||||
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
|
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
|
||||||
rc = 1;
|
rc = 1;
|
||||||
@@ -17277,11 +17773,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
|
|
||||||
open_db(p, 0);
|
open_db(p, 0);
|
||||||
|
|
||||||
/* When playing back a "dump", the content might appear in an order
|
if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
|
||||||
** which causes immediate foreign key constraints to be violated.
|
/* When playing back a "dump", the content might appear in an order
|
||||||
** So disable foreign-key constraint enforcement to prevent problems. */
|
** which causes immediate foreign key constraints to be violated.
|
||||||
raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
|
** So disable foreign-key constraint enforcement to prevent problems. */
|
||||||
raw_printf(p->out, "BEGIN TRANSACTION;\n");
|
raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
|
||||||
|
raw_printf(p->out, "BEGIN TRANSACTION;\n");
|
||||||
|
}
|
||||||
p->writableSchema = 0;
|
p->writableSchema = 0;
|
||||||
p->showHeader = 0;
|
p->showHeader = 0;
|
||||||
/* Set writable_schema=ON since doing so forces SQLite to initialize
|
/* Set writable_schema=ON since doing so forces SQLite to initialize
|
||||||
@@ -17299,14 +17797,16 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
);
|
);
|
||||||
run_schema_dump_query(p,zSql);
|
run_schema_dump_query(p,zSql);
|
||||||
sqlite3_free(zSql);
|
sqlite3_free(zSql);
|
||||||
zSql = sqlite3_mprintf(
|
if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
|
||||||
"SELECT sql FROM sqlite_schema "
|
zSql = sqlite3_mprintf(
|
||||||
"WHERE (%s) AND sql NOT NULL"
|
"SELECT sql FROM sqlite_schema "
|
||||||
" AND type IN ('index','trigger','view')",
|
"WHERE (%s) AND sql NOT NULL"
|
||||||
zLike
|
" AND type IN ('index','trigger','view')",
|
||||||
);
|
zLike
|
||||||
run_table_dump_query(p, zSql);
|
);
|
||||||
sqlite3_free(zSql);
|
run_table_dump_query(p, zSql);
|
||||||
|
sqlite3_free(zSql);
|
||||||
|
}
|
||||||
sqlite3_free(zLike);
|
sqlite3_free(zLike);
|
||||||
if( p->writableSchema ){
|
if( p->writableSchema ){
|
||||||
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
|
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
|
||||||
@@ -17314,7 +17814,9 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
}
|
}
|
||||||
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
|
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
|
||||||
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
|
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
|
||||||
raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
|
if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
|
||||||
|
raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
|
||||||
|
}
|
||||||
p->showHeader = savedShowHeader;
|
p->showHeader = savedShowHeader;
|
||||||
p->shellFlgs = savedShellFlags;
|
p->shellFlgs = savedShellFlags;
|
||||||
}else
|
}else
|
||||||
@@ -17753,7 +18255,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
while( (nSkip--)>0 ){
|
while( (nSkip--)>0 ){
|
||||||
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
|
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
|
||||||
}
|
}
|
||||||
zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
|
zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
|
||||||
if( zSql==0 ){
|
if( zSql==0 ){
|
||||||
import_cleanup(&sCtx);
|
import_cleanup(&sCtx);
|
||||||
shell_out_of_memory();
|
shell_out_of_memory();
|
||||||
@@ -17762,7 +18264,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||||
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
|
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
|
||||||
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
|
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
|
||||||
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
|
char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
|
||||||
char cSep = '(';
|
char cSep = '(';
|
||||||
while( xRead(&sCtx) ){
|
while( xRead(&sCtx) ){
|
||||||
zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
|
zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
|
||||||
@@ -17783,7 +18285,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
|
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
|
||||||
sqlite3_free(zCreate);
|
sqlite3_free(zCreate);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
|
utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
|
||||||
sqlite3_errmsg(p->db));
|
sqlite3_errmsg(p->db));
|
||||||
import_cleanup(&sCtx);
|
import_cleanup(&sCtx);
|
||||||
rc = 1;
|
rc = 1;
|
||||||
@@ -18548,9 +19050,16 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
rc = 1;
|
rc = 1;
|
||||||
goto meta_command_exit;
|
goto meta_command_exit;
|
||||||
}
|
}
|
||||||
if( notNormalFile(azArg[1])
|
if( azArg[1][0]=='|' ){
|
||||||
|| (p->in = fopen(azArg[1], "rb"))==0
|
p->in = popen(azArg[1]+1, "r");
|
||||||
){
|
if( p->in==0 ){
|
||||||
|
utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
|
||||||
|
rc = 1;
|
||||||
|
}else{
|
||||||
|
rc = process_input(p);
|
||||||
|
pclose(p->in);
|
||||||
|
}
|
||||||
|
}else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
|
||||||
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
|
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
|
||||||
rc = 1;
|
rc = 1;
|
||||||
}else{
|
}else{
|
||||||
@@ -18632,6 +19141,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
const char *zName = 0;
|
const char *zName = 0;
|
||||||
int iSchema = 0;
|
int iSchema = 0;
|
||||||
int bDebug = 0;
|
int bDebug = 0;
|
||||||
|
int bNoSystemTabs = 0;
|
||||||
int ii;
|
int ii;
|
||||||
|
|
||||||
open_db(p, 0);
|
open_db(p, 0);
|
||||||
@@ -18644,10 +19154,16 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
data.cMode = data.mode = MODE_Pretty;
|
data.cMode = data.mode = MODE_Pretty;
|
||||||
}else if( optionMatch(azArg[ii],"debug") ){
|
}else if( optionMatch(azArg[ii],"debug") ){
|
||||||
bDebug = 1;
|
bDebug = 1;
|
||||||
|
}else if( optionMatch(azArg[ii],"nosys") ){
|
||||||
|
bNoSystemTabs = 1;
|
||||||
|
}else if( azArg[ii][0]=='-' ){
|
||||||
|
utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
|
||||||
|
rc = 1;
|
||||||
|
goto meta_command_exit;
|
||||||
}else if( zName==0 ){
|
}else if( zName==0 ){
|
||||||
zName = azArg[ii];
|
zName = azArg[ii];
|
||||||
}else{
|
}else{
|
||||||
raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
|
raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
|
||||||
rc = 1;
|
rc = 1;
|
||||||
goto meta_command_exit;
|
goto meta_command_exit;
|
||||||
}
|
}
|
||||||
@@ -18733,7 +19249,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
appendText(&sSelect, " AND ", 0);
|
appendText(&sSelect, " AND ", 0);
|
||||||
sqlite3_free(zQarg);
|
sqlite3_free(zQarg);
|
||||||
}
|
}
|
||||||
appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
|
if( bNoSystemTabs ){
|
||||||
|
appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
|
||||||
|
}
|
||||||
|
appendText(&sSelect, "sql IS NOT NULL"
|
||||||
" ORDER BY snum, rowid", 0);
|
" ORDER BY snum, rowid", 0);
|
||||||
if( bDebug ){
|
if( bDebug ){
|
||||||
utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
|
utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
|
||||||
@@ -19430,6 +19949,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
|
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
|
||||||
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
|
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
|
||||||
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
|
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
|
||||||
|
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
|
||||||
};
|
};
|
||||||
int testctrl = -1;
|
int testctrl = -1;
|
||||||
int iCtrl = -1;
|
int iCtrl = -1;
|
||||||
@@ -19492,7 +20012,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
/* sqlite3_test_control(int) */
|
/* sqlite3_test_control(int) */
|
||||||
case SQLITE_TESTCTRL_PRNG_SAVE:
|
case SQLITE_TESTCTRL_PRNG_SAVE:
|
||||||
case SQLITE_TESTCTRL_PRNG_RESTORE:
|
case SQLITE_TESTCTRL_PRNG_RESTORE:
|
||||||
case SQLITE_TESTCTRL_PRNG_RESET:
|
|
||||||
case SQLITE_TESTCTRL_BYTEORDER:
|
case SQLITE_TESTCTRL_BYTEORDER:
|
||||||
if( nArg==2 ){
|
if( nArg==2 ){
|
||||||
rc2 = sqlite3_test_control(testctrl);
|
rc2 = sqlite3_test_control(testctrl);
|
||||||
@@ -19566,6 +20085,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SQLITE_TESTCTRL_SEEK_COUNT: {
|
||||||
|
u64 x = 0;
|
||||||
|
rc2 = sqlite3_test_control(testctrl, p->db, &x);
|
||||||
|
utf8_printf(p->out, "%llu\n", x);
|
||||||
|
isOk = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef YYCOVERAGE
|
#ifdef YYCOVERAGE
|
||||||
case SQLITE_TESTCTRL_PARSER_COVERAGE:
|
case SQLITE_TESTCTRL_PARSER_COVERAGE:
|
||||||
if( nArg==2 ){
|
if( nArg==2 ){
|
||||||
@@ -20144,8 +20671,11 @@ static void process_sqliterc(
|
|||||||
if( stdin_is_interactive ){
|
if( stdin_is_interactive ){
|
||||||
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
|
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
|
||||||
}
|
}
|
||||||
process_input(p);
|
if( process_input(p) && bail_on_error ) exit(1);
|
||||||
fclose(p->in);
|
fclose(p->in);
|
||||||
|
}else if( sqliterc_override!=0 ){
|
||||||
|
utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
|
||||||
|
if( bail_on_error ) exit(1);
|
||||||
}
|
}
|
||||||
p->in = inSaved;
|
p->in = inSaved;
|
||||||
p->lineno = savedLineno;
|
p->lineno = savedLineno;
|
||||||
@@ -20204,6 +20734,7 @@ static const char zOptions[] =
|
|||||||
#endif
|
#endif
|
||||||
" -stats print memory stats before each finalize\n"
|
" -stats print memory stats before each finalize\n"
|
||||||
" -table set output mode to 'table'\n"
|
" -table set output mode to 'table'\n"
|
||||||
|
" -tabs set output mode to 'tabs'\n"
|
||||||
" -version show SQLite version\n"
|
" -version show SQLite version\n"
|
||||||
" -vfs NAME use NAME as the default VFS\n"
|
" -vfs NAME use NAME as the default VFS\n"
|
||||||
#ifdef SQLITE_ENABLE_VFSTRACE
|
#ifdef SQLITE_ENABLE_VFSTRACE
|
||||||
@@ -20461,11 +20992,14 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|||||||
(void)cmdline_option_value(argc, argv, ++i);
|
(void)cmdline_option_value(argc, argv, ++i);
|
||||||
#endif
|
#endif
|
||||||
}else if( strcmp(z,"-pagecache")==0 ){
|
}else if( strcmp(z,"-pagecache")==0 ){
|
||||||
int n, sz;
|
sqlite3_int64 n, sz;
|
||||||
sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
sz = integerValue(cmdline_option_value(argc,argv,++i));
|
||||||
if( sz>70000 ) sz = 70000;
|
if( sz>70000 ) sz = 70000;
|
||||||
if( sz<0 ) sz = 0;
|
if( sz<0 ) sz = 0;
|
||||||
n = (int)integerValue(cmdline_option_value(argc,argv,++i));
|
n = integerValue(cmdline_option_value(argc,argv,++i));
|
||||||
|
if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
|
||||||
|
n = 0xffffffffffffLL/sz;
|
||||||
|
}
|
||||||
sqlite3_config(SQLITE_CONFIG_PAGECACHE,
|
sqlite3_config(SQLITE_CONFIG_PAGECACHE,
|
||||||
(n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
|
(n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
|
||||||
data.shellFlgs |= SHFLG_Pagecache;
|
data.shellFlgs |= SHFLG_Pagecache;
|
||||||
@@ -20527,6 +21061,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|||||||
#endif
|
#endif
|
||||||
}else if( strcmp(z, "-memtrace")==0 ){
|
}else if( strcmp(z, "-memtrace")==0 ){
|
||||||
sqlite3MemTraceActivate(stderr);
|
sqlite3MemTraceActivate(stderr);
|
||||||
|
}else if( strcmp(z,"-bail")==0 ){
|
||||||
|
bail_on_error = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verify_uninitialized();
|
verify_uninitialized();
|
||||||
@@ -20601,6 +21137,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|||||||
data.mode = MODE_List;
|
data.mode = MODE_List;
|
||||||
}else if( strcmp(z,"-quote")==0 ){
|
}else if( strcmp(z,"-quote")==0 ){
|
||||||
data.mode = MODE_Quote;
|
data.mode = MODE_Quote;
|
||||||
|
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
|
||||||
|
sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
|
||||||
}else if( strcmp(z,"-line")==0 ){
|
}else if( strcmp(z,"-line")==0 ){
|
||||||
data.mode = MODE_Line;
|
data.mode = MODE_Line;
|
||||||
}else if( strcmp(z,"-column")==0 ){
|
}else if( strcmp(z,"-column")==0 ){
|
||||||
@@ -20634,10 +21172,12 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|||||||
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
|
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
|
||||||
}else if( strcmp(z,"-ascii")==0 ){
|
}else if( strcmp(z,"-ascii")==0 ){
|
||||||
data.mode = MODE_Ascii;
|
data.mode = MODE_Ascii;
|
||||||
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
|
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
|
||||||
SEP_Unit);
|
sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
|
||||||
sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
|
}else if( strcmp(z,"-tabs")==0 ){
|
||||||
SEP_Record);
|
data.mode = MODE_List;
|
||||||
|
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
|
||||||
|
sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
|
||||||
}else if( strcmp(z,"-separator")==0 ){
|
}else if( strcmp(z,"-separator")==0 ){
|
||||||
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
|
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
|
||||||
"%s",cmdline_option_value(argc,argv,++i));
|
"%s",cmdline_option_value(argc,argv,++i));
|
||||||
@@ -20669,7 +21209,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|||||||
*/
|
*/
|
||||||
ShellSetFlag(&data, SHFLG_Backslash);
|
ShellSetFlag(&data, SHFLG_Backslash);
|
||||||
}else if( strcmp(z,"-bail")==0 ){
|
}else if( strcmp(z,"-bail")==0 ){
|
||||||
bail_on_error = 1;
|
/* No-op. The bail_on_error flag should already be set. */
|
||||||
}else if( strcmp(z,"-version")==0 ){
|
}else if( strcmp(z,"-version")==0 ){
|
||||||
printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
|
printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
|
||||||
return 0;
|
return 0;
|
||||||
@@ -20757,20 +21297,25 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|||||||
for(i=0; i<nCmd; i++){
|
for(i=0; i<nCmd; i++){
|
||||||
if( azCmd[i][0]=='.' ){
|
if( azCmd[i][0]=='.' ){
|
||||||
rc = do_meta_command(azCmd[i], &data);
|
rc = do_meta_command(azCmd[i], &data);
|
||||||
if( rc ) return rc==2 ? 0 : rc;
|
if( rc ){
|
||||||
|
free(azCmd);
|
||||||
|
return rc==2 ? 0 : rc;
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
open_db(&data, 0);
|
open_db(&data, 0);
|
||||||
rc = shell_exec(&data, azCmd[i], &zErrMsg);
|
rc = shell_exec(&data, azCmd[i], &zErrMsg);
|
||||||
if( zErrMsg!=0 ){
|
if( zErrMsg || rc ){
|
||||||
utf8_printf(stderr,"Error: %s\n", zErrMsg);
|
if( zErrMsg!=0 ){
|
||||||
|
utf8_printf(stderr,"Error: %s\n", zErrMsg);
|
||||||
|
}else{
|
||||||
|
utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
|
||||||
|
}
|
||||||
|
sqlite3_free(zErrMsg);
|
||||||
|
free(azCmd);
|
||||||
return rc!=0 ? rc : 1;
|
return rc!=0 ? rc : 1;
|
||||||
}else if( rc!=0 ){
|
|
||||||
utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(azCmd);
|
|
||||||
}else{
|
}else{
|
||||||
/* Run commands received from standard input
|
/* Run commands received from standard input
|
||||||
*/
|
*/
|
||||||
@@ -20816,6 +21361,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|||||||
rc = process_input(&data);
|
rc = process_input(&data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(azCmd);
|
||||||
set_table_name(&data, 0);
|
set_table_name(&data, 0);
|
||||||
if( data.db ){
|
if( data.db ){
|
||||||
session_close_all(&data);
|
session_close_all(&data);
|
||||||
|
|||||||
79
sqlite3.h
79
sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
|
|||||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||||
** [sqlite_version()] and [sqlite_source_id()].
|
** [sqlite_version()] and [sqlite_source_id()].
|
||||||
*/
|
*/
|
||||||
#define SQLITE_VERSION "3.33.0"
|
#define SQLITE_VERSION "3.34.0"
|
||||||
#define SQLITE_VERSION_NUMBER 3033000
|
#define SQLITE_VERSION_NUMBER 3034000
|
||||||
#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f"
|
#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 a26b6597e3ae272231b96f9982c3bcc17ddec2f2b6eb4df06a224b91089fed5b"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Run-Time Library Version Numbers
|
** CAPI3REF: Run-Time Library Version Numbers
|
||||||
@@ -504,6 +504,7 @@ SQLITE_API int sqlite3_exec(
|
|||||||
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
||||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||||
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
||||||
|
#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
|
||||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||||
@@ -6186,6 +6187,57 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
|
|||||||
*/
|
*/
|
||||||
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
|
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** CAPI3REF: Determine the transaction state of a database
|
||||||
|
** METHOD: sqlite3
|
||||||
|
**
|
||||||
|
** ^The sqlite3_txn_state(D,S) interface returns the current
|
||||||
|
** [transaction state] of schema S in database connection D. ^If S is NULL,
|
||||||
|
** then the highest transaction state of any schema on database connection D
|
||||||
|
** is returned. Transaction states are (in order of lowest to highest):
|
||||||
|
** <ol>
|
||||||
|
** <li value="0"> SQLITE_TXN_NONE
|
||||||
|
** <li value="1"> SQLITE_TXN_READ
|
||||||
|
** <li value="2"> SQLITE_TXN_WRITE
|
||||||
|
** </ol>
|
||||||
|
** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
|
||||||
|
** a valid schema, then -1 is returned.
|
||||||
|
*/
|
||||||
|
SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
|
||||||
|
** KEYWORDS: {transaction state}
|
||||||
|
**
|
||||||
|
** These constants define the current transaction state of a database file.
|
||||||
|
** ^The [sqlite3_txn_state(D,S)] interface returns one of these
|
||||||
|
** constants in order to describe the transaction state of schema S
|
||||||
|
** in [database connection] D.
|
||||||
|
**
|
||||||
|
** <dl>
|
||||||
|
** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
|
||||||
|
** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
|
||||||
|
** pending.</dd>
|
||||||
|
**
|
||||||
|
** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
|
||||||
|
** <dd>The SQLITE_TXN_READ state means that the database is currently
|
||||||
|
** in a read transaction. Content has been read from the database file
|
||||||
|
** but nothing in the database file has changed. The transaction state
|
||||||
|
** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
|
||||||
|
** no other conflicting concurrent write transactions. The transaction
|
||||||
|
** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
|
||||||
|
** [COMMIT].</dd>
|
||||||
|
**
|
||||||
|
** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
|
||||||
|
** <dd>The SQLITE_TXN_WRITE state means that the database is currently
|
||||||
|
** in a write transaction. Content has been written to the database file
|
||||||
|
** but has not yet committed. The transaction state will change to
|
||||||
|
** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
|
||||||
|
*/
|
||||||
|
#define SQLITE_TXN_NONE 0
|
||||||
|
#define SQLITE_TXN_READ 1
|
||||||
|
#define SQLITE_TXN_WRITE 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Find the next prepared statement
|
** CAPI3REF: Find the next prepared statement
|
||||||
** METHOD: sqlite3
|
** METHOD: sqlite3
|
||||||
@@ -7712,7 +7764,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
|||||||
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
|
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
|
||||||
#define SQLITE_TESTCTRL_PRNG_SEED 28
|
#define SQLITE_TESTCTRL_PRNG_SEED 28
|
||||||
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
|
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
|
||||||
#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
|
#define SQLITE_TESTCTRL_SEEK_COUNT 30
|
||||||
|
#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: SQL Keyword Checking
|
** CAPI3REF: SQL Keyword Checking
|
||||||
@@ -9192,10 +9245,11 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
|||||||
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
|
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
|
||||||
**
|
**
|
||||||
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
|
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
|
||||||
** method of a [virtual table], then it returns true if and only if the
|
** method of a [virtual table], then it might return true if the
|
||||||
** column is being fetched as part of an UPDATE operation during which the
|
** column is being fetched as part of an UPDATE operation during which the
|
||||||
** column value will not change. Applications might use this to substitute
|
** column value will not change. The virtual table implementation can use
|
||||||
** a return value that is less expensive to compute and that the corresponding
|
** this hint as permission to substitute a return value that is less
|
||||||
|
** expensive to compute and that the corresponding
|
||||||
** [xUpdate] method understands as a "no-change" value.
|
** [xUpdate] method understands as a "no-change" value.
|
||||||
**
|
**
|
||||||
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
||||||
@@ -9204,6 +9258,12 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
|||||||
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
||||||
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
||||||
** same column in the [xUpdate] method.
|
** same column in the [xUpdate] method.
|
||||||
|
**
|
||||||
|
** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
|
||||||
|
** implementations should continue to give a correct answer even if the
|
||||||
|
** sqlite3_vtab_nochange() interface were to always return false. In the
|
||||||
|
** current implementation, the sqlite3_vtab_nochange() interface does always
|
||||||
|
** returns false for the enhanced [UPDATE FROM] statement.
|
||||||
*/
|
*/
|
||||||
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
|
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
|
||||||
|
|
||||||
@@ -9345,6 +9405,7 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Flush caches to disk mid-transaction
|
** CAPI3REF: Flush caches to disk mid-transaction
|
||||||
|
** METHOD: sqlite3
|
||||||
**
|
**
|
||||||
** ^If a write-transaction is open on [database connection] D when the
|
** ^If a write-transaction is open on [database connection] D when the
|
||||||
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
|
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
|
||||||
@@ -9377,6 +9438,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: The pre-update hook.
|
** CAPI3REF: The pre-update hook.
|
||||||
|
** METHOD: sqlite3
|
||||||
**
|
**
|
||||||
** ^These interfaces are only available if SQLite is compiled using the
|
** ^These interfaces are only available if SQLite is compiled using the
|
||||||
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
|
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
|
||||||
@@ -9417,7 +9479,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
|||||||
** seventh parameter is the final rowid value of the row being inserted
|
** seventh parameter is the final rowid value of the row being inserted
|
||||||
** or updated. The value of the seventh parameter passed to the callback
|
** or updated. The value of the seventh parameter passed to the callback
|
||||||
** function is not defined for operations on WITHOUT ROWID tables, or for
|
** function is not defined for operations on WITHOUT ROWID tables, or for
|
||||||
** INSERT operations on rowid tables.
|
** DELETE operations on rowid tables.
|
||||||
**
|
**
|
||||||
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
|
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
|
||||||
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
|
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
|
||||||
@@ -9479,6 +9541,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Low-level system error code
|
** CAPI3REF: Low-level system error code
|
||||||
|
** METHOD: sqlite3
|
||||||
**
|
**
|
||||||
** ^Attempt to return the underlying operating system error code or error
|
** ^Attempt to return the underlying operating system error code or error
|
||||||
** number that caused the most recent I/O error or failure to open a file.
|
** number that caused the most recent I/O error or failure to open a file.
|
||||||
|
|||||||
@@ -335,6 +335,8 @@ struct sqlite3_api_routines {
|
|||||||
int,const char**);
|
int,const char**);
|
||||||
void (*free_filename)(char*);
|
void (*free_filename)(char*);
|
||||||
sqlite3_file *(*database_file_object)(const char*);
|
sqlite3_file *(*database_file_object)(const char*);
|
||||||
|
/* Version 3.34.0 and later */
|
||||||
|
int (*txn_state)(sqlite3*,const char*);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -639,6 +641,8 @@ typedef int (*sqlite3_loadext_entry)(
|
|||||||
#define sqlite3_create_filename sqlite3_api->create_filename
|
#define sqlite3_create_filename sqlite3_api->create_filename
|
||||||
#define sqlite3_free_filename sqlite3_api->free_filename
|
#define sqlite3_free_filename sqlite3_api->free_filename
|
||||||
#define sqlite3_database_file_object sqlite3_api->database_file_object
|
#define sqlite3_database_file_object sqlite3_api->database_file_object
|
||||||
|
/* Version 3.34.0 and later */
|
||||||
|
#define sqlite3_txn_state sqlite3_api->txn_state
|
||||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||||
|
|
||||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||||
|
|||||||
Reference in New Issue
Block a user