Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c07a705430 | |||
| 07052d5535 | |||
| bebf54438e | |||
| f470c37a2b | |||
| 60bdcf5e56 | |||
| 9b7e8e10f2 | |||
| 8820c8d3ee | |||
| 24efa5444d | |||
| ba160891de | |||
| bfbf7d9daa | |||
| bdc9744f60 | |||
| d7dc0a36cc | |||
| 49f84ce1cd | |||
| 5612ef1057 | |||
| 44d068532e | |||
| 5351e884aa | |||
| 15fc988ce0 | |||
| ca9a5faf70 | |||
| f8248c42f9 | |||
| 09b523c99b | |||
| 60afcb80ee | |||
| 601c8f2829 | |||
| b2d83494d3 | |||
| 17e65ae4c0 | |||
| 50db3e8d51 | |||
| 09d00b2f4f | |||
| 0efb6f5135 | |||
| 6dd5f07d3d | |||
| 982c1fac2b | |||
| d7134fe0c1 | |||
| 7c5577acdc | |||
| d7fda6cfc5 | |||
| 6afa35c985 | |||
| 1c06b47864 | |||
| eb7f2a0fc5 | |||
| 98aa2abc45 | |||
| 2e5e0e10f2 | |||
| 6b26a7b950 | |||
| 6705584a5b | |||
| 5398806889 | |||
| 2fae150402 | |||
| 6314eeaeb3 | |||
| 6fb5d358a8 | |||
| 7ebb605c0a | |||
| f8937f9034 | |||
| 2c3ba94969 | |||
| 7cc5595a01 | |||
| 5eaebf3a63 | |||
| fc9098a45e | |||
| 0d7f0ccd96 | |||
| 5db90714aa | |||
| 42eb070729 | |||
| eda079cd2c | |||
| 34566c4434 | |||
| 674b894269 | |||
| 504eba5f46 | |||
| 85c6892aa4 | |||
| c6727c8342 | |||
| 16f39b6e5d | |||
| c4b1e5e758 | |||
| 253c6ee1bf | |||
| b1e1a0fd2d | |||
| 40b4e7a692 | |||
| d4cb09e3d2 | |||
| 051a1022ff | |||
| e597c47545 | |||
| de79e094bc | |||
| 746127e734 | |||
| 0208337c16 | |||
| e68fe9665a | |||
| 95f78d98b9 | |||
| 86f3492650 | |||
| 6557a07ca8 | |||
| 9b84f03556 | |||
| 2b7cdf6f6b | |||
| 6a9afa918b | |||
| e9816d82a7 |
@@ -437,6 +437,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
$(TOP)/ext/misc/csv.c \
|
||||
$(TOP)/ext/misc/eval.c \
|
||||
$(TOP)/ext/misc/explain.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/fuzzer.c \
|
||||
$(TOP)/ext/fts5/fts5_tcl.c \
|
||||
|
||||
@@ -1515,6 +1515,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\closure.c \
|
||||
$(TOP)\ext\misc\csv.c \
|
||||
$(TOP)\ext\misc\eval.c \
|
||||
$(TOP)\ext\misc\explain.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\fuzzer.c \
|
||||
$(TOP)\ext\fts5\fts5_tcl.c \
|
||||
|
||||
@@ -172,7 +172,7 @@ AC_ARG_ENABLE(session, [AS_HELP_STRING(
|
||||
[--enable-session], [enable the session extension [default=no]])],
|
||||
[], [])
|
||||
if test x"$enable_session" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.25.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.26.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.25.0'
|
||||
PACKAGE_STRING='sqlite 3.25.0'
|
||||
PACKAGE_VERSION='3.26.0'
|
||||
PACKAGE_STRING='sqlite 3.26.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1466,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.25.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1531,7 +1531,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.25.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.26.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1657,7 +1657,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.25.0
|
||||
sqlite configure 3.26.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2076,7 +2076,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.25.0, which was
|
||||
It was created by sqlite $as_me 3.26.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -12232,7 +12232,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.25.0, which was
|
||||
This file was extended by sqlite $as_me 3.26.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12298,7 +12298,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.25.0
|
||||
sqlite config.status 3.26.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
** 2018-09-16
|
||||
**
|
||||
** 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 the
|
||||
** EXPLAIN output from an SQL statement.
|
||||
**
|
||||
** Usage example:
|
||||
**
|
||||
** .load ./explain
|
||||
** SELECT p2 FROM explain('SELECT * FROM sqlite_master')
|
||||
** WHERE opcode='OpenRead';
|
||||
*/
|
||||
#if !defined(SQLITEINT_H)
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
/* explain_vtab is a subclass of sqlite3_vtab which will
|
||||
** serve as the underlying representation of a explain virtual table
|
||||
*/
|
||||
typedef struct explain_vtab explain_vtab;
|
||||
struct explain_vtab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
sqlite3 *db; /* Database connection for this explain vtab */
|
||||
};
|
||||
|
||||
/* explain_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 from an EXPLAIN operation.
|
||||
*/
|
||||
typedef struct explain_cursor explain_cursor;
|
||||
struct explain_cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
sqlite3 *db; /* Database connection for this cursor */
|
||||
char *zSql; /* Value for the EXPLN_COLUMN_SQL column */
|
||||
sqlite3_stmt *pExplain; /* Statement being explained */
|
||||
int rc; /* Result of last sqlite3_step() on pExplain */
|
||||
};
|
||||
|
||||
/*
|
||||
** The explainConnect() method is invoked to create a new
|
||||
** explain_vtab that describes the explain virtual table.
|
||||
**
|
||||
** Think of this routine as the constructor for explain_vtab objects.
|
||||
**
|
||||
** All this routine needs to do is:
|
||||
**
|
||||
** (1) Allocate the explain_vtab object and initialize all fields.
|
||||
**
|
||||
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
|
||||
** result set of queries against explain will look like.
|
||||
*/
|
||||
static int explainConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
explain_vtab *pNew;
|
||||
int rc;
|
||||
|
||||
/* Column numbers */
|
||||
#define EXPLN_COLUMN_ADDR 0 /* Instruction address */
|
||||
#define EXPLN_COLUMN_OPCODE 1 /* Opcode */
|
||||
#define EXPLN_COLUMN_P1 2 /* Operand 1 */
|
||||
#define EXPLN_COLUMN_P2 3 /* Operand 2 */
|
||||
#define EXPLN_COLUMN_P3 4 /* Operand 3 */
|
||||
#define EXPLN_COLUMN_P4 5 /* Operand 4 */
|
||||
#define EXPLN_COLUMN_P5 6 /* Operand 5 */
|
||||
#define EXPLN_COLUMN_COMMENT 7 /* Comment */
|
||||
#define EXPLN_COLUMN_SQL 8 /* SQL that is being explained */
|
||||
|
||||
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x(addr,opcode,p1,p2,p3,p4,p5,comment,sql HIDDEN)");
|
||||
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;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is the destructor for explain_cursor objects.
|
||||
*/
|
||||
static int explainDisconnect(sqlite3_vtab *pVtab){
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Constructor for a new explain_cursor object.
|
||||
*/
|
||||
static int explainOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
explain_cursor *pCur;
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
pCur->db = ((explain_vtab*)p)->db;
|
||||
*ppCursor = &pCur->base;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destructor for a explain_cursor.
|
||||
*/
|
||||
static int explainClose(sqlite3_vtab_cursor *cur){
|
||||
explain_cursor *pCur = (explain_cursor*)cur;
|
||||
sqlite3_finalize(pCur->pExplain);
|
||||
sqlite3_free(pCur->zSql);
|
||||
sqlite3_free(pCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Advance a explain_cursor to its next row of output.
|
||||
*/
|
||||
static int explainNext(sqlite3_vtab_cursor *cur){
|
||||
explain_cursor *pCur = (explain_cursor*)cur;
|
||||
pCur->rc = sqlite3_step(pCur->pExplain);
|
||||
if( pCur->rc!=SQLITE_DONE && pCur->rc!=SQLITE_ROW ) return pCur->rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return values of columns for the row at which the explain_cursor
|
||||
** is currently pointing.
|
||||
*/
|
||||
static int explainColumn(
|
||||
sqlite3_vtab_cursor *cur, /* The cursor */
|
||||
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
||||
int i /* Which column to return */
|
||||
){
|
||||
explain_cursor *pCur = (explain_cursor*)cur;
|
||||
if( i==EXPLN_COLUMN_SQL ){
|
||||
sqlite3_result_text(ctx, pCur->zSql, -1, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_value(ctx, sqlite3_column_value(pCur->pExplain, 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 explainRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
explain_cursor *pCur = (explain_cursor*)cur;
|
||||
*pRowid = sqlite3_column_int64(pCur->pExplain, 0);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the cursor has been moved off of the last
|
||||
** row of output.
|
||||
*/
|
||||
static int explainEof(sqlite3_vtab_cursor *cur){
|
||||
explain_cursor *pCur = (explain_cursor*)cur;
|
||||
return pCur->rc!=SQLITE_ROW;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is called to "rewind" the explain_cursor object back
|
||||
** to the first row of output. This method is always called at least
|
||||
** once prior to any call to explainColumn() or explainRowid() or
|
||||
** explainEof().
|
||||
**
|
||||
** The argv[0] is the SQL statement that is to be explained.
|
||||
*/
|
||||
static int explainFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
explain_cursor *pCur = (explain_cursor *)pVtabCursor;
|
||||
char *zSql = 0;
|
||||
int rc;
|
||||
sqlite3_finalize(pCur->pExplain);
|
||||
pCur->pExplain = 0;
|
||||
if( sqlite3_value_type(argv[0])!=SQLITE_TEXT ){
|
||||
pCur->rc = SQLITE_DONE;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
sqlite3_free(pCur->zSql);
|
||||
pCur->zSql = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
|
||||
if( pCur->zSql ){
|
||||
zSql = sqlite3_mprintf("EXPLAIN %s", pCur->zSql);
|
||||
}
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pExplain, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( rc ){
|
||||
sqlite3_finalize(pCur->pExplain);
|
||||
pCur->pExplain = 0;
|
||||
sqlite3_free(pCur->zSql);
|
||||
pCur->zSql = 0;
|
||||
}else{
|
||||
pCur->rc = sqlite3_step(pCur->pExplain);
|
||||
rc = (pCur->rc==SQLITE_DONE || pCur->rc==SQLITE_ROW) ? SQLITE_OK : pCur->rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** SQLite will invoke this method one or more times while planning a query
|
||||
** that uses the explain virtual table. This routine needs to create
|
||||
** a query plan for each invocation and compute an estimated cost for that
|
||||
** plan.
|
||||
*/
|
||||
static int explainBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
int i;
|
||||
|
||||
pIdxInfo->estimatedCost = (double)1000000;
|
||||
pIdxInfo->estimatedRows = 500;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
|
||||
if( p->usable
|
||||
&& p->iColumn==EXPLN_COLUMN_SQL
|
||||
&& p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
){
|
||||
pIdxInfo->estimatedCost = 10.0;
|
||||
pIdxInfo->idxNum = 1;
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[i].omit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This following structure defines all the methods for the
|
||||
** explain virtual table.
|
||||
*/
|
||||
static sqlite3_module explainModule = {
|
||||
0, /* iVersion */
|
||||
0, /* xCreate */
|
||||
explainConnect, /* xConnect */
|
||||
explainBestIndex, /* xBestIndex */
|
||||
explainDisconnect, /* xDisconnect */
|
||||
0, /* xDestroy */
|
||||
explainOpen, /* xOpen - open a cursor */
|
||||
explainClose, /* xClose - close a cursor */
|
||||
explainFilter, /* xFilter - configure scan constraints */
|
||||
explainNext, /* xNext - advance a cursor */
|
||||
explainEof, /* xEof - check for end of scan */
|
||||
explainColumn, /* xColumn - read data */
|
||||
explainRowid, /* xRowid - read data */
|
||||
0, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
int sqlite3ExplainVtabInit(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
rc = sqlite3_create_module(db, "explain", &explainModule, 0);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_explain_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
rc = sqlite3ExplainVtabInit(db);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
** 2018-09-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.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file demonstrates an eponymous virtual table that returns information
|
||||
** from sqlite3_status64() and sqlite3_db_status().
|
||||
**
|
||||
** Usage example:
|
||||
**
|
||||
** .load ./memstat
|
||||
** .mode quote
|
||||
** .header on
|
||||
** SELECT * FROM memstat;
|
||||
*/
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB)
|
||||
#if !defined(SQLITEINT_H)
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
/* memstat_vtab is a subclass of sqlite3_vtab which will
|
||||
** serve as the underlying representation of a memstat virtual table
|
||||
*/
|
||||
typedef struct memstat_vtab memstat_vtab;
|
||||
struct memstat_vtab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
sqlite3 *db; /* Database connection for this memstat vtab */
|
||||
};
|
||||
|
||||
/* memstat_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 memstat_cursor memstat_cursor;
|
||||
struct memstat_cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
sqlite3 *db; /* Database connection for this cursor */
|
||||
int iRowid; /* Current row in aMemstatColumn[] */
|
||||
int iDb; /* Which schema we are looking at */
|
||||
int nDb; /* Number of schemas */
|
||||
char **azDb; /* Names of all schemas */
|
||||
sqlite3_int64 aVal[2]; /* Result values */
|
||||
};
|
||||
|
||||
/*
|
||||
** The memstatConnect() method is invoked to create a new
|
||||
** memstat_vtab that describes the memstat virtual table.
|
||||
**
|
||||
** Think of this routine as the constructor for memstat_vtab objects.
|
||||
**
|
||||
** All this routine needs to do is:
|
||||
**
|
||||
** (1) Allocate the memstat_vtab object and initialize all fields.
|
||||
**
|
||||
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
|
||||
** result set of queries against memstat will look like.
|
||||
*/
|
||||
static int memstatConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
memstat_vtab *pNew;
|
||||
int rc;
|
||||
|
||||
/* Column numbers */
|
||||
#define MSV_COLUMN_NAME 0 /* Name of quantity being measured */
|
||||
#define MSV_COLUMN_SCHEMA 1 /* schema name */
|
||||
#define MSV_COLUMN_VALUE 2 /* Current value */
|
||||
#define MSV_COLUMN_HIWTR 3 /* Highwater mark */
|
||||
|
||||
rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,schema,value,hiwtr)");
|
||||
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;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is the destructor for memstat_cursor objects.
|
||||
*/
|
||||
static int memstatDisconnect(sqlite3_vtab *pVtab){
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Constructor for a new memstat_cursor object.
|
||||
*/
|
||||
static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
memstat_cursor *pCur;
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
pCur->db = ((memstat_vtab*)p)->db;
|
||||
*ppCursor = &pCur->base;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear all the schema names from a cursor
|
||||
*/
|
||||
static void memstatClearSchema(memstat_cursor *pCur){
|
||||
int i;
|
||||
if( pCur->azDb==0 ) return;
|
||||
for(i=0; i<pCur->nDb; i++){
|
||||
sqlite3_free(pCur->azDb[i]);
|
||||
}
|
||||
sqlite3_free(pCur->azDb);
|
||||
pCur->azDb = 0;
|
||||
pCur->nDb = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Fill in the azDb[] array for the cursor.
|
||||
*/
|
||||
static int memstatFindSchemas(memstat_cursor *pCur){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rc;
|
||||
if( pCur->nDb ) return SQLITE_OK;
|
||||
rc = sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
char **az, *z;
|
||||
az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
|
||||
if( az==0 ){
|
||||
memstatClearSchema(pCur);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pCur->azDb = az;
|
||||
z = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
|
||||
if( z==0 ){
|
||||
memstatClearSchema(pCur);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pCur->azDb[pCur->nDb] = z;
|
||||
pCur->nDb++;
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Destructor for a memstat_cursor.
|
||||
*/
|
||||
static int memstatClose(sqlite3_vtab_cursor *cur){
|
||||
memstat_cursor *pCur = (memstat_cursor*)cur;
|
||||
memstatClearSchema(pCur);
|
||||
sqlite3_free(cur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Allowed values for aMemstatColumn[].eType
|
||||
*/
|
||||
#define MSV_GSTAT 0 /* sqlite3_status64() information */
|
||||
#define MSV_DB 1 /* sqlite3_db_status() information */
|
||||
#define MSV_ZIPVFS 2 /* ZIPVFS file-control with 64-bit return */
|
||||
|
||||
/*
|
||||
** An array of quantities that can be measured and reported by
|
||||
** this virtual table
|
||||
*/
|
||||
static const struct MemstatColumns {
|
||||
const char *zName; /* Symbolic name */
|
||||
unsigned char eType; /* Type of interface */
|
||||
unsigned char mNull; /* Bitmask of which columns are NULL */
|
||||
/* 2: dbname, 4: current, 8: hiwtr */
|
||||
int eOp; /* Opcode */
|
||||
} aMemstatColumn[] = {
|
||||
{"MEMORY_USED", MSV_GSTAT, 2, SQLITE_STATUS_MEMORY_USED },
|
||||
{"MALLOC_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_MALLOC_SIZE },
|
||||
{"MALLOC_COUNT", MSV_GSTAT, 2, SQLITE_STATUS_MALLOC_COUNT },
|
||||
{"PAGECACHE_USED", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_USED },
|
||||
{"PAGECACHE_OVERFLOW", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_OVERFLOW },
|
||||
{"PAGECACHE_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_PAGECACHE_SIZE },
|
||||
{"PARSER_STACK", MSV_GSTAT, 6, SQLITE_STATUS_PARSER_STACK },
|
||||
{"DB_LOOKASIDE_USED", MSV_DB, 2, SQLITE_DBSTATUS_LOOKASIDE_USED },
|
||||
{"DB_LOOKASIDE_HIT", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_HIT },
|
||||
{"DB_LOOKASIDE_MISS_SIZE", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE},
|
||||
{"DB_LOOKASIDE_MISS_FULL", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL},
|
||||
{"DB_CACHE_USED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED },
|
||||
#if SQLITE_VERSION_NUMBER >= 3140000
|
||||
{"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED },
|
||||
#endif
|
||||
{"DB_SCHEMA_USED", MSV_DB, 10, SQLITE_DBSTATUS_SCHEMA_USED },
|
||||
{"DB_STMT_USED", MSV_DB, 10, SQLITE_DBSTATUS_STMT_USED },
|
||||
{"DB_CACHE_HIT", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_HIT },
|
||||
{"DB_CACHE_MISS", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_MISS },
|
||||
{"DB_CACHE_WRITE", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_WRITE },
|
||||
#if SQLITE_VERSION_NUMBER >= 3230000
|
||||
{"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL },
|
||||
#endif
|
||||
{"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS },
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
{"ZIPVFS_CACHE_USED", MSV_ZIPVFS, 8, 231454 },
|
||||
{"ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 8, 231455 },
|
||||
{"ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 8, 231456 },
|
||||
{"ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 8, 231457 },
|
||||
{"ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 8, 231458 },
|
||||
{"ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 8, 231459 },
|
||||
#endif /* SQLITE_ENABLE_ZIPVFS */
|
||||
};
|
||||
#define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0]))
|
||||
|
||||
/*
|
||||
** Advance a memstat_cursor to its next row of output.
|
||||
*/
|
||||
static int memstatNext(sqlite3_vtab_cursor *cur){
|
||||
memstat_cursor *pCur = (memstat_cursor*)cur;
|
||||
int i;
|
||||
assert( pCur->iRowid<=MSV_NROW );
|
||||
while(1){
|
||||
i = (int)pCur->iRowid - 1;
|
||||
if( (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){
|
||||
pCur->iRowid++;
|
||||
if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; /* End of the table */
|
||||
pCur->iDb = 0;
|
||||
i++;
|
||||
}
|
||||
pCur->aVal[0] = 0;
|
||||
pCur->aVal[1] = 0;
|
||||
switch( aMemstatColumn[i].eType ){
|
||||
case MSV_GSTAT: {
|
||||
if( sqlite3_libversion_number()>=3010000 ){
|
||||
sqlite3_status64(aMemstatColumn[i].eOp,
|
||||
&pCur->aVal[0], &pCur->aVal[1],0);
|
||||
}else{
|
||||
int xCur, xHiwtr;
|
||||
sqlite3_status(aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
|
||||
pCur->aVal[0] = xCur;
|
||||
pCur->aVal[1] = xHiwtr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSV_DB: {
|
||||
int xCur, xHiwtr;
|
||||
sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
|
||||
pCur->aVal[0] = xCur;
|
||||
pCur->aVal[1] = xHiwtr;
|
||||
break;
|
||||
}
|
||||
case MSV_ZIPVFS: {
|
||||
int rc;
|
||||
rc = sqlite3_file_control(pCur->db, pCur->azDb[pCur->iDb],
|
||||
aMemstatColumn[i].eOp, (void*)&pCur->aVal[0]);
|
||||
if( rc!=SQLITE_OK ) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return values of columns for the row at which the memstat_cursor
|
||||
** is currently pointing.
|
||||
*/
|
||||
static int memstatColumn(
|
||||
sqlite3_vtab_cursor *cur, /* The cursor */
|
||||
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
||||
int iCol /* Which column to return */
|
||||
){
|
||||
memstat_cursor *pCur = (memstat_cursor*)cur;
|
||||
int i;
|
||||
assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW );
|
||||
i = (int)pCur->iRowid - 1;
|
||||
if( (aMemstatColumn[i].mNull & (1<<iCol))!=0 ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
switch( iCol ){
|
||||
case MSV_COLUMN_NAME: {
|
||||
sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC);
|
||||
break;
|
||||
}
|
||||
case MSV_COLUMN_SCHEMA: {
|
||||
sqlite3_result_text(ctx, pCur->azDb[pCur->iDb], -1, 0);
|
||||
break;
|
||||
}
|
||||
case MSV_COLUMN_VALUE: {
|
||||
sqlite3_result_int64(ctx, pCur->aVal[0]);
|
||||
break;
|
||||
}
|
||||
case MSV_COLUMN_HIWTR: {
|
||||
sqlite3_result_int64(ctx, pCur->aVal[1]);
|
||||
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 memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
memstat_cursor *pCur = (memstat_cursor*)cur;
|
||||
*pRowid = pCur->iRowid*1000 + pCur->iDb;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the cursor has been moved off of the last
|
||||
** row of output.
|
||||
*/
|
||||
static int memstatEof(sqlite3_vtab_cursor *cur){
|
||||
memstat_cursor *pCur = (memstat_cursor*)cur;
|
||||
return pCur->iRowid>MSV_NROW;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is called to "rewind" the memstat_cursor object back
|
||||
** to the first row of output. This method is always called at least
|
||||
** once prior to any call to memstatColumn() or memstatRowid() or
|
||||
** memstatEof().
|
||||
*/
|
||||
static int memstatFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
memstat_cursor *pCur = (memstat_cursor *)pVtabCursor;
|
||||
int rc = memstatFindSchemas(pCur);
|
||||
if( rc ) return rc;
|
||||
pCur->iRowid = 0;
|
||||
pCur->iDb = 0;
|
||||
return memstatNext(pVtabCursor);
|
||||
}
|
||||
|
||||
/*
|
||||
** SQLite will invoke this method one or more times while planning a query
|
||||
** that uses the memstat virtual table. This routine needs to create
|
||||
** a query plan for each invocation and compute an estimated cost for that
|
||||
** plan.
|
||||
*/
|
||||
static int memstatBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
pIdxInfo->estimatedCost = (double)500;
|
||||
pIdxInfo->estimatedRows = 500;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This following structure defines all the methods for the
|
||||
** memstat virtual table.
|
||||
*/
|
||||
static sqlite3_module memstatModule = {
|
||||
0, /* iVersion */
|
||||
0, /* xCreate */
|
||||
memstatConnect, /* xConnect */
|
||||
memstatBestIndex, /* xBestIndex */
|
||||
memstatDisconnect, /* xDisconnect */
|
||||
0, /* xDestroy */
|
||||
memstatOpen, /* xOpen - open a cursor */
|
||||
memstatClose, /* xClose - close a cursor */
|
||||
memstatFilter, /* xFilter - configure scan constraints */
|
||||
memstatNext, /* xNext - advance a cursor */
|
||||
memstatEof, /* xEof - check for end of scan */
|
||||
memstatColumn, /* xColumn - read data */
|
||||
memstatRowid, /* xRowid - read data */
|
||||
0, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0, /* xRollbackTo */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
int sqlite3MemstatVtabInit(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
rc = sqlite3_create_module(db, "sqlite_memstat", &memstatModule, 0);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_memstat_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
rc = sqlite3MemstatVtabInit(db);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_CORE */
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) */
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This SQLite extension implements a functions that compute SHA1 hashes.
|
||||
** This SQLite extension implements functions that compute SHA1 hashes.
|
||||
** Two SQL functions are implemented:
|
||||
**
|
||||
** sha1(X)
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This SQLite extension implements a functions that compute SHA1 hashes.
|
||||
** This SQLite extension implements functions that compute SHA3 hashes.
|
||||
** Two SQL functions are implemented:
|
||||
**
|
||||
** sha3(X,SIZE)
|
||||
|
||||
@@ -1295,6 +1295,9 @@ typedef struct Transliteration Transliteration;
|
||||
struct Transliteration {
|
||||
unsigned short int cFrom;
|
||||
unsigned char cTo0, cTo1, cTo2, cTo3;
|
||||
#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
|
||||
unsigned char cTo4;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1708,7 +1711,11 @@ static const Transliteration *spellfixFindTranslit(int c, int *pxTop){
|
||||
** should be freed by the caller.
|
||||
*/
|
||||
static unsigned char *transliterate(const unsigned char *zIn, int nIn){
|
||||
#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
|
||||
unsigned char *zOut = sqlite3_malloc64( nIn*5 + 1 );
|
||||
#else
|
||||
unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 );
|
||||
#endif
|
||||
int c, sz, nOut;
|
||||
if( zOut==0 ) return 0;
|
||||
nOut = 0;
|
||||
@@ -1732,6 +1739,11 @@ static unsigned char *transliterate(const unsigned char *zIn, int nIn){
|
||||
zOut[nOut++] = tbl[x].cTo2;
|
||||
if( tbl[x].cTo3 ){
|
||||
zOut[nOut++] = tbl[x].cTo3;
|
||||
#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
|
||||
if( tbl[x].cTo4 ){
|
||||
zOut[nOut++] = tbl[x].cTo4;
|
||||
}
|
||||
#endif /* SQLITE_SPELLFIX_5BYTE_MAPPINGS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+74
-26
@@ -405,7 +405,8 @@ struct rbu_vfs {
|
||||
sqlite3_vfs *pRealVfs; /* Underlying VFS */
|
||||
sqlite3_mutex *mutex; /* Mutex to protect pMain */
|
||||
sqlite3rbu *pRbu; /* Owner RBU object */
|
||||
rbu_file *pMain; /* Linked list of main db files */
|
||||
rbu_file *pMain; /* List of main db files */
|
||||
rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -434,6 +435,7 @@ struct rbu_file {
|
||||
const char *zWal; /* Wal filename for this main db file */
|
||||
rbu_file *pWalFd; /* Wal file descriptor for this main db */
|
||||
rbu_file *pMainNext; /* Next MAIN_DB file */
|
||||
rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -4030,6 +4032,69 @@ static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add an item to the main-db lists, if it is not already present.
|
||||
**
|
||||
** There are two main-db lists. One for all file descriptors, and one
|
||||
** for all file descriptors with rbu_file.pDb!=0. If the argument has
|
||||
** rbu_file.pDb!=0, then it is assumed to already be present on the
|
||||
** main list and is only added to the pDb!=0 list.
|
||||
*/
|
||||
static void rbuMainlistAdd(rbu_file *p){
|
||||
rbu_vfs *pRbuVfs = p->pRbuVfs;
|
||||
rbu_file *pIter;
|
||||
assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) );
|
||||
sqlite3_mutex_enter(pRbuVfs->mutex);
|
||||
if( p->pRbu==0 ){
|
||||
for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext);
|
||||
p->pMainNext = pRbuVfs->pMain;
|
||||
pRbuVfs->pMain = p;
|
||||
}else{
|
||||
for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){}
|
||||
if( pIter==0 ){
|
||||
p->pMainRbuNext = pRbuVfs->pMainRbu;
|
||||
pRbuVfs->pMainRbu = p;
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(pRbuVfs->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove an item from the main-db lists.
|
||||
*/
|
||||
static void rbuMainlistRemove(rbu_file *p){
|
||||
rbu_file **pp;
|
||||
sqlite3_mutex_enter(p->pRbuVfs->mutex);
|
||||
for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){}
|
||||
if( *pp ) *pp = p->pMainNext;
|
||||
p->pMainNext = 0;
|
||||
for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){}
|
||||
if( *pp ) *pp = p->pMainRbuNext;
|
||||
p->pMainRbuNext = 0;
|
||||
sqlite3_mutex_leave(p->pRbuVfs->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
** Given that zWal points to a buffer containing a wal file name passed to
|
||||
** either the xOpen() or xAccess() VFS method, search the main-db list for
|
||||
** a file-handle opened by the same database connection on the corresponding
|
||||
** database file.
|
||||
**
|
||||
** If parameter bRbu is true, only search for file-descriptors with
|
||||
** rbu_file.pDb!=0.
|
||||
*/
|
||||
static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){
|
||||
rbu_file *pDb;
|
||||
sqlite3_mutex_enter(pRbuVfs->mutex);
|
||||
if( bRbu ){
|
||||
for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){}
|
||||
}else{
|
||||
for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
|
||||
}
|
||||
sqlite3_mutex_leave(pRbuVfs->mutex);
|
||||
return pDb;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an rbu file.
|
||||
*/
|
||||
@@ -4047,17 +4112,14 @@ static int rbuVfsClose(sqlite3_file *pFile){
|
||||
sqlite3_free(p->zDel);
|
||||
|
||||
if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
|
||||
rbu_file **pp;
|
||||
sqlite3_mutex_enter(p->pRbuVfs->mutex);
|
||||
for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext));
|
||||
*pp = p->pMainNext;
|
||||
sqlite3_mutex_leave(p->pRbuVfs->mutex);
|
||||
rbuMainlistRemove(p);
|
||||
rbuUnlockShm(p);
|
||||
p->pReal->pMethods->xShmUnmap(p->pReal, 0);
|
||||
}
|
||||
else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
|
||||
rbuUpdateTempSize(p, 0);
|
||||
}
|
||||
assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p );
|
||||
|
||||
/* Close the underlying file handle */
|
||||
rc = p->pReal->pMethods->xClose(p->pReal);
|
||||
@@ -4316,6 +4378,9 @@ static int rbuVfsFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
}else if( rc==SQLITE_NOTFOUND ){
|
||||
pRbu->pTargetFd = p;
|
||||
p->pRbu = pRbu;
|
||||
if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
|
||||
rbuMainlistAdd(p);
|
||||
}
|
||||
if( p->pWalFd ) p->pWalFd->pRbu = pRbu;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
@@ -4477,20 +4542,6 @@ static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Given that zWal points to a buffer containing a wal file name passed to
|
||||
** either the xOpen() or xAccess() VFS method, return a pointer to the
|
||||
** file-handle opened by the same database connection on the corresponding
|
||||
** database file.
|
||||
*/
|
||||
static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){
|
||||
rbu_file *pDb;
|
||||
sqlite3_mutex_enter(pRbuVfs->mutex);
|
||||
for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
|
||||
sqlite3_mutex_leave(pRbuVfs->mutex);
|
||||
return pDb;
|
||||
}
|
||||
|
||||
/*
|
||||
** A main database named zName has just been opened. The following
|
||||
** function returns a pointer to a buffer owned by SQLite that contains
|
||||
@@ -4569,7 +4620,7 @@ static int rbuVfsOpen(
|
||||
pFd->zWal = rbuMainToWal(zName, flags);
|
||||
}
|
||||
else if( flags & SQLITE_OPEN_WAL ){
|
||||
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName);
|
||||
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
|
||||
if( pDb ){
|
||||
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
|
||||
/* This call is to open a *-wal file. Intead, open the *-oal. This
|
||||
@@ -4621,10 +4672,7 @@ static int rbuVfsOpen(
|
||||
** mutex protected linked list of all such files. */
|
||||
pFile->pMethods = &rbuvfs_io_methods;
|
||||
if( flags & SQLITE_OPEN_MAIN_DB ){
|
||||
sqlite3_mutex_enter(pRbuVfs->mutex);
|
||||
pFd->pMainNext = pRbuVfs->pMain;
|
||||
pRbuVfs->pMain = pFd;
|
||||
sqlite3_mutex_leave(pRbuVfs->mutex);
|
||||
rbuMainlistAdd(pFd);
|
||||
}
|
||||
}else{
|
||||
sqlite3_free(pFd->zDel);
|
||||
@@ -4672,7 +4720,7 @@ static int rbuVfsAccess(
|
||||
** file opened instead.
|
||||
*/
|
||||
if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
|
||||
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath);
|
||||
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1);
|
||||
if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
|
||||
if( *pResOut ){
|
||||
rc = SQLITE_CANTOPEN;
|
||||
|
||||
+109
-21
@@ -106,14 +106,24 @@ typedef float GeoCoord;
|
||||
**
|
||||
** encoding (1 byte) 0=big-endian, 1=little-endian
|
||||
** nvertex (3 bytes) Number of vertexes as a big-endian integer
|
||||
**
|
||||
** Enough space is allocated for 4 coordinates, to work around over-zealous
|
||||
** warnings coming from some compiler (notably, clang). In reality, the size
|
||||
** of each GeoPoly memory allocate is adjusted as necessary so that the
|
||||
** GeoPoly.a[] array at the end is the appropriate size.
|
||||
*/
|
||||
typedef struct GeoPoly GeoPoly;
|
||||
struct GeoPoly {
|
||||
int nVertex; /* Number of vertexes */
|
||||
unsigned char hdr[4]; /* Header for on-disk representation */
|
||||
GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */
|
||||
GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */
|
||||
};
|
||||
|
||||
/* The size of a memory allocation needed for a GeoPoly object sufficient
|
||||
** to hold N coordinate pairs.
|
||||
*/
|
||||
#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))
|
||||
|
||||
/*
|
||||
** State of a parse of a GeoJSON input.
|
||||
*/
|
||||
@@ -138,7 +148,7 @@ static void geopolySwab32(unsigned char *a){
|
||||
|
||||
/* Skip whitespace. Return the next non-whitespace character. */
|
||||
static char geopolySkipSpace(GeoParse *p){
|
||||
while( p->z[0] && safe_isspace(p->z[0]) ) p->z++;
|
||||
while( safe_isspace(p->z[0]) ) p->z++;
|
||||
return p->z[0];
|
||||
}
|
||||
|
||||
@@ -158,7 +168,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
|
||||
if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0;
|
||||
for(;; j++){
|
||||
c = z[j];
|
||||
if( c>='0' && c<='9' ) continue;
|
||||
if( safe_isdigit(c) ) continue;
|
||||
if( c=='.' ){
|
||||
if( z[j-1]=='-' ) return 0;
|
||||
if( seenDP ) return 0;
|
||||
@@ -180,7 +190,17 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
|
||||
break;
|
||||
}
|
||||
if( z[j-1]<'0' ) return 0;
|
||||
if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z);
|
||||
if( pVal ){
|
||||
#ifdef SQLITE_AMALGAMATION
|
||||
/* The sqlite3AtoF() routine is much much faster than atof(), if it
|
||||
** is available */
|
||||
double r;
|
||||
(void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8);
|
||||
*pVal = r;
|
||||
#else
|
||||
*pVal = (GeoCoord)atof((const char*)p->z);
|
||||
#endif
|
||||
}
|
||||
p->z += j;
|
||||
return 1;
|
||||
}
|
||||
@@ -238,12 +258,10 @@ static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){
|
||||
&& s.a[1]==s.a[s.nVertex*2-1]
|
||||
&& (s.z++, geopolySkipSpace(&s)==0)
|
||||
){
|
||||
int nByte;
|
||||
GeoPoly *pOut;
|
||||
int x = 1;
|
||||
s.nVertex--; /* Remove the redundant vertex at the end */
|
||||
nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord);
|
||||
pOut = sqlite3_malloc64( nByte );
|
||||
pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) );
|
||||
x = 1;
|
||||
if( pOut==0 ) goto parse_json_err;
|
||||
pOut->nVertex = s.nVertex;
|
||||
@@ -476,6 +494,64 @@ static void geopolyAreaFunc(
|
||||
}
|
||||
}
|
||||
|
||||
#define GEOPOLY_PI 3.1415926535897932385
|
||||
|
||||
/* Fast approximation for cosine(X) for X between -0.5*pi and 2*pi
|
||||
*/
|
||||
static double geopolyCosine(double r){
|
||||
assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI );
|
||||
if( r>=1.5*GEOPOLY_PI ){
|
||||
r -= 2.0*GEOPOLY_PI;
|
||||
}
|
||||
if( r>=0.5*GEOPOLY_PI ){
|
||||
return -geopolyCosine(r-GEOPOLY_PI);
|
||||
}else{
|
||||
double r2 = r*r;
|
||||
double r3 = r2*r;
|
||||
double r5 = r3*r2;
|
||||
return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Function: geopoly_regular(X,Y,R,N)
|
||||
**
|
||||
** Construct a simple, convex, regular polygon centered at X, Y
|
||||
** with circumradius R and with N sides.
|
||||
*/
|
||||
static void geopolyRegularFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
double x = sqlite3_value_double(argv[0]);
|
||||
double y = sqlite3_value_double(argv[1]);
|
||||
double r = sqlite3_value_double(argv[2]);
|
||||
int n = sqlite3_value_int(argv[3]);
|
||||
int i;
|
||||
GeoPoly *p;
|
||||
|
||||
if( n<3 || r<=0.0 ) return;
|
||||
if( n>1000 ) n = 1000;
|
||||
p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) );
|
||||
if( p==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
i = 1;
|
||||
p->hdr[0] = *(unsigned char*)&i;
|
||||
p->hdr[1] = 0;
|
||||
p->hdr[2] = (n>>8)&0xff;
|
||||
p->hdr[3] = n&0xff;
|
||||
for(i=0; i<n; i++){
|
||||
double rAngle = 2.0*GEOPOLY_PI*i/n;
|
||||
p->a[i*2] = x - r*geopolyCosine(rAngle-0.5*GEOPOLY_PI);
|
||||
p->a[i*2+1] = y + r*geopolyCosine(rAngle);
|
||||
}
|
||||
sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** If pPoly is a polygon, compute its bounding box. Then:
|
||||
**
|
||||
@@ -520,7 +596,7 @@ static GeoPoly *geopolyBBox(
|
||||
if( pRc ) *pRc = SQLITE_OK;
|
||||
if( aCoord==0 ){
|
||||
geopolyBboxFill:
|
||||
pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6);
|
||||
pOut = sqlite3_realloc(p, GEOPOLY_SZ(4));
|
||||
if( pOut==0 ){
|
||||
sqlite3_free(p);
|
||||
if( context ) sqlite3_result_error_nomem(context);
|
||||
@@ -1548,7 +1624,16 @@ static int geopolyUpdate(
|
||||
if( sqlite3_value_nochange(aData[2]) ){
|
||||
sqlite3_bind_null(pUp, 2);
|
||||
}else{
|
||||
sqlite3_bind_value(pUp, 2, aData[2]);
|
||||
GeoPoly *p = 0;
|
||||
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<pRtree->nAux; jj++){
|
||||
@@ -1621,19 +1706,21 @@ static int sqlite3_geopoly_init(sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
static const struct {
|
||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
||||
int nArg;
|
||||
signed char nArg;
|
||||
unsigned char bPure;
|
||||
const char *zName;
|
||||
} aFunc[] = {
|
||||
{ geopolyAreaFunc, 1, "geopoly_area" },
|
||||
{ geopolyBlobFunc, 1, "geopoly_blob" },
|
||||
{ geopolyJsonFunc, 1, "geopoly_json" },
|
||||
{ geopolySvgFunc, -1, "geopoly_svg" },
|
||||
{ geopolyWithinFunc, 2, "geopoly_within" },
|
||||
{ geopolyContainsPointFunc, 3, "geopoly_contains_point" },
|
||||
{ geopolyOverlapFunc, 2, "geopoly_overlap" },
|
||||
{ geopolyDebugFunc, 1, "geopoly_debug" },
|
||||
{ geopolyBBoxFunc, 1, "geopoly_bbox" },
|
||||
{ geopolyXformFunc, 7, "geopoly_xform" },
|
||||
{ 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" },
|
||||
};
|
||||
static const struct {
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
|
||||
@@ -1644,8 +1731,9 @@ static int sqlite3_geopoly_init(sqlite3 *db){
|
||||
};
|
||||
int i;
|
||||
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
||||
int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8;
|
||||
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
|
||||
SQLITE_UTF8, 0,
|
||||
enc, 0,
|
||||
aFunc[i].xFunc, 0, 0);
|
||||
}
|
||||
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
|
||||
|
||||
@@ -586,4 +586,17 @@ SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"')
|
||||
ROLLBACK;
|
||||
.print '</svg>'
|
||||
|
||||
.print '<h1>Regular Polygons</h1>'
|
||||
.print '<svg width="1000" height="200" style="border:1px solid black">'
|
||||
SELECT geopoly_svg(geopoly_regular(100,100,40,3),'style="fill:none;stroke:red;stroke-width:1"');
|
||||
SELECT geopoly_svg(geopoly_regular(200,100,40,4),'style="fill:none;stroke:orange;stroke-width:1"');
|
||||
SELECT geopoly_svg(geopoly_regular(300,100,40,5),'style="fill:none;stroke:green;stroke-width:1"');
|
||||
SELECT geopoly_svg(geopoly_regular(400,100,40,6),'style="fill:none;stroke:blue;stroke-width:1"');
|
||||
SELECT geopoly_svg(geopoly_regular(500,100,40,7),'style="fill:none;stroke:purple;stroke-width:1"');
|
||||
SELECT geopoly_svg(geopoly_regular(600,100,40,8),'style="fill:none;stroke:red;stroke-width:1"');
|
||||
SELECT geopoly_svg(geopoly_regular(700,100,40,10),'style="fill:none;stroke:orange;stroke-width:1"');
|
||||
SELECT geopoly_svg(geopoly_regular(800,100,40,20),'style="fill:none;stroke:green;stroke-width:1"');
|
||||
SELECT geopoly_svg(geopoly_regular(900,100,40,30),'style="fill:none;stroke:blue;stroke-width:1"');
|
||||
.print '</svg>'
|
||||
|
||||
.print '</html>'
|
||||
|
||||
@@ -4866,13 +4866,12 @@ static int sessionChangegroupOutput(
|
||||
sessionAppendByte(&buf, p->op, &rc);
|
||||
sessionAppendByte(&buf, p->bIndirect, &rc);
|
||||
sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
|
||||
if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
|
||||
rc = xOutput(pOut, buf.aBuf, buf.nBuf);
|
||||
buf.nBuf = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
|
||||
rc = xOutput(pOut, buf.aBuf, buf.nBuf);
|
||||
buf.nBuf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
@@ -210,7 +210,7 @@ int sqlite3_user_authenticate(
|
||||
db->auth.nAuthPW = nPW;
|
||||
rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
|
||||
db->auth.authLevel = authLevel;
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
sqlite3ExpirePreparedStatements(db, 0);
|
||||
if( rc ){
|
||||
return rc; /* OOM error, I/O error, etc. */
|
||||
}
|
||||
|
||||
@@ -361,6 +361,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
$(TOP)/ext/misc/csv.c \
|
||||
$(TOP)/ext/misc/eval.c \
|
||||
$(TOP)/ext/misc/explain.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/fuzzer.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C Version\s3.25.0
|
||||
D 2018-09-15T04:01:47.208
|
||||
C Ensure\seach\sALTER\sTABLE\sstatement\smakes\sjust\sa\ssingle\sSQLITE_ALTER_TABLE\scall\nto\sthe\sauthorizer\sfunction.
|
||||
D 2018-10-06T14:33:41.324
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995
|
||||
F Makefile.in 01e95208a78b57d056131382c493c963518f36da4c42b12a97eb324401b3a334
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc a889c6981a222d639f8a548adcfb3183ac07871e27452ace4d810735750f216a
|
||||
F Makefile.msc b946f8806a5d401a299453f61de80dfd1a9df14fa4902b299e6465e3c3134872
|
||||
F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee
|
||||
F VERSION d3e3afdec1165a5e593dcdfffd8e0f33a2b0186067eb51a073ef6c4aec34923d
|
||||
F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
@@ -17,7 +17,7 @@ F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a
|
||||
F autoconf/Makefile.msc 9e73d9abaadb7a4951ddd0e947c5c791770f23bb1e04bfa50b43c01bee0575f2
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
F autoconf/configure.ac 573b98629d6963e6d9bf2897c3f4708fb94ce49897822526ad268181875e1736
|
||||
F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192
|
||||
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
@@ -33,7 +33,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure e80ab4e1f5c63a6979971712d35142ad69ef40da6ee4e4df3456be1a77439124 x
|
||||
F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x
|
||||
F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
@@ -281,10 +281,12 @@ F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f0
|
||||
F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657
|
||||
F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a
|
||||
F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
|
||||
F ext/misc/explain.c 5851a1a4a1bba6e078da4103fcafc84aa54adfd8edbba419f5cf1eba9f000d50
|
||||
F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f83069fd
|
||||
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363
|
||||
F ext/misc/memstat.c 2780712e90765b810645227578438d972b76a089210901bfe9ec88f6a45b0570
|
||||
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
|
||||
F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
@@ -295,10 +297,10 @@ F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6
|
||||
F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
|
||||
F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
|
||||
F ext/misc/series.c c7197db304f7009b08d6459a9de02e7f51ad0e1a3fdacbc1ebf5252a9a346959
|
||||
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
|
||||
F ext/misc/shathree.c 9e960ba50483214c6a7a4b1517f8d8cef799e9db381195178c3fd3ad207e10c0
|
||||
F ext/misc/sha1.c df0a667211baa2c0612d8486acbf6331b9f8633fd4d605c17c7cccd26d59c6bd
|
||||
F ext/misc/shathree.c 22ba7ca84a433d6466a7d05dcc876910b435a715da8cc462517db9351412b8c8
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5
|
||||
F ext/misc/spellfix.c f88ecb2c0294453ce8b7704b211f5350c41b085b38c8e056852e3a08b0f5e484
|
||||
F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74
|
||||
F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
|
||||
F ext/misc/templatevtab.c 8251b31011dd00fc38e739c78c234c930be42b3b274bbe0493b79cd40db02a9e
|
||||
@@ -346,7 +348,7 @@ F ext/rbu/rbusplit.test 69271c790732b28bd465551d80b0a9a3f074e189896ee8490ce56d22
|
||||
F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1
|
||||
F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
|
||||
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
|
||||
F ext/rbu/sqlite3rbu.c f438fea899d15d13ff3e3133242b9e378c37b5a3d76add8c342c68bdd65c6819
|
||||
F ext/rbu/sqlite3rbu.c 71f8c09948d09ec9c5a8dbe7127e8ef61ef0853e698b2650be2485ac7b9c75c8
|
||||
F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
|
||||
F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
@@ -359,7 +361,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
|
||||
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/geopoly.c 415a8ca5dfab54eea779e0bf31a859afb0b869a5147a726df4aec4b57c1bad57
|
||||
F ext/rtree/geopoly.c 04db01e24dca675c5ab75110709aed054325f7474b2f567dd98361c373dcff3c
|
||||
F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
|
||||
@@ -387,7 +389,7 @@ F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
|
||||
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
||||
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F ext/rtree/visual01.txt 17c3afefc208c375607aa82242e97fa79c316e539bcd0b7b3e59344c69445d05
|
||||
F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1d2f94ac66
|
||||
F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
|
||||
F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc
|
||||
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
|
||||
@@ -414,16 +416,16 @@ F ext/session/sessionfault2.test 555a8504de03d59b369ef20209585da5aeb2671dedabc45
|
||||
F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8
|
||||
F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e
|
||||
F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
|
||||
F ext/session/sqlite3session.c 2d29bbd888599b94b2c8b31ff433675e008273a4d225b336508b18e6187fec1d
|
||||
F ext/session/sqlite3session.c ba76c7f01d4c71ab4d134cfda0ba43faae04bff01b8e81d1279a6101c706e3b5
|
||||
F ext/session/sqlite3session.h c01820d5b6e73e86d88008f4d1c1c7dfb83422963018292b864028a0400ceccf
|
||||
F ext/session/test_session.c dba36c6c0153b22501112d3e8882b5c946cf617c955153b6712bd2f8ba1428c0
|
||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
|
||||
F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e629edbe2648
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 1db6df4bff24ed6684917e3fe311ce28f5924d6417c698fe4326f7cadf02df31
|
||||
F main.mk ff82d38126f8f0668b7990e0f1f3dcd74fa2d477c19b2e3feaaba586051e9b48
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -435,17 +437,17 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 3800f24c922dfcab2e7a05b49123e2f9c903c26fccea71a5f9ac765e91949355
|
||||
F src/alter.c 27281c6ed70154c3184d8d775270a61cf3b9cdf169097348abbdbb1f855b2a4f
|
||||
F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
|
||||
F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a
|
||||
F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114
|
||||
F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
|
||||
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173
|
||||
F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
|
||||
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
|
||||
F src/build.c 90571aa2a9eb44e04291ffe9984c814883b9eb371f89898accec384520369597
|
||||
F src/build.c 0b3d422770877d74ee6d54f4c122d82c48f7d04ee3bfb91702e402de7f5c45ac
|
||||
F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387
|
||||
@@ -453,19 +455,19 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
|
||||
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
|
||||
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
|
||||
F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2
|
||||
F src/expr.c 92dc4e104b06d06ffeacbd1a4dc0a520daf37f6156278fb6ece5e90e2ca6b610
|
||||
F src/expr.c 5cee8fb79b1952689af80ed71ed16ad295f29d85de30c7592993b05cf1ec1e06
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
|
||||
F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
|
||||
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
|
||||
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
|
||||
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c c723716f0de7aa0a679300f7d3541c89645f4a9882161cecdb3093fc07f8cc4b
|
||||
F src/insert.c 0a214201afec77880a31a59c33d86b473a160fc5cc31981eab2041ae03d8bf2f
|
||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||
F src/loadext.c 30b140d0e5031924c56f802760506c0a235ced0dff9f3d95119aa86df12856e2
|
||||
F src/main.c 1f54ee71990bfbf4cdc2dc79bdc33e7c4f54eef6922447b4c910f9b5885a4478
|
||||
F src/main.c 6275ece0699a957c4709a7ebe29476f132adbe459d18a6b497e234e4669abf91
|
||||
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@@ -485,33 +487,33 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de
|
||||
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c d8e37bc3af9b15a52c3fecd366c95416251aa8d89481dd56170bad538b421721
|
||||
F src/os_unix.c d483d738183c822cc96ec5539424eee5b9847c882dee57f93b880aaf46a7af19
|
||||
F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b
|
||||
F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963
|
||||
F src/parse.y 4118dbf9c37c410e5c4775c033b1aaf67ac8ff7965df7a4bb429dd5db2dbe374
|
||||
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
|
||||
F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179
|
||||
F src/pcache.c 4196eb6ed3bbf00b80596c8e0b4f50e57eb7d890c19fb27a7354306abb7f983d
|
||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||
F src/pragma.c 79abc65c08d2754048efee3ba99fe91863dfeab0ba699a4439fa5053ec87cf36
|
||||
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/pragma.c a656ff043a03bd94153e6d731a3fbf1bb420207edc969d8fc04b4d2448387901
|
||||
F src/pragma.h 0ea639401ed7b8275c145e3a814119831e296118b545421e76ae2e1516f10ad8
|
||||
F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097
|
||||
F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b
|
||||
F src/resolve.c bc8c79e56439b111e7d9415e44940951f7087e9466c3a9d664558ef0faf31073
|
||||
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
|
||||
F src/select.c ed6192ddd09a97169cb1c6d732b26c0f647b72d5fa8ca401c7ee1180fbbe521a
|
||||
F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f
|
||||
F src/select.c 33aacf1c17c64a00788c779b23d0875dd0d90eb4c08f867ebc31139ef3a67c95
|
||||
F src/shell.c.in 6046da2a92998b8fe004ed4eadd4d7f53d6a8e4d99e5e25a0cc7de6de5f6b26b
|
||||
F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63
|
||||
F src/sqliteInt.h ce34da1aacca2cd4b63803db697f682af95c02d1e1750f240438b0d96a59bdb8
|
||||
F src/sqliteInt.h 75d8266b27c287aeada717a541cf7b7543383fccdb1d7d45a5620f666e864c55
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c e0bf71a6d24b8c23393c000abffab05979bbca2a72d0b0f79260e2cf1527fda5
|
||||
F src/test1.c 31c491ccb536bd9916a084e732ffe783b3c8973f2586d5a56aed0e3a9701dfff
|
||||
F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6
|
||||
F src/test1.c 9bb042e4afedc570f78638993fc9cc1760d897d3b27dd72c20618044b2a8fa5e
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||
@@ -526,7 +528,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
|
||||
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c 6c3f341ece48020c4ddbce055643a91c653283b3a6853c46ea18d22e5c72847d
|
||||
F src/test_config.c 3bbc5e593f308cbff426bb88c9dbf75deab551e5ddcece1251b8d9a40e55aef5
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
|
||||
F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
|
||||
@@ -565,32 +567,32 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b
|
||||
F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f
|
||||
F src/treeview.c 0ef7dc77d6fe03172ba65dddfd3b3c557b7b7e217ca1963b7665beb266a0e2c0
|
||||
F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
|
||||
F src/update.c 345ce35eb1332eb4829857aa8b1f65a614b07dae91d0346c0dc2baacafbcc51b
|
||||
F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274
|
||||
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
||||
F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
|
||||
F src/vdbe.c 80603eb66708c2f27879912a4e9456900e66491c3409ca5e392109114e8f6337
|
||||
F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b
|
||||
F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
|
||||
F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827
|
||||
F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611
|
||||
F src/vdbeaux.c c3c397274380f13db702baa3506ba87379446a4d71135a1177b624f73dd3c830
|
||||
F src/vdbeaux.c 9fe7760a6b9739f21f3e19ad5364330b0f681998fc52c32358243b0060423474
|
||||
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
|
||||
F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641
|
||||
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
|
||||
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
|
||||
F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594
|
||||
F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
|
||||
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
|
||||
F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
|
||||
F src/where.c 2019126801437944c38cc62a99491e98591460b7cc07ab57eb66165f710a289b
|
||||
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
|
||||
F src/wherecode.c 4f88f5b39ad4aeb5bdd47a546d74149bb902ef49ca9f02a45b2a5bd2dd70b6bd
|
||||
F src/whereexpr.c eb462ebe085f6cbb6bdda797a041fbd7e3724586203344043d1088a2117d8e44
|
||||
F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
|
||||
F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
|
||||
F src/where.c a54a3d639bcd751d1474deff58e239b2e475a96e1b8f9178aa7864df8782a4e3
|
||||
F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
|
||||
F src/wherecode.c 3df0a541373d5f999684d761e4bd700d57adb46c7d39da4e77b767b5adcd5893
|
||||
F src/whereexpr.c 1b5a5a7876997f65232bbf19c5c1eeb47eb328b8fa5b28c865543052904cde00
|
||||
F src/window.c a28d8d42c51c7e31136a42f3e245282049d4a9466b36d7bd765772991472df41
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@@ -598,15 +600,18 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
|
||||
F test/alter.test cf28c2f35253d3395cf16334fb9dde1d8c4b035cb7c89204353ee1f47feaec1b
|
||||
F test/alter.test 99e72759d48d6531ac2a9f346b4a9b5fe8f89c67a0fa5e916a3990d3b1fe9d09
|
||||
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
|
||||
F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
|
||||
F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433
|
||||
F test/alterauth.test dc50064e3d57d60cf8708decefed15cfa154242f6d44069858d4c6c9b1aea961
|
||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||
F test/alterauth2.test 9480bdf43499b589ca3f80e38ccb6ac6a00b41c702e89fabc366e4b755a432de
|
||||
F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/altermalloc2.test 0231398534c494401a70a1d06a63d7849cb5b317fcc14228cbdb53039eba7eae
|
||||
F test/altertab.test fe08624ef1554b85c943ac6289f591e2e9984704a6b35b94613af42cc92ba474
|
||||
F test/alterlegacy.test e7c07d605c2a85e7d1696c89e6bf64dfc932fc6d9320fe8708c8f5fc0b524d41
|
||||
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
|
||||
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
|
||||
F test/altertab.test fb8a9a2ab6deb5f860d27675f6213d14ab79b705e0d6350eead4ef3a3f73bf3e
|
||||
F test/altertab2.test 159fd5f7b23ddc841fe678f579f9b1b8e69f44296f3ff75d1b4c155d37a59832
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df
|
||||
F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8
|
||||
@@ -636,8 +641,8 @@ F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be82
|
||||
F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
|
||||
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
|
||||
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
|
||||
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
|
||||
F test/auth.test f0c1a8fc7f07d94e3e26ba7f77eb4a5cedda67b10d9a49275b154ab03749b6c0
|
||||
F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438
|
||||
F test/auth.test 3310d9c08e928beca42d3eadaaf53cef619d9d275f598565a3758a21ce63138e
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
|
||||
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
|
||||
@@ -692,9 +697,9 @@ F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
|
||||
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
|
||||
F test/capi2.test 34a1a9a96d543a2ec2c209696b11b164444f57253b1f2cba1c2e53fadede6c7b
|
||||
F test/capi3.test 36f5c859c91a9bb0075d6ddcfcf2476cad629b09f7bfd135776fb94b06c04706
|
||||
F test/capi3.test b299c89d80891c6c9b7f0e4b199df002b8b9f11c19f07d4a6eb7b325f1244de0
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098
|
||||
F test/capi3c.test e853c6c1f9a596e0bc58153be08706813bf5795d479d6f81581e3bda3f9d0909
|
||||
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857
|
||||
@@ -748,7 +753,7 @@ F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
|
||||
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
|
||||
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
|
||||
F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
|
||||
F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219
|
||||
F test/crash5.test f14ff37eddc41991be4eb63568f86caa306fd9962a0ae3750db8836777bb7aae
|
||||
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
|
||||
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
|
||||
F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
|
||||
@@ -958,13 +963,13 @@ F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
|
||||
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c 8074a35ed4ec3735a5e144b7e0e9123d9821a92281756c1a40d43e302dd79243
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2
|
||||
F test/fuzzdata5.db 7a3467a24e7112c1f1041ae9ad1e7060c2074da82d420ce786953cc3d3dd20b5
|
||||
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
|
||||
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
@@ -989,7 +994,7 @@ F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
||||
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
|
||||
F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
|
||||
F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9
|
||||
F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758
|
||||
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
|
||||
F test/incrvacuum.test b729aab1d4983037da57e66c20dfd7458561a85626dcf824f60175e35f4ce152
|
||||
@@ -1007,7 +1012,7 @@ F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
|
||||
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
|
||||
F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
|
||||
F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
|
||||
F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216
|
||||
F test/indexexpr2.test d8f56b6cf4e5663486129bc18c6bde4cef9f8876942b001bfdd692a2b1a42668
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a
|
||||
@@ -1051,7 +1056,7 @@ F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/like3.test cf0ff2d06c9d8456283aeff405b911642298441206306aeaeaa93973233b1195
|
||||
F test/like3.test 430691e6057e11a59e934be74c06b85605b80061d45af5714d52886a811efeb7
|
||||
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
|
||||
F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e
|
||||
F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9
|
||||
@@ -1064,7 +1069,7 @@ F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
|
||||
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
|
||||
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
|
||||
F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
|
||||
F test/lookaside.test b17c99ae3aef96a8c9fa6f6be33cc75b93d657cb791d3827302b6835b71941f7
|
||||
F test/lookaside.test 5a828e7256f1ee4da8e1bdaa03373a3ccdb0f1ff98dfa82e9b76cb41a45b1083
|
||||
F test/main.test 6bbb3999fd461eb8fb335cbab97409a3d7f91bbb8da60635e8be3e4a04a77772
|
||||
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test 18dd1c4188c81ca79cf123527c71b19ee0c31feb9947fdffb0dc6ceb1436816a
|
||||
@@ -1090,6 +1095,7 @@ F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c0837
|
||||
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
|
||||
F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
|
||||
F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
|
||||
F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0fe5e411264c8a9
|
||||
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
|
||||
@@ -1165,7 +1171,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test fdcb2d733fc21396e0300206023795463ba0d0ee5eda2042863b044933391da3
|
||||
F test/permutations.test 8749e292c8f7e98072049543da8c0fe60e1625f0a9f49068623060984c176bbf
|
||||
F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30
|
||||
F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
@@ -1173,7 +1179,7 @@ F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
||||
F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c
|
||||
F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd
|
||||
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
@@ -1191,7 +1197,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl 7e90ec5d2854d80e2574f70df834ef9cae705d21fe43a19dc217a3ce33a3798c x
|
||||
F test/releasetest.tcl c5b474f9880073fc3b69729ee05d5284653a9ee101af572204917d9dcb1d9015 x
|
||||
F test/resetdb.test 684a6ffde5a5141bba79f3101981cc38dcfc3403f61e643b7b3aa68bef0b8408
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
@@ -1261,7 +1267,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
|
||||
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test 707c03fbd07ac506cfb6fa09da4ee22e2b50453c3db2f404694116eb990168f3
|
||||
F test/shell1.test d2bf5daeb6f449f0169c9ef3094db17a16a02199c5dcf1a635a3e79b07eb0edd
|
||||
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
|
||||
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
|
||||
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
|
||||
@@ -1329,11 +1335,11 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
|
||||
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
|
||||
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51
|
||||
F test/tabfunc01.test 5ddfdcda81f362d54cf301a65678edea2a02a570760a4c88051fc2730aafcd81
|
||||
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 5337e8890b96dad1ee541b15fbeec32e6bac2fe7fa096f91089057385aadba9b
|
||||
F test/tclsqlite.test dca8aa30d84175e7d8c8fc43d3ffa11fa56e23fbdac2679d03833a0f326edf34
|
||||
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
|
||||
F test/tempdb2.test 4749545409c6d7438b435c3f05cdd139cf4145a954a6908d19e3443ffd8724b3
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
@@ -1341,7 +1347,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl d5138d226cc2aaacb6934cdd79acaa5edd17cad862482895b833bbf62c49aca0
|
||||
F test/tester.tcl fa5656391e3b477508abe12b3b81f019b2e71397399ab38a2f32d8d7f3bf8e56
|
||||
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1514,7 +1520,7 @@ F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
|
||||
F test/trigger7.test 93cfa9b48ab9104b2b3d87bc544ac8021405643e36f23ee84635fbfaf9b8fef5
|
||||
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
||||
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
|
||||
F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
|
||||
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
|
||||
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
|
||||
F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
|
||||
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
|
||||
@@ -1554,7 +1560,7 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2
|
||||
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
|
||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test 226fb71e37be61854f3a01929ae0a7e14584d6aef5c459bb0a22318f0b6dd210
|
||||
F test/view.test 71e1bf4c0e2e0d37c84d7db5b33cd47eb4a7662c19d93ede4112b350b186f61f
|
||||
F test/vtab1.test 8f91b9538d1404c3932293a588c4344218a0c94792d4289bb55e41020e7b3fff
|
||||
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
|
||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||
@@ -1574,7 +1580,7 @@ F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be4
|
||||
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
|
||||
F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f
|
||||
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_err.test 1c476cac24c9c730f83cd7c8bf66482a30151be08d36a2283f87fc38a2dacbb1
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
|
||||
F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918
|
||||
@@ -1639,17 +1645,17 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/window1.test 7cb260079cd88d6d6177b0f592686f2bbbc2d10f4f415c8a37cd153eb83c87ca
|
||||
F test/window1.test 474bef1a6ac291755e51d1f9458dc11117c1870ac5e08b4d3938649b215f8334
|
||||
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
|
||||
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
|
||||
F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823
|
||||
F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98
|
||||
F test/window4.tcl 871364059b7d320d556ec6ef804d604a4e8cc1547a3102c5d56067371bb200af
|
||||
F test/window4.test 323b118eb592932036388643ca6dcaead87f699bbea2984bbca49ba4ad6c2509
|
||||
F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb
|
||||
F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62
|
||||
F test/window5.test 8187f46597c90b73e8f96659e893353cbda337479cc582f7a488eab351ba08d3
|
||||
F test/window6.test 7574778c79cae89f1781df237bf9ff5063886deca91a36efc53934315f0e7612
|
||||
F test/window6.test 5eae4ae7a590ccf1e605880969ca0bad3955616ac91cad3031baea38748badb3
|
||||
F test/windowfault.test 23abad97b72c6f609002255ddd41ef5c8922408f918f9b98ad6005ab316e482f
|
||||
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
|
||||
F test/with1.test 2465d98ffce80d00553ac7135697c18b0369275b6ecc750daa2af320b8c812ca
|
||||
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
|
||||
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
|
||||
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
|
||||
@@ -1698,7 +1704,7 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
|
||||
F tool/mkpragmatab.tcl fc895d5a40e725b19b866b058b3994bfc45db3e7fef40db9e6c6fd921bf8a337
|
||||
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
|
||||
F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
@@ -1765,10 +1771,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 7921dd91a1745aa79ea157b91b22c380e9331800050861ee6ca1f0efa0a97628
|
||||
R cd1dec78fa9aef334fc060d76165a055
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.25.0 *
|
||||
U drh
|
||||
Z 7af864335c95fcb0688b7f5b8af875de
|
||||
P ff10d2c7de430c88167b1e6e4f5307eee5d69e22c8d24b2ef4fcb3aea25a92e1
|
||||
R 39888c280f11777f99cfb547c69d2aa6
|
||||
T *branch * alter-auth-callbacks
|
||||
T *sym-alter-auth-callbacks *
|
||||
T -sym-trunk *
|
||||
U dan
|
||||
Z 0aa866dd88e8ea8e5fcdd3c207d5f8ef
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
b63af6c3bd33152742648d5d2e8dc5d5fcbcdd27df409272b6aea00a6f761760
|
||||
dac285474a4b09cb004b797567d050952cb12b952e5688bc4a6e4599faa21565
|
||||
+73
-35
@@ -98,6 +98,9 @@ void sqlite3AlterRenameTable(
|
||||
Vdbe *v;
|
||||
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
|
||||
u32 savedDbFlags; /* Saved value of db->mDbFlags */
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
sqlite3_xauth xAuth = db->xAuth;
|
||||
#endif
|
||||
|
||||
savedDbFlags = db->mDbFlags;
|
||||
if( NEVER(db->mallocFailed) ) goto exit_rename_table;
|
||||
@@ -145,6 +148,7 @@ void sqlite3AlterRenameTable(
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
|
||||
goto exit_rename_table;
|
||||
}
|
||||
db->xAuth = 0;
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
@@ -169,20 +173,6 @@ void sqlite3AlterRenameTable(
|
||||
goto exit_rename_table;
|
||||
}
|
||||
|
||||
/* If this is a virtual table, invoke the xRename() function if
|
||||
** one is defined. The xRename() callback will modify the names
|
||||
** of any resources used by the v-table implementation (including other
|
||||
** SQLite tables) that are identified by the name of the virtual table.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( pVTab ){
|
||||
int i = ++pParse->nMem;
|
||||
sqlite3VdbeLoadString(v, i, zName);
|
||||
sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
|
||||
sqlite3MayAbort(pParse);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* figure out how many UTF-8 characters are in zName */
|
||||
zTabName = pTab->zName;
|
||||
nTabName = sqlite3Utf8CharLen(zTabName, -1);
|
||||
@@ -240,10 +230,27 @@ void sqlite3AlterRenameTable(
|
||||
, zDb, zTabName, zName, zTabName, zDb, zName);
|
||||
}
|
||||
|
||||
/* If this is a virtual table, invoke the xRename() function if
|
||||
** one is defined. The xRename() callback will modify the names
|
||||
** of any resources used by the v-table implementation (including other
|
||||
** SQLite tables) that are identified by the name of the virtual table.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( pVTab ){
|
||||
int i = ++pParse->nMem;
|
||||
sqlite3VdbeLoadString(v, i, zName);
|
||||
sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
|
||||
sqlite3MayAbort(pParse);
|
||||
}
|
||||
#endif
|
||||
|
||||
renameReloadSchema(pParse, iDb);
|
||||
renameTestSchema(pParse, zDb, iDb==1);
|
||||
|
||||
exit_rename_table:
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
db->xAuth = xAuth;
|
||||
#endif
|
||||
sqlite3SrcListDelete(db, pSrc);
|
||||
sqlite3DbFree(db, zName);
|
||||
db->mDbFlags = savedDbFlags;
|
||||
@@ -347,6 +354,10 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
||||
if( zCol ){
|
||||
char *zEnd = &zCol[pColDef->n-1];
|
||||
u32 savedDbFlags = db->mDbFlags;
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
sqlite3_xauth xAuth = db->xAuth;
|
||||
db->xAuth = 0;
|
||||
#endif
|
||||
while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
|
||||
*zEnd-- = '\0';
|
||||
}
|
||||
@@ -360,6 +371,9 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
||||
);
|
||||
sqlite3DbFree(db, zCol);
|
||||
db->mDbFlags = savedDbFlags;
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
db->xAuth = xAuth;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Make sure the schema version is at least 3. But do not upgrade
|
||||
@@ -520,6 +534,9 @@ void sqlite3AlterRenameColumn(
|
||||
const char *zDb; /* Name of schema containing the table */
|
||||
int iSchema; /* Index of the schema */
|
||||
int bQuote; /* True to quote the new name */
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
sqlite3_xauth xAuth = db->xAuth;
|
||||
#endif
|
||||
|
||||
/* Locate the table to be altered */
|
||||
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
|
||||
@@ -539,6 +556,7 @@ void sqlite3AlterRenameColumn(
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
|
||||
goto exit_rename_column;
|
||||
}
|
||||
db->xAuth = 0;
|
||||
#endif
|
||||
|
||||
/* Make sure the old name really is a column name in the table to be
|
||||
@@ -584,6 +602,9 @@ void sqlite3AlterRenameColumn(
|
||||
renameTestSchema(pParse, zDb, iSchema==1);
|
||||
|
||||
exit_rename_column:
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
db->xAuth = xAuth;
|
||||
#endif
|
||||
sqlite3SrcListDelete(db, pSrc);
|
||||
sqlite3DbFree(db, zOld);
|
||||
sqlite3DbFree(db, zNew);
|
||||
@@ -803,7 +824,7 @@ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
|
||||
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
|
||||
}else if( pExpr->op==TK_COLUMN
|
||||
&& pExpr->iColumn==p->iCol
|
||||
&& p->pTab==pExpr->pTab
|
||||
&& p->pTab==pExpr->y.pTab
|
||||
){
|
||||
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
|
||||
}
|
||||
@@ -1061,9 +1082,14 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
|
||||
db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName
|
||||
);
|
||||
pParse->eTriggerOp = pNew->op;
|
||||
/* ALWAYS() because if the table of the trigger does not exist, the
|
||||
** error would have been hit before this point */
|
||||
if( ALWAYS(pParse->pTriggerTab) ){
|
||||
rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
|
||||
}
|
||||
|
||||
/* Resolve symbols in WHEN clause */
|
||||
if( pNew->pWhen ){
|
||||
if( rc==SQLITE_OK && pNew->pWhen ){
|
||||
rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen);
|
||||
}
|
||||
|
||||
@@ -1076,7 +1102,7 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
|
||||
Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb);
|
||||
if( pTarget==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
}else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){
|
||||
SrcList sSrc;
|
||||
memset(&sSrc, 0, sizeof(sSrc));
|
||||
sSrc.nSrc = 1;
|
||||
@@ -1341,8 +1367,8 @@ renameColumnFunc_done:
|
||||
*/
|
||||
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
|
||||
RenameCtx *p = pWalker->u.pRename;
|
||||
if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){
|
||||
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab);
|
||||
if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){
|
||||
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab);
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
@@ -1422,17 +1448,20 @@ static void renameTableFunc(
|
||||
rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
int isLegacy = (db->flags & SQLITE_LegacyAlter);
|
||||
if( sParse.pNewTable ){
|
||||
Table *pTab = sParse.pNewTable;
|
||||
|
||||
if( pTab->pSelect ){
|
||||
NameContext sNC;
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
sNC.pParse = &sParse;
|
||||
if( isLegacy==0 ){
|
||||
NameContext sNC;
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
sNC.pParse = &sParse;
|
||||
|
||||
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
|
||||
if( sParse.nErr ) rc = sParse.rc;
|
||||
sqlite3WalkSelect(&sWalker, pTab->pSelect);
|
||||
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
|
||||
if( sParse.nErr ) rc = sParse.rc;
|
||||
sqlite3WalkSelect(&sWalker, pTab->pSelect);
|
||||
}
|
||||
}else{
|
||||
/* Modify any FK definitions to point to the new table. */
|
||||
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||
@@ -1451,7 +1480,9 @@ static void renameTableFunc(
|
||||
** "CREATE [VIRTUAL] TABLE" bit. */
|
||||
if( sqlite3_stricmp(zOld, pTab->zName)==0 ){
|
||||
sCtx.pTab = pTab;
|
||||
sqlite3WalkExprList(&sWalker, pTab->pCheck);
|
||||
if( isLegacy==0 ){
|
||||
sqlite3WalkExprList(&sWalker, pTab->pCheck);
|
||||
}
|
||||
renameTokenFind(&sParse, &sCtx, pTab->zName);
|
||||
}
|
||||
}
|
||||
@@ -1459,7 +1490,9 @@ static void renameTableFunc(
|
||||
|
||||
else if( sParse.pNewIndex ){
|
||||
renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName);
|
||||
sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
|
||||
if( isLegacy==0 ){
|
||||
sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
@@ -1472,12 +1505,14 @@ static void renameTableFunc(
|
||||
renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table);
|
||||
}
|
||||
|
||||
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
|
||||
if( rc==SQLITE_OK ){
|
||||
renameWalkTrigger(&sWalker, pTrigger);
|
||||
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
|
||||
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
|
||||
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
|
||||
if( isLegacy==0 ){
|
||||
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
|
||||
if( rc==SQLITE_OK ){
|
||||
renameWalkTrigger(&sWalker, pTrigger);
|
||||
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
|
||||
if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
|
||||
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1535,6 +1570,7 @@ static void renameTableTest(
|
||||
char const *zDb = (const char*)sqlite3_value_text(argv[0]);
|
||||
char const *zInput = (const char*)sqlite3_value_text(argv[1]);
|
||||
int bTemp = sqlite3_value_int(argv[4]);
|
||||
int isLegacy = (db->flags & SQLITE_LegacyAlter);
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
sqlite3_xauth xAuth = db->xAuth;
|
||||
@@ -1547,7 +1583,7 @@ static void renameTableTest(
|
||||
Parse sParse;
|
||||
rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sParse.pNewTable && sParse.pNewTable->pSelect ){
|
||||
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
|
||||
NameContext sNC;
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
sNC.pParse = &sParse;
|
||||
@@ -1556,7 +1592,9 @@ static void renameTableTest(
|
||||
}
|
||||
|
||||
else if( sParse.pNewTrigger ){
|
||||
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
|
||||
if( isLegacy==0 ){
|
||||
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
|
||||
int i2 = sqlite3FindDbName(db, zDb);
|
||||
|
||||
@@ -151,6 +151,7 @@ void sqlite3AuthRead(
|
||||
int iCol; /* Index of column in table */
|
||||
|
||||
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
|
||||
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
|
||||
if( db->xAuth==0 ) return;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
|
||||
if( iDb<0 ){
|
||||
@@ -207,6 +208,7 @@ int sqlite3AuthCheck(
|
||||
/* Don't do any authorization checks if the database is initialising
|
||||
** or if the parser is being invoked from within sqlite3_declare_vtab.
|
||||
*/
|
||||
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
|
||||
if( db->init.busy || IN_SPECIAL_PARSE ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
+7
-4
@@ -1771,10 +1771,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
}
|
||||
}
|
||||
|
||||
/* The remaining transformations only apply to b-tree tables, not to
|
||||
** virtual tables */
|
||||
if( IN_DECLARE_VTAB ) return;
|
||||
|
||||
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
|
||||
** into BTREE_BLOBKEY.
|
||||
*/
|
||||
@@ -2287,6 +2283,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
assert( pTable->pSelect );
|
||||
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
|
||||
if( pSel ){
|
||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||
u8 eParseMode = pParse->eParseMode;
|
||||
pParse->eParseMode = PARSE_MODE_NORMAL;
|
||||
#endif
|
||||
n = pParse->nTab;
|
||||
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
|
||||
pTable->nCol = -1;
|
||||
@@ -2332,6 +2332,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
sqlite3DeleteTable(db, pSelTab);
|
||||
sqlite3SelectDelete(db, pSel);
|
||||
db->lookaside.bDisable--;
|
||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||
pParse->eParseMode = eParseMode;
|
||||
#endif
|
||||
} else {
|
||||
nErr++;
|
||||
}
|
||||
|
||||
+51
-51
@@ -58,8 +58,8 @@ char sqlite3ExprAffinity(Expr *pExpr){
|
||||
return sqlite3AffinityType(pExpr->u.zToken, 0);
|
||||
}
|
||||
#endif
|
||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
|
||||
return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
|
||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
|
||||
return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
||||
}
|
||||
if( op==TK_SELECT_COLUMN ){
|
||||
assert( pExpr->pLeft->flags&EP_xIsSelect );
|
||||
@@ -143,13 +143,13 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
if( p->flags & EP_Generic ) break;
|
||||
if( (op==TK_AGG_COLUMN || op==TK_COLUMN
|
||||
|| op==TK_REGISTER || op==TK_TRIGGER)
|
||||
&& p->pTab!=0
|
||||
&& p->y.pTab!=0
|
||||
){
|
||||
/* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
|
||||
/* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
|
||||
** a TK_COLUMN but was previously evaluated and cached in a register */
|
||||
int j = p->iColumn;
|
||||
if( j>=0 ){
|
||||
const char *zColl = p->pTab->aCol[j].zColl;
|
||||
const char *zColl = p->y.pTab->aCol[j].zColl;
|
||||
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
|
||||
}
|
||||
break;
|
||||
@@ -1052,6 +1052,10 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
|
||||
assert( p!=0 );
|
||||
/* Sanity check: Assert that the IntValue is non-negative if it exists */
|
||||
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
|
||||
|
||||
assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed );
|
||||
assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced)
|
||||
|| p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) );
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
assert( p->pLeft==0 );
|
||||
@@ -1070,8 +1074,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
|
||||
}else{
|
||||
sqlite3ExprListDelete(db, p->x.pList);
|
||||
}
|
||||
if( !ExprHasProperty(p, EP_Reduced) ){
|
||||
sqlite3WindowDelete(db, p->pWin);
|
||||
if( ExprHasProperty(p, EP_WinFunc) ){
|
||||
assert( p->op==TK_FUNCTION );
|
||||
sqlite3WindowDelete(db, p->y.pWin);
|
||||
}
|
||||
}
|
||||
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
|
||||
@@ -1135,7 +1140,7 @@ static int dupedExprStructSize(Expr *p, int flags){
|
||||
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
|
||||
if( 0==flags || p->op==TK_SELECT_COLUMN
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
|| p->pWin
|
||||
|| ExprHasProperty(p, EP_WinFunc)
|
||||
#endif
|
||||
){
|
||||
nSize = EXPR_FULLSIZE;
|
||||
@@ -1265,7 +1270,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
}
|
||||
|
||||
/* Fill in pNew->pLeft and pNew->pRight. */
|
||||
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
|
||||
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){
|
||||
zAlloc += dupedExprNodeSize(p, dupFlags);
|
||||
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
|
||||
pNew->pLeft = p->pLeft ?
|
||||
@@ -1273,17 +1278,16 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
pNew->pRight = p->pRight ?
|
||||
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( ExprHasProperty(p, EP_WinFunc) ){
|
||||
pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin);
|
||||
assert( ExprHasProperty(pNew, EP_WinFunc) );
|
||||
}
|
||||
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
||||
if( pzBuffer ){
|
||||
*pzBuffer = zAlloc;
|
||||
}
|
||||
}else{
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
|
||||
pNew->pWin = 0;
|
||||
}else{
|
||||
pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
||||
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
|
||||
if( pNew->op==TK_SELECT_COLUMN ){
|
||||
pNew->pLeft = p->pLeft;
|
||||
@@ -2089,8 +2093,8 @@ int sqlite3ExprCanBeNull(const Expr *p){
|
||||
return 0;
|
||||
case TK_COLUMN:
|
||||
return ExprHasProperty(p, EP_CanBeNull) ||
|
||||
p->pTab==0 || /* Reference to column of index on expression */
|
||||
(p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
|
||||
p->y.pTab==0 || /* Reference to column of index on expression */
|
||||
(p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0);
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -3378,7 +3382,7 @@ expr_code_doover:
|
||||
** constant.
|
||||
*/
|
||||
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
|
||||
int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
|
||||
int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
||||
if( aff!=SQLITE_AFF_BLOB ){
|
||||
static const char zAff[] = "B\000C\000D\000E";
|
||||
assert( SQLITE_AFF_BLOB=='A' );
|
||||
@@ -3402,7 +3406,7 @@ expr_code_doover:
|
||||
iTab = pParse->iSelfTab - 1;
|
||||
}
|
||||
}
|
||||
return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
|
||||
return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
|
||||
pExpr->iColumn, iTab, target,
|
||||
pExpr->op2);
|
||||
}
|
||||
@@ -3616,8 +3620,8 @@ expr_code_doover:
|
||||
CollSeq *pColl = 0; /* A collating sequence */
|
||||
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){
|
||||
return pExpr->pWin->regResult;
|
||||
if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
||||
return pExpr->y.pWin->regResult;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3860,7 +3864,7 @@ expr_code_doover:
|
||||
** p1==1 -> old.a p1==4 -> new.a
|
||||
** p1==2 -> old.b p1==5 -> new.b
|
||||
*/
|
||||
Table *pTab = pExpr->pTab;
|
||||
Table *pTab = pExpr->y.pTab;
|
||||
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
|
||||
|
||||
assert( pExpr->iTable==0 || pExpr->iTable==1 );
|
||||
@@ -3871,7 +3875,7 @@ expr_code_doover:
|
||||
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
|
||||
VdbeComment((v, "r[%d]=%s.%s", target,
|
||||
(pExpr->iTable ? "new" : "old"),
|
||||
(pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
|
||||
(pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName)
|
||||
));
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
@@ -4722,6 +4726,20 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
|
||||
if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
|
||||
if( pA->op==TK_FUNCTION ){
|
||||
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
/* Justification for the assert():
|
||||
** window functions have p->op==TK_FUNCTION but aggregate functions
|
||||
** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
|
||||
** function and a window function should have failed before reaching
|
||||
** this point. And, it is not possible to have a window function and
|
||||
** a scalar function with the same name and number of arguments. So
|
||||
** if we reach this point, either A and B both window functions or
|
||||
** neither are a window functions. */
|
||||
assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) );
|
||||
if( ExprHasProperty(pA,EP_WinFunc) ){
|
||||
if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2;
|
||||
}
|
||||
#endif
|
||||
}else if( pA->op==TK_COLLATE ){
|
||||
if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
|
||||
}else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
|
||||
@@ -4741,21 +4759,6 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
|
||||
if( pA->iTable!=pB->iTable
|
||||
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
/* Justification for the assert():
|
||||
** window functions have p->op==TK_FUNCTION but aggregate functions
|
||||
** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
|
||||
** function and a window function should have failed before reaching
|
||||
** this point. And, it is not possible to have a window function and
|
||||
** a scalar function with the same name and number of arguments. So
|
||||
** if we reach this point, either A and B both window functions or
|
||||
** neither are a window functions. */
|
||||
assert( (pA->pWin==0)==(pB->pWin==0) );
|
||||
|
||||
if( pA->pWin!=0 ){
|
||||
if( sqlite3WindowCompare(pParse,pA->pWin,pB->pWin)!=0 ) return 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4846,18 +4849,15 @@ int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
|
||||
/*
|
||||
** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
|
||||
** If the expression node requires that the table at pWalker->iCur
|
||||
** have a non-NULL column, then set pWalker->eCode to 1 and abort.
|
||||
** have one or more non-NULL column, then set pWalker->eCode to 1 and abort.
|
||||
**
|
||||
** This routine controls an optimization. False positives (setting
|
||||
** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives
|
||||
** (never setting pWalker->eCode) is a harmless missed optimization.
|
||||
*/
|
||||
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
|
||||
/* This routine is only called for WHERE clause expressions and so it
|
||||
** cannot have any TK_AGG_COLUMN entries because those are only found
|
||||
** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause,
|
||||
** but that is an illegal construct and the query will be rejected at
|
||||
** a later stage of processing, so the TK_AGG_FUNCTION case does not
|
||||
** need to be considered here. */
|
||||
assert( pExpr->op!=TK_AGG_COLUMN );
|
||||
testcase( pExpr->op==TK_AGG_COLUMN );
|
||||
testcase( pExpr->op==TK_AGG_FUNCTION );
|
||||
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
|
||||
switch( pExpr->op ){
|
||||
case TK_ISNOT:
|
||||
@@ -4899,8 +4899,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pExpr->op==TK_LE );
|
||||
testcase( pExpr->op==TK_GT );
|
||||
testcase( pExpr->op==TK_GE );
|
||||
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
|
||||
|| (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
|
||||
if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab))
|
||||
|| (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab))
|
||||
){
|
||||
return WRC_Prune;
|
||||
}
|
||||
@@ -5131,7 +5131,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
|
||||
){
|
||||
pCol = &pAggInfo->aCol[k];
|
||||
pCol->pTab = pExpr->pTab;
|
||||
pCol->pTab = pExpr->y.pTab;
|
||||
pCol->iTable = pExpr->iTable;
|
||||
pCol->iColumn = pExpr->iColumn;
|
||||
pCol->iMem = ++pParse->nMem;
|
||||
|
||||
+1
-1
@@ -502,7 +502,7 @@ static Expr *exprTableColumn(
|
||||
){
|
||||
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
|
||||
if( pExpr ){
|
||||
pExpr->pTab = pTab;
|
||||
pExpr->y.pTab = pTab;
|
||||
pExpr->iTable = iCursor;
|
||||
pExpr->iColumn = iCol;
|
||||
}
|
||||
|
||||
+25
-9
@@ -1126,14 +1126,15 @@ insert_cleanup:
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged()
|
||||
** Meanings of bits in of pWalker->eCode for
|
||||
** sqlite3ExprReferencesUpdatedColumn()
|
||||
*/
|
||||
#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */
|
||||
#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */
|
||||
|
||||
/* This is the Walker callback from checkConstraintUnchanged(). Set
|
||||
** bit 0x01 of pWalker->eCode if
|
||||
** pWalker->eCode to 0 if this expression node references any of the
|
||||
/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn().
|
||||
* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this
|
||||
** expression node references any of the
|
||||
** columns that are being modifed by an UPDATE statement.
|
||||
*/
|
||||
static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
|
||||
@@ -1155,12 +1156,21 @@ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
|
||||
** only columns that are modified by the UPDATE are those for which
|
||||
** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true.
|
||||
**
|
||||
** Return true if CHECK constraint pExpr does not use any of the
|
||||
** Return true if CHECK constraint pExpr uses any of the
|
||||
** changing columns (or the rowid if it is changing). In other words,
|
||||
** return true if this CHECK constraint can be skipped when validating
|
||||
** return true if this CHECK constraint must be validated for
|
||||
** the new row in the UPDATE statement.
|
||||
**
|
||||
** 2018-09-15: pExpr might also be an expression for an index-on-expressions.
|
||||
** The operation of this routine is the same - return true if an only if
|
||||
** the expression uses one or more of columns identified by the second and
|
||||
** third arguments.
|
||||
*/
|
||||
static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
|
||||
int sqlite3ExprReferencesUpdatedColumn(
|
||||
Expr *pExpr, /* The expression to be checked */
|
||||
int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */
|
||||
int chngRowid /* True if UPDATE changes the rowid */
|
||||
){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.eCode = 0;
|
||||
@@ -1175,7 +1185,7 @@ static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
|
||||
testcase( w.eCode==CKCNSTRNT_COLUMN );
|
||||
testcase( w.eCode==CKCNSTRNT_ROWID );
|
||||
testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) );
|
||||
return !w.eCode;
|
||||
return w.eCode!=0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1381,7 +1391,13 @@ void sqlite3GenerateConstraintChecks(
|
||||
for(i=0; i<pCheck->nExpr; i++){
|
||||
int allOk;
|
||||
Expr *pExpr = pCheck->a[i].pExpr;
|
||||
if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue;
|
||||
if( aiChng
|
||||
&& !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng)
|
||||
){
|
||||
/* The check constraints do not reference any of the columns being
|
||||
** updated so there is no point it verifying the check constraint */
|
||||
continue;
|
||||
}
|
||||
allOk = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
|
||||
|
||||
@@ -3021,6 +3021,7 @@ static int openDatabase(
|
||||
db->nDb = 2;
|
||||
db->magic = SQLITE_MAGIC_BUSY;
|
||||
db->aDb = db->aDbStatic;
|
||||
db->lookaside.bDisable = 1;
|
||||
|
||||
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
|
||||
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
|
||||
|
||||
+63
-57
@@ -136,12 +136,10 @@
|
||||
#define SQLITE_FSFLAGS_IS_MSDOS 0x1
|
||||
|
||||
/*
|
||||
** If we are to be thread-safe, include the pthreads header and define
|
||||
** the SQLITE_UNIX_THREADS macro.
|
||||
** If we are to be thread-safe, include the pthreads header.
|
||||
*/
|
||||
#if SQLITE_THREADSAFE
|
||||
# include <pthread.h>
|
||||
# define SQLITE_UNIX_THREADS 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -521,7 +519,11 @@ static struct unix_syscall {
|
||||
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
|
||||
|
||||
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
||||
# ifdef __ANDROID__
|
||||
{ "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
|
||||
# else
|
||||
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
|
||||
# endif
|
||||
#else
|
||||
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
|
||||
#endif
|
||||
@@ -1115,8 +1117,7 @@ struct unixFileId {
|
||||
|
||||
/*
|
||||
** An instance of the following structure is allocated for each open
|
||||
** inode. Or, on LinuxThreads, there is one of these structures for
|
||||
** each inode opened by each thread.
|
||||
** inode.
|
||||
**
|
||||
** A single inode can have multiple file descriptors, so each unixFile
|
||||
** structure contains a pointer to an instance of this object and this
|
||||
@@ -1162,13 +1163,16 @@ struct unixInodeInfo {
|
||||
|
||||
/*
|
||||
** A lists of all unixInodeInfo objects.
|
||||
**
|
||||
** Must hold unixBigLock in order to read or write this variable.
|
||||
*/
|
||||
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** True if the inode mutex is held, or not. Used only within assert()
|
||||
** to help verify correct mutex usage.
|
||||
** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not.
|
||||
** This routine is used only within assert() to help verify correct mutex
|
||||
** usage.
|
||||
*/
|
||||
int unixFileMutexHeld(unixFile *pFile){
|
||||
assert( pFile->pInode );
|
||||
@@ -1296,8 +1300,8 @@ static void closePendingFds(unixFile *pFile){
|
||||
/*
|
||||
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
|
||||
**
|
||||
** The mutex entered using the unixEnterMutex() function must be held
|
||||
** when this function is called.
|
||||
** The global mutex must be held when this routine is called, but the mutex
|
||||
** on the inode being deleted must NOT be held.
|
||||
*/
|
||||
static void releaseInodeInfo(unixFile *pFile){
|
||||
unixInodeInfo *pInode = pFile->pInode;
|
||||
@@ -1332,8 +1336,7 @@ static void releaseInodeInfo(unixFile *pFile){
|
||||
** describes that file descriptor. Create a new one if necessary. The
|
||||
** return value might be uninitialized if an error occurs.
|
||||
**
|
||||
** The mutex entered using the unixEnterMutex() function must be held
|
||||
** when this function is called.
|
||||
** The global mutex must held when calling this routine.
|
||||
**
|
||||
** Return an appropriate error code.
|
||||
*/
|
||||
@@ -1394,6 +1397,7 @@ static int findInodeInfo(
|
||||
#else
|
||||
fileId.ino = (u64)statbuf.st_ino;
|
||||
#endif
|
||||
assert( unixMutexHeld() );
|
||||
pInode = inodeList;
|
||||
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
|
||||
pInode = pInode->pNext;
|
||||
@@ -1413,6 +1417,7 @@ static int findInodeInfo(
|
||||
}
|
||||
}
|
||||
pInode->nRef = 1;
|
||||
assert( unixMutexHeld() );
|
||||
pInode->pNext = inodeList;
|
||||
pInode->pPrev = 0;
|
||||
if( inodeList ) inodeList->pPrev = pInode;
|
||||
@@ -4210,18 +4215,18 @@ static int unixGetpagesize(void){
|
||||
**
|
||||
** The following fields are read-only after the object is created:
|
||||
**
|
||||
** fid
|
||||
** hShm
|
||||
** zFilename
|
||||
**
|
||||
** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
|
||||
** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
|
||||
** unixMutexHeld() is true when reading or writing any other field
|
||||
** in this structure.
|
||||
*/
|
||||
struct unixShmNode {
|
||||
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
|
||||
sqlite3_mutex *mutex; /* Mutex to access this object */
|
||||
sqlite3_mutex *pShmMutex; /* Mutex to access this object */
|
||||
char *zFilename; /* Name of the mmapped file */
|
||||
int h; /* Open file descriptor */
|
||||
int hShm; /* Open file descriptor */
|
||||
int szRegion; /* Size of shared-memory regions */
|
||||
u16 nRegion; /* Size of array apRegion */
|
||||
u8 isReadonly; /* True if read-only */
|
||||
@@ -4243,16 +4248,16 @@ struct unixShmNode {
|
||||
** The following fields are initialized when this object is created and
|
||||
** are read-only thereafter:
|
||||
**
|
||||
** unixShm.pFile
|
||||
** unixShm.pShmNode
|
||||
** unixShm.id
|
||||
**
|
||||
** All other fields are read/write. The unixShm.pFile->mutex must be held
|
||||
** while accessing any read/write fields.
|
||||
** All other fields are read/write. The unixShm.pShmNode->pShmMutex must
|
||||
** be held while accessing any read/write fields.
|
||||
*/
|
||||
struct unixShm {
|
||||
unixShmNode *pShmNode; /* The underlying unixShmNode object */
|
||||
unixShm *pNext; /* Next unixShm with the same unixShmNode */
|
||||
u8 hasMutex; /* True if holding the unixShmNode mutex */
|
||||
u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */
|
||||
u8 id; /* Id of this connection within its unixShmNode */
|
||||
u16 sharedMask; /* Mask of shared locks held */
|
||||
u16 exclMask; /* Mask of exclusive locks held */
|
||||
@@ -4282,7 +4287,8 @@ static int unixShmSystemLock(
|
||||
|
||||
/* Access to the unixShmNode object is serialized by the caller */
|
||||
pShmNode = pFile->pInode->pShmNode;
|
||||
assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) );
|
||||
assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
|
||||
assert( pShmNode->nRef>0 || unixMutexHeld() );
|
||||
|
||||
/* Shared locks never span more than one byte */
|
||||
assert( n==1 || lockType!=F_RDLCK );
|
||||
@@ -4290,13 +4296,13 @@ static int unixShmSystemLock(
|
||||
/* Locks are within range */
|
||||
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
|
||||
|
||||
if( pShmNode->h>=0 ){
|
||||
if( pShmNode->hShm>=0 ){
|
||||
/* Initialize the locking parameters */
|
||||
f.l_type = lockType;
|
||||
f.l_whence = SEEK_SET;
|
||||
f.l_start = ofst;
|
||||
f.l_len = n;
|
||||
rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
|
||||
rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
|
||||
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
|
||||
}
|
||||
|
||||
@@ -4368,18 +4374,18 @@ static void unixShmPurge(unixFile *pFd){
|
||||
int nShmPerMap = unixShmRegionPerMap();
|
||||
int i;
|
||||
assert( p->pInode==pFd->pInode );
|
||||
sqlite3_mutex_free(p->mutex);
|
||||
sqlite3_mutex_free(p->pShmMutex);
|
||||
for(i=0; i<p->nRegion; i+=nShmPerMap){
|
||||
if( p->h>=0 ){
|
||||
if( p->hShm>=0 ){
|
||||
osMunmap(p->apRegion[i], p->szRegion);
|
||||
}else{
|
||||
sqlite3_free(p->apRegion[i]);
|
||||
}
|
||||
}
|
||||
sqlite3_free(p->apRegion);
|
||||
if( p->h>=0 ){
|
||||
robust_close(pFd, p->h, __LINE__);
|
||||
p->h = -1;
|
||||
if( p->hShm>=0 ){
|
||||
robust_close(pFd, p->hShm, __LINE__);
|
||||
p->hShm = -1;
|
||||
}
|
||||
p->pInode->pShmNode = 0;
|
||||
sqlite3_free(p);
|
||||
@@ -4421,7 +4427,7 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
|
||||
lock.l_start = UNIX_SHM_DMS;
|
||||
lock.l_len = 1;
|
||||
lock.l_type = F_WRLCK;
|
||||
if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) {
|
||||
if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
|
||||
rc = SQLITE_IOERR_LOCK;
|
||||
}else if( lock.l_type==F_UNLCK ){
|
||||
if( pShmNode->isReadonly ){
|
||||
@@ -4429,7 +4435,7 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
|
||||
rc = SQLITE_READONLY_CANTINIT;
|
||||
}else{
|
||||
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
|
||||
if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){
|
||||
if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 0) ){
|
||||
rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
|
||||
}
|
||||
}
|
||||
@@ -4535,12 +4541,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath);
|
||||
sqlite3FileSuffix3(pDbFd->zPath, zShm);
|
||||
#endif
|
||||
pShmNode->h = -1;
|
||||
pShmNode->hShm = -1;
|
||||
pDbFd->pInode->pShmNode = pShmNode;
|
||||
pShmNode->pInode = pDbFd->pInode;
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
if( pShmNode->mutex==0 ){
|
||||
pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||
if( pShmNode->pShmMutex==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto shm_open_err;
|
||||
}
|
||||
@@ -4548,11 +4554,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
|
||||
if( pInode->bProcessLock==0 ){
|
||||
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
|
||||
pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777));
|
||||
pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777));
|
||||
}
|
||||
if( pShmNode->h<0 ){
|
||||
pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
|
||||
if( pShmNode->h<0 ){
|
||||
if( pShmNode->hShm<0 ){
|
||||
pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
|
||||
if( pShmNode->hShm<0 ){
|
||||
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
|
||||
goto shm_open_err;
|
||||
}
|
||||
@@ -4563,7 +4569,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
** is owned by the same user that owns the original database. Otherwise,
|
||||
** the original owner will not be able to connect.
|
||||
*/
|
||||
robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
|
||||
robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid);
|
||||
|
||||
rc = unixLockSharedMemory(pDbFd, pShmNode);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
|
||||
@@ -4583,13 +4589,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
** the cover of the unixEnterMutex() mutex and the pointer from the
|
||||
** new (struct unixShm) object to the pShmNode has been set. All that is
|
||||
** left to do is to link the new object into the linked list starting
|
||||
** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
|
||||
** mutex.
|
||||
** at pShmNode->pFirst. This must be done while holding the
|
||||
** pShmNode->pShmMutex.
|
||||
*/
|
||||
sqlite3_mutex_enter(pShmNode->mutex);
|
||||
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
||||
p->pNext = pShmNode->pFirst;
|
||||
pShmNode->pFirst = p;
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
||||
return rc;
|
||||
|
||||
/* Jump here on any error */
|
||||
@@ -4641,7 +4647,7 @@ static int unixShmMap(
|
||||
|
||||
p = pDbFd->pShm;
|
||||
pShmNode = p->pShmNode;
|
||||
sqlite3_mutex_enter(pShmNode->mutex);
|
||||
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
||||
if( pShmNode->isUnlocked ){
|
||||
rc = unixLockSharedMemory(pDbFd, pShmNode);
|
||||
if( rc!=SQLITE_OK ) goto shmpage_out;
|
||||
@@ -4649,8 +4655,8 @@ static int unixShmMap(
|
||||
}
|
||||
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
|
||||
assert( pShmNode->pInode==pDbFd->pInode );
|
||||
assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
|
||||
assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
|
||||
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
|
||||
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
|
||||
|
||||
/* Minimum number of regions required to be mapped. */
|
||||
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
|
||||
@@ -4662,12 +4668,12 @@ static int unixShmMap(
|
||||
|
||||
pShmNode->szRegion = szRegion;
|
||||
|
||||
if( pShmNode->h>=0 ){
|
||||
if( pShmNode->hShm>=0 ){
|
||||
/* The requested region is not mapped into this processes address space.
|
||||
** Check to see if it has been allocated (i.e. if the wal-index file is
|
||||
** large enough to contain the requested region).
|
||||
*/
|
||||
if( osFstat(pShmNode->h, &sStat) ){
|
||||
if( osFstat(pShmNode->hShm, &sStat) ){
|
||||
rc = SQLITE_IOERR_SHMSIZE;
|
||||
goto shmpage_out;
|
||||
}
|
||||
@@ -4695,7 +4701,7 @@ static int unixShmMap(
|
||||
assert( (nByte % pgsz)==0 );
|
||||
for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
|
||||
int x = 0;
|
||||
if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){
|
||||
if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){
|
||||
const char *zFile = pShmNode->zFilename;
|
||||
rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
|
||||
goto shmpage_out;
|
||||
@@ -4718,10 +4724,10 @@ static int unixShmMap(
|
||||
int nMap = szRegion*nShmPerMap;
|
||||
int i;
|
||||
void *pMem;
|
||||
if( pShmNode->h>=0 ){
|
||||
if( pShmNode->hShm>=0 ){
|
||||
pMem = osMmap(0, nMap,
|
||||
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
|
||||
MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion
|
||||
);
|
||||
if( pMem==MAP_FAILED ){
|
||||
rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
|
||||
@@ -4750,7 +4756,7 @@ shmpage_out:
|
||||
*pp = 0;
|
||||
}
|
||||
if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -4784,12 +4790,12 @@ static int unixShmLock(
|
||||
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|
||||
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
|
||||
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
|
||||
assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
|
||||
assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
|
||||
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
|
||||
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
|
||||
|
||||
mask = (1<<(ofst+n)) - (1<<ofst);
|
||||
assert( n>1 || mask==(1<<ofst) );
|
||||
sqlite3_mutex_enter(pShmNode->mutex);
|
||||
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
||||
if( flags & SQLITE_SHM_UNLOCK ){
|
||||
u16 allMask = 0; /* Mask of locks held by siblings */
|
||||
|
||||
@@ -4862,7 +4868,7 @@ static int unixShmLock(
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
|
||||
p->id, osGetpid(0), p->sharedMask, p->exclMask));
|
||||
return rc;
|
||||
@@ -4912,14 +4918,14 @@ static int unixShmUnmap(
|
||||
|
||||
/* Remove connection p from the set of connections associated
|
||||
** with pShmNode */
|
||||
sqlite3_mutex_enter(pShmNode->mutex);
|
||||
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
||||
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
|
||||
*pp = p->pNext;
|
||||
|
||||
/* Free the connection p */
|
||||
sqlite3_free(p);
|
||||
pDbFd->pShm = 0;
|
||||
sqlite3_mutex_leave(pShmNode->mutex);
|
||||
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
||||
|
||||
/* If pShmNode->nRef has reached 0, then close the underlying
|
||||
** shared-memory file, too */
|
||||
@@ -4928,7 +4934,7 @@ static int unixShmUnmap(
|
||||
assert( pShmNode->nRef>0 );
|
||||
pShmNode->nRef--;
|
||||
if( pShmNode->nRef==0 ){
|
||||
if( deleteFlag && pShmNode->h>=0 ){
|
||||
if( deleteFlag && pShmNode->hShm>=0 ){
|
||||
osUnlink(pShmNode->zFilename);
|
||||
}
|
||||
unixShmPurge(pDbFd);
|
||||
|
||||
+1
-4
@@ -941,13 +941,10 @@ idlist(A) ::= nm(Y).
|
||||
p->pLeft = p->pRight = 0;
|
||||
p->x.pList = 0;
|
||||
p->pAggInfo = 0;
|
||||
p->pTab = 0;
|
||||
p->y.pTab = 0;
|
||||
p->op2 = 0;
|
||||
p->iTable = 0;
|
||||
p->iColumn = 0;
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
p->pWin = 0;
|
||||
#endif
|
||||
p->u.zToken = (char*)&p[1];
|
||||
memcpy(p->u.zToken, t.z, t.n);
|
||||
p->u.zToken[t.n] = 0;
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
** The PCache.pSynced variable is used to optimize searching for a dirty
|
||||
** page to eject from the cache mid-transaction. It is better to eject
|
||||
** a page that does not require a journal sync than one that does.
|
||||
** Therefore, pSynced is maintained to that it *almost* always points
|
||||
** Therefore, pSynced is maintained so that it *almost* always points
|
||||
** to either the oldest page in the pDirty/pDirtyTail list that has a
|
||||
** clear PGHDR_NEED_SYNC flag or to a page that is older than this one
|
||||
** (so that the right page to eject can be found by following pDirtyPrev
|
||||
|
||||
+6
-4
@@ -1090,11 +1090,12 @@ void sqlite3Pragma(
|
||||
int nHidden = 0;
|
||||
Column *pCol;
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
pParse->nMem = 6;
|
||||
pParse->nMem = 7;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3ViewGetColumnNames(pParse, pTab);
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
if( IsHiddenColumn(pCol) ){
|
||||
int isHidden = IsHiddenColumn(pCol);
|
||||
if( isHidden && pPragma->iArg==0 ){
|
||||
nHidden++;
|
||||
continue;
|
||||
}
|
||||
@@ -1106,13 +1107,14 @@ void sqlite3Pragma(
|
||||
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
|
||||
}
|
||||
assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
|
||||
sqlite3VdbeMultiLoad(v, 1, "issisi",
|
||||
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
|
||||
i-nHidden,
|
||||
pCol->zName,
|
||||
sqlite3ColumnType(pCol,""),
|
||||
pCol->notNull ? 1 : 0,
|
||||
pCol->pDflt ? pCol->pDflt->u.zToken : 0,
|
||||
k);
|
||||
k,
|
||||
isHidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+70
-61
@@ -68,58 +68,57 @@
|
||||
** result column is different from the name of the pragma
|
||||
*/
|
||||
static const char *const pragCName[] = {
|
||||
/* 0 */ "cache_size", /* Used by: default_cache_size */
|
||||
/* 1 */ "cid", /* Used by: table_info */
|
||||
/* 2 */ "name",
|
||||
/* 3 */ "type",
|
||||
/* 4 */ "notnull",
|
||||
/* 5 */ "dflt_value",
|
||||
/* 6 */ "pk",
|
||||
/* 7 */ "tbl", /* Used by: stats */
|
||||
/* 8 */ "idx",
|
||||
/* 9 */ "wdth",
|
||||
/* 10 */ "hght",
|
||||
/* 11 */ "flgs",
|
||||
/* 12 */ "seqno", /* Used by: index_info */
|
||||
/* 13 */ "cid",
|
||||
/* 14 */ "name",
|
||||
/* 0 */ "id", /* Used by: foreign_key_list */
|
||||
/* 1 */ "seq",
|
||||
/* 2 */ "table",
|
||||
/* 3 */ "from",
|
||||
/* 4 */ "to",
|
||||
/* 5 */ "on_update",
|
||||
/* 6 */ "on_delete",
|
||||
/* 7 */ "match",
|
||||
/* 8 */ "cid", /* Used by: table_xinfo */
|
||||
/* 9 */ "name",
|
||||
/* 10 */ "type",
|
||||
/* 11 */ "notnull",
|
||||
/* 12 */ "dflt_value",
|
||||
/* 13 */ "pk",
|
||||
/* 14 */ "hidden",
|
||||
/* table_info reuses 8 */
|
||||
/* 15 */ "seqno", /* Used by: index_xinfo */
|
||||
/* 16 */ "cid",
|
||||
/* 17 */ "name",
|
||||
/* 18 */ "desc",
|
||||
/* 19 */ "coll",
|
||||
/* 20 */ "key",
|
||||
/* 21 */ "seq", /* Used by: index_list */
|
||||
/* 22 */ "name",
|
||||
/* 23 */ "unique",
|
||||
/* 24 */ "origin",
|
||||
/* 25 */ "partial",
|
||||
/* 26 */ "seq", /* Used by: database_list */
|
||||
/* 21 */ "tbl", /* Used by: stats */
|
||||
/* 22 */ "idx",
|
||||
/* 23 */ "wdth",
|
||||
/* 24 */ "hght",
|
||||
/* 25 */ "flgs",
|
||||
/* 26 */ "seq", /* Used by: index_list */
|
||||
/* 27 */ "name",
|
||||
/* 28 */ "file",
|
||||
/* 29 */ "name", /* Used by: function_list */
|
||||
/* 30 */ "builtin",
|
||||
/* 31 */ "name", /* Used by: module_list pragma_list */
|
||||
/* 32 */ "seq", /* Used by: collation_list */
|
||||
/* 33 */ "name",
|
||||
/* 34 */ "id", /* Used by: foreign_key_list */
|
||||
/* 35 */ "seq",
|
||||
/* 36 */ "table",
|
||||
/* 37 */ "from",
|
||||
/* 38 */ "to",
|
||||
/* 39 */ "on_update",
|
||||
/* 40 */ "on_delete",
|
||||
/* 41 */ "match",
|
||||
/* 42 */ "table", /* Used by: foreign_key_check */
|
||||
/* 43 */ "rowid",
|
||||
/* 44 */ "parent",
|
||||
/* 45 */ "fkid",
|
||||
/* 46 */ "busy", /* Used by: wal_checkpoint */
|
||||
/* 47 */ "log",
|
||||
/* 48 */ "checkpointed",
|
||||
/* 49 */ "timeout", /* Used by: busy_timeout */
|
||||
/* 50 */ "database", /* Used by: lock_status */
|
||||
/* 51 */ "status",
|
||||
/* 28 */ "unique",
|
||||
/* 29 */ "origin",
|
||||
/* 30 */ "partial",
|
||||
/* 31 */ "table", /* Used by: foreign_key_check */
|
||||
/* 32 */ "rowid",
|
||||
/* 33 */ "parent",
|
||||
/* 34 */ "fkid",
|
||||
/* index_info reuses 15 */
|
||||
/* 35 */ "seq", /* Used by: database_list */
|
||||
/* 36 */ "name",
|
||||
/* 37 */ "file",
|
||||
/* 38 */ "busy", /* Used by: wal_checkpoint */
|
||||
/* 39 */ "log",
|
||||
/* 40 */ "checkpointed",
|
||||
/* 41 */ "name", /* Used by: function_list */
|
||||
/* 42 */ "builtin",
|
||||
/* collation_list reuses 26 */
|
||||
/* 43 */ "database", /* Used by: lock_status */
|
||||
/* 44 */ "status",
|
||||
/* 45 */ "cache_size", /* Used by: default_cache_size */
|
||||
/* module_list pragma_list reuses 9 */
|
||||
/* 46 */ "timeout", /* Used by: busy_timeout */
|
||||
};
|
||||
|
||||
/* Definitions of all built-in pragmas */
|
||||
@@ -165,7 +164,7 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "busy_timeout",
|
||||
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 49, 1,
|
||||
/* ColNames: */ 46, 1,
|
||||
/* iArg: */ 0 },
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
{/* zName: */ "cache_size",
|
||||
@@ -202,7 +201,7 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "collation_list",
|
||||
/* ePragTyp: */ PragTyp_COLLATION_LIST,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 32, 2,
|
||||
/* ColNames: */ 26, 2,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
|
||||
@@ -237,14 +236,14 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "database_list",
|
||||
/* ePragTyp: */ PragTyp_DATABASE_LIST,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
|
||||
/* ColNames: */ 26, 3,
|
||||
/* ColNames: */ 35, 3,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
|
||||
{/* zName: */ "default_cache_size",
|
||||
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
|
||||
/* ColNames: */ 0, 1,
|
||||
/* ColNames: */ 45, 1,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
@@ -274,14 +273,14 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "foreign_key_check",
|
||||
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
|
||||
/* ColNames: */ 42, 4,
|
||||
/* ColNames: */ 31, 4,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
|
||||
{/* zName: */ "foreign_key_list",
|
||||
/* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 34, 8,
|
||||
/* ColNames: */ 0, 8,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
@@ -317,7 +316,7 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "function_list",
|
||||
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 29, 2,
|
||||
/* ColNames: */ 41, 2,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#endif
|
||||
@@ -353,12 +352,12 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "index_info",
|
||||
/* ePragTyp: */ PragTyp_INDEX_INFO,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 12, 3,
|
||||
/* ColNames: */ 15, 3,
|
||||
/* iArg: */ 0 },
|
||||
{/* zName: */ "index_list",
|
||||
/* ePragTyp: */ PragTyp_INDEX_LIST,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 21, 5,
|
||||
/* ColNames: */ 26, 5,
|
||||
/* iArg: */ 0 },
|
||||
{/* zName: */ "index_xinfo",
|
||||
/* ePragTyp: */ PragTyp_INDEX_INFO,
|
||||
@@ -393,6 +392,11 @@ static const PragmaName aPragmaName[] = {
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
{/* zName: */ "legacy_alter_table",
|
||||
/* ePragTyp: */ PragTyp_FLAG,
|
||||
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ SQLITE_LegacyAlter },
|
||||
{/* zName: */ "legacy_file_format",
|
||||
/* ePragTyp: */ PragTyp_FLAG,
|
||||
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
||||
@@ -410,7 +414,7 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "lock_status",
|
||||
/* ePragTyp: */ PragTyp_LOCK_STATUS,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 50, 2,
|
||||
/* ColNames: */ 43, 2,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
@@ -436,7 +440,7 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "module_list",
|
||||
/* ePragTyp: */ PragTyp_MODULE_LIST,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 31, 1,
|
||||
/* ColNames: */ 9, 1,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#endif
|
||||
@@ -469,7 +473,7 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "pragma_list",
|
||||
/* ePragTyp: */ PragTyp_PRAGMA_LIST,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 31, 1,
|
||||
/* ColNames: */ 9, 1,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
@@ -556,7 +560,7 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "stats",
|
||||
/* ePragTyp: */ PragTyp_STATS,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
|
||||
/* ColNames: */ 7, 5,
|
||||
/* ColNames: */ 21, 5,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
@@ -570,8 +574,13 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "table_info",
|
||||
/* ePragTyp: */ PragTyp_TABLE_INFO,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 1, 6,
|
||||
/* ColNames: */ 8, 6,
|
||||
/* iArg: */ 0 },
|
||||
{/* zName: */ "table_xinfo",
|
||||
/* ePragTyp: */ PragTyp_TABLE_INFO,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
||||
/* ColNames: */ 8, 7,
|
||||
/* iArg: */ 1 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
{/* zName: */ "temp_store",
|
||||
@@ -635,7 +644,7 @@ static const PragmaName aPragmaName[] = {
|
||||
{/* zName: */ "wal_checkpoint",
|
||||
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
|
||||
/* ePragFlg: */ PragFlg_NeedSchema,
|
||||
/* ColNames: */ 46, 3,
|
||||
/* ColNames: */ 38, 3,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
@@ -646,4 +655,4 @@ static const PragmaName aPragmaName[] = {
|
||||
/* iArg: */ SQLITE_WriteSchema },
|
||||
#endif
|
||||
};
|
||||
/* Number of pragmas: 60 on by default, 77 total. */
|
||||
/* Number of pragmas: 62 on by default, 79 total. */
|
||||
|
||||
+26
-29
@@ -159,7 +159,7 @@ int sqlite3MatchSpanName(
|
||||
** (even if X is implied).
|
||||
** pExpr->iTable Set to the cursor number for the table obtained
|
||||
** from pSrcList.
|
||||
** pExpr->pTab Points to the Table structure of X.Y (even if
|
||||
** 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.
|
||||
@@ -203,7 +203,6 @@ static int lookupName(
|
||||
|
||||
/* Initialize the node to no-match */
|
||||
pExpr->iTable = -1;
|
||||
pExpr->pTab = 0;
|
||||
ExprSetVVAProperty(pExpr, EP_NoReduce);
|
||||
|
||||
/* Translate the schema name in zDb into a pointer to the corresponding
|
||||
@@ -265,7 +264,7 @@ static int lookupName(
|
||||
continue;
|
||||
}
|
||||
if( IN_RENAME_OBJECT && pItem->zAlias ){
|
||||
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab);
|
||||
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
|
||||
}
|
||||
}
|
||||
if( 0==(cntTab++) ){
|
||||
@@ -291,13 +290,13 @@ static int lookupName(
|
||||
}
|
||||
if( pMatch ){
|
||||
pExpr->iTable = pMatch->iCursor;
|
||||
pExpr->pTab = pMatch->pTab;
|
||||
pExpr->y.pTab = pMatch->pTab;
|
||||
/* RIGHT JOIN not (yet) supported */
|
||||
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
|
||||
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
|
||||
ExprSetProperty(pExpr, EP_CanBeNull);
|
||||
}
|
||||
pSchema = pExpr->pTab->pSchema;
|
||||
pSchema = pExpr->y.pTab->pSchema;
|
||||
}
|
||||
} /* if( pSrcList ) */
|
||||
|
||||
@@ -354,7 +353,7 @@ static int lookupName(
|
||||
testcase( iCol==(-1) );
|
||||
if( IN_RENAME_OBJECT ){
|
||||
pExpr->iColumn = iCol;
|
||||
pExpr->pTab = pTab;
|
||||
pExpr->y.pTab = pTab;
|
||||
eNewExprOp = TK_COLUMN;
|
||||
}else{
|
||||
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
|
||||
@@ -376,7 +375,7 @@ static int lookupName(
|
||||
testcase( iCol==32 );
|
||||
pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
|
||||
}
|
||||
pExpr->pTab = pTab;
|
||||
pExpr->y.pTab = pTab;
|
||||
pExpr->iColumn = (i16)iCol;
|
||||
eNewExprOp = TK_TRIGGER;
|
||||
#endif /* SQLITE_OMIT_TRIGGER */
|
||||
@@ -476,7 +475,7 @@ static int lookupName(
|
||||
assert( pExpr->op==TK_ID );
|
||||
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
|
||||
pExpr->op = TK_STRING;
|
||||
pExpr->pTab = 0;
|
||||
pExpr->y.pTab = 0;
|
||||
return WRC_Prune;
|
||||
}
|
||||
if( sqlite3ExprIdToTrueFalse(pExpr) ){
|
||||
@@ -554,9 +553,9 @@ Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
|
||||
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
|
||||
if( p ){
|
||||
struct SrcList_item *pItem = &pSrc->a[iSrc];
|
||||
p->pTab = pItem->pTab;
|
||||
p->y.pTab = pItem->pTab;
|
||||
p->iTable = pItem->iCursor;
|
||||
if( p->pTab->iPKey==iCol ){
|
||||
if( p->y.pTab->iPKey==iCol ){
|
||||
p->iColumn = -1;
|
||||
}else{
|
||||
p->iColumn = (ynVar)iCol;
|
||||
@@ -646,7 +645,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
pItem = pSrcList->a;
|
||||
assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
|
||||
pExpr->op = TK_COLUMN;
|
||||
pExpr->pTab = pItem->pTab;
|
||||
pExpr->y.pTab = pItem->pTab;
|
||||
pExpr->iTable = pItem->iCursor;
|
||||
pExpr->iColumn = -1;
|
||||
pExpr->affinity = SQLITE_AFF_INTEGER;
|
||||
@@ -690,9 +689,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
zColumn = pRight->u.zToken;
|
||||
if( IN_RENAME_OBJECT ){
|
||||
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
|
||||
}
|
||||
if( IN_RENAME_OBJECT ){
|
||||
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft);
|
||||
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
|
||||
}
|
||||
}
|
||||
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
|
||||
@@ -782,18 +779,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
|| (pDef->xValue==0 && pDef->xInverse==0)
|
||||
|| (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
|
||||
);
|
||||
if( pDef && pDef->xValue==0 && pExpr->pWin ){
|
||||
if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"%.*s() may not be used as a window function", nId, zId
|
||||
);
|
||||
pNC->nErr++;
|
||||
}else if(
|
||||
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|
||||
|| (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin)
|
||||
|| (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
|
||||
|| (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin)
|
||||
|| (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0)
|
||||
){
|
||||
const char *zType;
|
||||
if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
|
||||
if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){
|
||||
zType = "window";
|
||||
}else{
|
||||
zType = "aggregate";
|
||||
@@ -823,7 +820,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
if( is_agg ){
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg);
|
||||
pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg);
|
||||
#else
|
||||
pNC->ncFlags &= ~NC_AllowAgg;
|
||||
#endif
|
||||
@@ -832,17 +829,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
sqlite3WalkExprList(pWalker, pList);
|
||||
if( is_agg ){
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( pExpr->pWin ){
|
||||
if( pExpr->y.pWin ){
|
||||
Select *pSel = pNC->pWinSelect;
|
||||
sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition);
|
||||
sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy);
|
||||
sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter);
|
||||
sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef);
|
||||
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
|
||||
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
|
||||
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
|
||||
sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
|
||||
if( 0==pSel->pWin
|
||||
|| 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin)
|
||||
|| 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin)
|
||||
){
|
||||
pExpr->pWin->pNextWin = pSel->pWin;
|
||||
pSel->pWin = pExpr->pWin;
|
||||
pExpr->y.pWin->pNextWin = pSel->pWin;
|
||||
pSel->pWin = pExpr->y.pWin;
|
||||
}
|
||||
pNC->ncFlags |= NC_AllowWin;
|
||||
}else
|
||||
@@ -1265,13 +1262,13 @@ static int resolveOrderGroupBy(
|
||||
for(j=0; j<pSelect->pEList->nExpr; j++){
|
||||
if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( pE->pWin ){
|
||||
if( ExprHasProperty(pE, EP_WinFunc) ){
|
||||
/* Since this window function is being changed into a reference
|
||||
** to the same window function the result set, remove the instance
|
||||
** of this window function from the Select.pWin list. */
|
||||
Window **pp;
|
||||
for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
|
||||
if( *pp==pE->pWin ){
|
||||
if( *pp==pE->y.pWin ){
|
||||
*pp = (*pp)->pNextWin;
|
||||
}
|
||||
}
|
||||
|
||||
+15
-7
@@ -803,7 +803,7 @@ static void selectExprDefer(
|
||||
struct ExprList_item *pItem = &pEList->a[i];
|
||||
if( pItem->u.x.iOrderByCol==0 ){
|
||||
Expr *pExpr = pItem->pExpr;
|
||||
Table *pTab = pExpr->pTab;
|
||||
Table *pTab = pExpr->y.pTab;
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
|
||||
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
|
||||
){
|
||||
@@ -826,12 +826,12 @@ static void selectExprDefer(
|
||||
Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
|
||||
if( pNew ){
|
||||
pNew->iTable = pExpr->iTable;
|
||||
pNew->pTab = pExpr->pTab;
|
||||
pNew->y.pTab = pExpr->y.pTab;
|
||||
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
|
||||
pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
|
||||
}
|
||||
}
|
||||
pSort->aDefer[nDefer].pTab = pExpr->pTab;
|
||||
pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
|
||||
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
|
||||
pSort->aDefer[nDefer].nKey = nKey;
|
||||
nDefer++;
|
||||
@@ -1680,7 +1680,7 @@ static const char *columnTypeImpl(
|
||||
break;
|
||||
}
|
||||
|
||||
assert( pTab && pExpr->pTab==pTab );
|
||||
assert( pTab && pExpr->y.pTab==pTab );
|
||||
if( pS ){
|
||||
/* The "table" is actually a sub-select or a view in the FROM clause
|
||||
** of the SELECT statement. Return the declaration type and origin
|
||||
@@ -1865,7 +1865,7 @@ static void generateColumnNames(
|
||||
|
||||
assert( p!=0 );
|
||||
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
|
||||
assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
|
||||
assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
|
||||
if( pEList->a[i].zName ){
|
||||
/* An AS clause always takes first priority */
|
||||
char *zName = pEList->a[i].zName;
|
||||
@@ -1873,7 +1873,7 @@ static void generateColumnNames(
|
||||
}else if( srcName && p->op==TK_COLUMN ){
|
||||
char *zCol;
|
||||
int iCol = p->iColumn;
|
||||
pTab = p->pTab;
|
||||
pTab = p->y.pTab;
|
||||
assert( pTab!=0 );
|
||||
if( iCol<0 ) iCol = pTab->iPKey;
|
||||
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
|
||||
@@ -1964,7 +1964,7 @@ int sqlite3ColumnsFromExprList(
|
||||
if( pColExpr->op==TK_COLUMN ){
|
||||
/* For columns use the column name name */
|
||||
int iCol = pColExpr->iColumn;
|
||||
Table *pTab = pColExpr->pTab;
|
||||
Table *pTab = pColExpr->y.pTab;
|
||||
assert( pTab!=0 );
|
||||
if( iCol<0 ) iCol = pTab->iPKey;
|
||||
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
|
||||
@@ -2318,6 +2318,13 @@ static void generateWithRecursiveQuery(
|
||||
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;
|
||||
|
||||
@@ -6086,6 +6093,7 @@ int sqlite3Select(
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
|
||||
sqlite3VdbeResolveLabel(v, addrGosub);
|
||||
VdbeNoopComment((v, "inner-loop subroutine"));
|
||||
sSort.labelOBLopt = 0;
|
||||
selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak);
|
||||
sqlite3VdbeResolveLabel(v, iCont);
|
||||
sqlite3VdbeAddOp1(v, OP_Return, regGosub);
|
||||
|
||||
+216
-138
@@ -1273,7 +1273,7 @@ static void editFunc(
|
||||
if( bBin ){
|
||||
sqlite3_result_blob64(context, p, sz, sqlite3_free);
|
||||
}else{
|
||||
int i, j;
|
||||
sqlite3_int64 i, j;
|
||||
if( hasCRNL ){
|
||||
/* If the original contains \r\n then do no conversions back to \n */
|
||||
j = sz;
|
||||
@@ -3335,137 +3335,229 @@ static int run_schema_dump_query(
|
||||
}
|
||||
|
||||
/*
|
||||
** Text of a help message
|
||||
** Text of help messages.
|
||||
**
|
||||
** The help text for each individual command begins with a line that starts
|
||||
** with ".". Subsequent lines are supplimental information.
|
||||
**
|
||||
** There must be two or more spaces between the end of the command and the
|
||||
** start of the description of what that command does.
|
||||
*/
|
||||
static char zHelp[] =
|
||||
static const char *(azHelp[]) = {
|
||||
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
".archive ... Manage SQL archives: \".archive --help\" for details\n"
|
||||
".archive ... Manage SQL archives",
|
||||
" Each command must have exactly one of the following options:",
|
||||
" -c, --create Create a new archive",
|
||||
" -u, --update Update or add files to an existing archive",
|
||||
" -t, --list List contents of archive",
|
||||
" -x, --extract Extract files from archive",
|
||||
" Optional arguments:",
|
||||
" -v, --verbose Print each filename as it is processed",
|
||||
" -f FILE, --file FILE Operate on archive FILE (default is current db)",
|
||||
" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS",
|
||||
" -C DIR, --directory DIR Change to directory DIR to read/extract files",
|
||||
" -n, --dryrun Show the SQL that would have occurred",
|
||||
" Examples:",
|
||||
" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar",
|
||||
" .ar -tf archive.sar # List members of archive.sar",
|
||||
" .ar -xvf archive.sar # Verbosely extract files from archive.sar",
|
||||
" See also:",
|
||||
" http://sqlite.org/cli.html#sqlar_archive_support",
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
".auth ON|OFF Show authorizer callbacks\n"
|
||||
".auth ON|OFF Show authorizer callbacks",
|
||||
#endif
|
||||
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
|
||||
" Add \"--append\" to open using appendvfs.\n"
|
||||
".bail on|off Stop after hitting an error. Default OFF\n"
|
||||
".binary on|off Turn binary output on or off. Default OFF\n"
|
||||
".cd DIRECTORY Change the working directory to DIRECTORY\n"
|
||||
".changes on|off Show number of rows changed by SQL\n"
|
||||
".check GLOB Fail if output since .testcase does not match\n"
|
||||
".clone NEWDB Clone data into NEWDB from the existing database\n"
|
||||
".databases List names and files of attached databases\n"
|
||||
".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n"
|
||||
".dbinfo ?DB? Show status information about the database\n"
|
||||
".dump ?TABLE? ... Dump the database in an SQL text format\n"
|
||||
" If TABLE specified, only dump tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".echo on|off Turn command echo on or off\n"
|
||||
".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n"
|
||||
".excel Display the output of next command in a spreadsheet\n"
|
||||
".exit Exit this program\n"
|
||||
".expert EXPERIMENTAL. Suggest indexes for specified queries\n"
|
||||
".backup ?DB? FILE Backup DB (default \"main\") to FILE",
|
||||
" --append Use the appendvfs",
|
||||
".bail on|off Stop after hitting an error. Default OFF",
|
||||
".binary on|off Turn binary output on or off. Default OFF",
|
||||
".cd DIRECTORY Change the working directory to DIRECTORY",
|
||||
".changes on|off Show number of rows changed by SQL",
|
||||
".check GLOB Fail if output since .testcase does not match",
|
||||
".clone NEWDB Clone data into NEWDB from the existing database",
|
||||
".databases List names and files of attached databases",
|
||||
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
|
||||
".dbinfo ?DB? Show status information about the database",
|
||||
".dump ?TABLE? ... Render all database content as SQL",
|
||||
" Options:",
|
||||
" --preserve-rowids Include ROWID values in the output",
|
||||
" --newlines Allow unescaped newline characters in output",
|
||||
" TABLE is LIKE pattern for the tables to dump",
|
||||
".echo on|off Turn command echo on or off",
|
||||
".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN",
|
||||
".excel Display the output of next command in a spreadsheet",
|
||||
".exit ?CODE? Exit this program with return-code CODE",
|
||||
".expert EXPERIMENTAL. Suggest indexes for specified queries",
|
||||
/* Because explain mode comes on automatically now, the ".explain" mode
|
||||
** is removed from the help screen. It is still supported for legacy, however */
|
||||
/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/
|
||||
".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
|
||||
".headers on|off Turn display of headers on or off\n"
|
||||
".help Show this message\n"
|
||||
".import FILE TABLE Import data from FILE into TABLE\n"
|
||||
/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/
|
||||
".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
|
||||
".headers on|off Turn display of headers on or off",
|
||||
".help ?-all? ?PATTERN? Show help text for PATTERN",
|
||||
".import FILE TABLE Import data from FILE into TABLE",
|
||||
#ifndef SQLITE_OMIT_TEST_CONTROL
|
||||
".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n"
|
||||
".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
|
||||
#endif
|
||||
".indexes ?TABLE? Show names of all indexes\n"
|
||||
" If TABLE specified, only show indexes for tables\n"
|
||||
" matching LIKE pattern TABLE.\n"
|
||||
".indexes ?TABLE? Show names of indexes",
|
||||
" If TABLE is specified, only show indexes for",
|
||||
" tables matching TABLE using the LIKE operator.",
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
|
||||
".iotrace FILE Enable I/O diagnostic logging to FILE",
|
||||
#endif
|
||||
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
|
||||
".lint OPTIONS Report potential schema issues. Options:\n"
|
||||
" fkey-indexes Find missing foreign key indexes\n"
|
||||
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
|
||||
".lint OPTIONS Report potential schema issues.",
|
||||
" Options:",
|
||||
" fkey-indexes Find missing foreign key indexes",
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
".load FILE ?ENTRY? Load an extension library\n"
|
||||
".load FILE ?ENTRY? Load an extension library",
|
||||
#endif
|
||||
".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
|
||||
".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
|
||||
" ascii Columns/rows delimited by 0x1F and 0x1E\n"
|
||||
" csv Comma-separated values\n"
|
||||
" column Left-aligned columns. (See .width)\n"
|
||||
" html HTML <table> code\n"
|
||||
" insert SQL insert statements for TABLE\n"
|
||||
" line One value per line\n"
|
||||
" list Values delimited by \"|\"\n"
|
||||
" quote Escape answers as for SQL\n"
|
||||
" tabs Tab-separated values\n"
|
||||
" tcl TCL list elements\n"
|
||||
".nullvalue STRING Use STRING in place of NULL values\n"
|
||||
".once (-e|-x|FILE) Output for the next SQL command only to FILE\n"
|
||||
" or invoke system text editor (-e) or spreadsheet (-x)\n"
|
||||
" on the output.\n"
|
||||
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
|
||||
" The --new option starts with an empty file\n"
|
||||
" Other options: --readonly --append --zip\n"
|
||||
".output ?FILE? Send output to FILE or stdout\n"
|
||||
".print STRING... Print literal STRING\n"
|
||||
".prompt MAIN CONTINUE Replace the standard prompts\n"
|
||||
".quit Exit this program\n"
|
||||
".read FILENAME Execute SQL in FILENAME\n"
|
||||
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
|
||||
".save FILE Write in-memory database into FILE\n"
|
||||
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
|
||||
".schema ?PATTERN? Show the CREATE statements matching PATTERN\n"
|
||||
" Add --indent for pretty-printing\n"
|
||||
".selftest ?--init? Run tests defined in the SELFTEST table\n"
|
||||
".separator COL ?ROW? Change the column separator and optionally the row\n"
|
||||
" separator for both the output mode and .import\n"
|
||||
".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
|
||||
".mode MODE ?TABLE? Set output mode",
|
||||
" MODE is one of:",
|
||||
" ascii Columns/rows delimited by 0x1F and 0x1E",
|
||||
" csv Comma-separated values",
|
||||
" column Left-aligned columns. (See .width)",
|
||||
" html HTML <table> code",
|
||||
" insert SQL insert statements for TABLE",
|
||||
" line One value per line",
|
||||
" list Values delimited by \"|\"",
|
||||
" quote Escape answers as for SQL",
|
||||
" tabs Tab-separated values",
|
||||
" tcl TCL list elements",
|
||||
".nullvalue STRING Use STRING in place of NULL values",
|
||||
".once (-e|-x|FILE) Output for the next SQL command only to FILE",
|
||||
" If FILE begins with '|' then open as a pipe",
|
||||
" Other options:",
|
||||
" -e Invoke system text editor",
|
||||
" -x Open in a spreadsheet",
|
||||
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
|
||||
" Options:",
|
||||
" --append Use appendvfs to append database to the end of FILE",
|
||||
" --new Initialize FILE to an empty database",
|
||||
" --readonly Open FILE readonly",
|
||||
" --zip FILE is a ZIP archive",
|
||||
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
|
||||
" If FILE begins with '|' then open it as a pipe.",
|
||||
".print STRING... Print literal STRING",
|
||||
".prompt MAIN CONTINUE Replace the standard prompts",
|
||||
".quit Exit this program",
|
||||
".read FILE Read input from FILE",
|
||||
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
|
||||
".save FILE Write in-memory database into FILE",
|
||||
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
|
||||
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
|
||||
" Options:",
|
||||
" --indent Try to pretty-print the schema",
|
||||
".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
|
||||
" Options:",
|
||||
" --init Create a new SELFTEST table",
|
||||
" -v Verbose output",
|
||||
".separator COL ?ROW? Change the column and row separators",
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
".session CMD ... Create or control sessions\n"
|
||||
".session ?NAME? CMD ... Create or control sessions",
|
||||
" Subcommands:",
|
||||
" attach TABLE Attach TABLE",
|
||||
" changeset FILE Write a changeset into FILE",
|
||||
" close Close one session",
|
||||
" enable ?BOOLEAN? Set or query the enable bit",
|
||||
" filter GLOB... Reject tables matching GLOBs",
|
||||
" indirect ?BOOLEAN? Mark or query the indirect status",
|
||||
" isempty Query whether the session is empty",
|
||||
" list List currently open session names",
|
||||
" open DB NAME Open a new session on DB",
|
||||
" patchset FILE Write a patchset into FILE",
|
||||
" If ?NAME? is omitted, the first defined session is used.",
|
||||
#endif
|
||||
".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n"
|
||||
".sha3sum ... Compute a SHA3 hash of database content",
|
||||
" Options:",
|
||||
" --schema Also hash the sqlite_master table",
|
||||
" --sha3-224 Use the sha3-224 algorithm",
|
||||
" --sha3-256 Use the sha3-256 algorithm. This is the default.",
|
||||
" --sha3-384 Use the sha3-384 algorithm",
|
||||
" --sha3-512 Use the sha3-512 algorithm",
|
||||
" Any other argument is a LIKE pattern for tables to hash",
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
|
||||
".shell CMD ARGS... Run CMD ARGS... in a system shell",
|
||||
#endif
|
||||
".show Show the current values for various settings\n"
|
||||
".stats ?on|off? Show stats or turn stats on or off\n"
|
||||
".show Show the current values for various settings",
|
||||
".stats ?on|off? Show stats or turn stats on or off",
|
||||
#ifndef SQLITE_NOHAVE_SYSTEM
|
||||
".system CMD ARGS... Run CMD ARGS... in a system shell\n"
|
||||
".system CMD ARGS... Run CMD ARGS... in a system shell",
|
||||
#endif
|
||||
".tables ?TABLE? List names of tables\n"
|
||||
" If TABLE specified, only list tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".testcase NAME Begin redirecting output to 'testcase-out.txt'\n"
|
||||
".timeout MS Try opening locked tables for MS milliseconds\n"
|
||||
".timer on|off Turn SQL timer on or off\n"
|
||||
".trace FILE|off Output each SQL statement as it is run\n"
|
||||
".vfsinfo ?AUX? Information about the top-level VFS\n"
|
||||
".vfslist List all available VFSes\n"
|
||||
".vfsname ?AUX? Print the name of the VFS stack\n"
|
||||
".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
|
||||
" Negative values right-justify\n"
|
||||
;
|
||||
".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
|
||||
".testcase NAME Begin redirecting output to 'testcase-out.txt'",
|
||||
".timeout MS Try opening locked tables for MS milliseconds",
|
||||
".timer on|off Turn SQL timer on or off",
|
||||
".trace FILE|off Output each SQL statement as it is run",
|
||||
".vfsinfo ?AUX? Information about the top-level VFS",
|
||||
".vfslist List all available VFSes",
|
||||
".vfsname ?AUX? Print the name of the VFS stack",
|
||||
".width NUM1 NUM2 ... Set column widths for \"column\" mode",
|
||||
" Negative values right-justify",
|
||||
};
|
||||
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
/*
|
||||
** Print help information for the ".sessions" command
|
||||
** Output help text.
|
||||
**
|
||||
** zPattern describes the set of commands for which help text is provided.
|
||||
** If zPattern is NULL, then show all commands, but only give a one-line
|
||||
** description of each.
|
||||
**
|
||||
** Return the number of matches.
|
||||
*/
|
||||
void session_help(ShellState *p){
|
||||
raw_printf(p->out,
|
||||
".session ?NAME? SUBCOMMAND ?ARGS...?\n"
|
||||
"If ?NAME? is omitted, the first defined session is used.\n"
|
||||
"Subcommands:\n"
|
||||
" attach TABLE Attach TABLE\n"
|
||||
" changeset FILE Write a changeset into FILE\n"
|
||||
" close Close one session\n"
|
||||
" enable ?BOOLEAN? Set or query the enable bit\n"
|
||||
" filter GLOB... Reject tables matching GLOBs\n"
|
||||
" indirect ?BOOLEAN? Mark or query the indirect status\n"
|
||||
" isempty Query whether the session is empty\n"
|
||||
" list List currently open session names\n"
|
||||
" open DB NAME Open a new session on DB\n"
|
||||
" patchset FILE Write a patchset into FILE\n"
|
||||
);
|
||||
static int showHelp(FILE *out, const char *zPattern){
|
||||
int i, j;
|
||||
int n = 0;
|
||||
char *zPat;
|
||||
if( zPattern==0 || zPattern[0]=='0' ){
|
||||
/* Show all commands, but only one line per command */
|
||||
for(i=0; i<ArraySize(azHelp); i++){
|
||||
if( azHelp[i][0]=='.' ){
|
||||
utf8_printf(out, "%s\n", azHelp[i]);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* Look for commands that for which zPattern is an exact prefix */
|
||||
zPat = sqlite3_mprintf(".%s*", zPattern);
|
||||
for(i=0; i<ArraySize(azHelp); i++){
|
||||
if( sqlite3_strglob(zPat, azHelp[i])==0 ){
|
||||
utf8_printf(out, "%s\n", azHelp[i]);
|
||||
j = i+1;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
sqlite3_free(zPat);
|
||||
if( n ){
|
||||
if( n==1 ){
|
||||
/* when zPattern is a prefix of exactly one command, then include the
|
||||
** details of that command, which should begin at offset j */
|
||||
while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
|
||||
utf8_printf(out, "%s\n", azHelp[j]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
/* Look for commands that contain zPattern anywhere. Show the complete
|
||||
** text of all commands that match. */
|
||||
zPat = sqlite3_mprintf("%%%s%%", zPattern);
|
||||
for(i=0; i<ArraySize(azHelp); i++){
|
||||
if( azHelp[i][0]=='.' ) j = i;
|
||||
if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
|
||||
utf8_printf(out, "%s\n", azHelp[j]);
|
||||
while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
|
||||
j++;
|
||||
utf8_printf(out, "%s\n", azHelp[j]);
|
||||
}
|
||||
i = j;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
sqlite3_free(zPat);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Forward reference */
|
||||
static int process_input(ShellState *p, FILE *in);
|
||||
@@ -4941,32 +5033,7 @@ struct ArCommand {
|
||||
** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
|
||||
*/
|
||||
static int arUsage(FILE *f){
|
||||
raw_printf(f,
|
||||
"\n"
|
||||
"Usage: .ar [OPTION...] [FILE...]\n"
|
||||
"The .ar command manages sqlar archives.\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n"
|
||||
" .ar -tf archive.sar # List members of archive.sar\n"
|
||||
" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n"
|
||||
"\n"
|
||||
"Each command line must feature exactly one command option:\n"
|
||||
" -c, --create Create a new archive\n"
|
||||
" -u, --update Update or add files to an existing archive\n"
|
||||
" -t, --list List contents of archive\n"
|
||||
" -x, --extract Extract files from archive\n"
|
||||
"\n"
|
||||
"And zero or more optional options:\n"
|
||||
" -v, --verbose Print each filename as it is processed\n"
|
||||
" -f FILE, --file FILE Operate on archive FILE (default is current db)\n"
|
||||
" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n"
|
||||
" -C DIR, --directory DIR Change to directory DIR to read/extract files\n"
|
||||
" -n, --dryrun Show the SQL that would have occurred\n"
|
||||
"\n"
|
||||
"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
|
||||
"\n"
|
||||
);
|
||||
showHelp(f,"archive");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
@@ -5073,6 +5140,7 @@ static int arParseCommand(
|
||||
struct ArSwitch *pEnd = &aSwitch[nSwitch];
|
||||
|
||||
if( nArg<=1 ){
|
||||
utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
|
||||
return arUsage(stderr);
|
||||
}else{
|
||||
char *z = azArg[1];
|
||||
@@ -5844,7 +5912,10 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else
|
||||
|
||||
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
|
||||
static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = {
|
||||
static const struct DbConfigChoices {
|
||||
const char *zName;
|
||||
int op;
|
||||
} aDbConfig[] = {
|
||||
{ "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
|
||||
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
|
||||
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
|
||||
@@ -6091,7 +6162,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else
|
||||
|
||||
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
|
||||
utf8_printf(p->out, "%s", zHelp);
|
||||
if( nArg>=2 ){
|
||||
int n = showHelp(p->out, azArg[1]);
|
||||
if( n==0 ){
|
||||
utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
|
||||
}
|
||||
}else{
|
||||
showHelp(p->out, 0);
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
|
||||
@@ -7095,7 +7173,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else
|
||||
/* If no command name matches, show a syntax error */
|
||||
session_syntax_error:
|
||||
session_help(p);
|
||||
showHelp(p->out, "session");
|
||||
}else
|
||||
#endif
|
||||
|
||||
|
||||
+9
-5
@@ -1536,6 +1536,7 @@ struct sqlite3 {
|
||||
#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/
|
||||
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
|
||||
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
|
||||
#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
|
||||
|
||||
/* Flags used only if debugging */
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -2459,11 +2460,11 @@ struct Expr {
|
||||
** TK_COLUMN: the value of p5 for OP_Column
|
||||
** TK_AGG_FUNCTION: nesting depth */
|
||||
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
||||
Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
|
||||
** for a column of an index on an expression */
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
Window *pWin; /* Window definition for window functions */
|
||||
#endif
|
||||
union {
|
||||
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
|
||||
** for a column of an index on an expression */
|
||||
Window *pWin; /* TK_FUNCTION: Window definition for the func */
|
||||
} y;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2493,6 +2494,7 @@ struct Expr {
|
||||
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
|
||||
#define EP_Alias 0x400000 /* Is an alias for a result set column */
|
||||
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
|
||||
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
|
||||
|
||||
/*
|
||||
** The EP_Propagate mask is a set of properties that automatically propagate
|
||||
@@ -3178,6 +3180,7 @@ struct AuthContext {
|
||||
*/
|
||||
#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 */
|
||||
@@ -4002,6 +4005,7 @@ void sqlite3GenerateRowDelete(
|
||||
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
|
||||
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
|
||||
void sqlite3ResolvePartIdxLabel(Parse*,int);
|
||||
int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
|
||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
||||
u8,u8,int,int*,int*,Upsert*);
|
||||
#ifdef SQLITE_ENABLE_NULL_TRIM
|
||||
|
||||
@@ -3497,6 +3497,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
|
||||
#endif
|
||||
|
||||
if( objc==1 ) return sqliteCmdUsage(interp, objv);
|
||||
if( objc==2 ){
|
||||
zArg = Tcl_GetStringFromObj(objv[1], 0);
|
||||
if( strcmp(zArg,"-version")==0 ){
|
||||
|
||||
@@ -7038,6 +7038,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
|
||||
extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
@@ -7062,6 +7063,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
|
||||
{ "closure", sqlite3_closure_init },
|
||||
{ "csv", sqlite3_csv_init },
|
||||
{ "eval", sqlite3_eval_init },
|
||||
{ "explain", sqlite3_explain_init },
|
||||
{ "fileio", sqlite3_fileio_init },
|
||||
{ "fuzzer", sqlite3_fuzzer_init },
|
||||
{ "ieee754", sqlite3_ieee_init },
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ static void set_options(Tcl_Interp *interp){
|
||||
STRINGVALUE(SQLITE_MAX_WORKER_THREADS), TCL_GLOBAL_ONLY
|
||||
);
|
||||
|
||||
#if 1 /* def SQLITE_MEMDEBUG */
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY);
|
||||
|
||||
+1
-1
@@ -497,7 +497,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
}else{
|
||||
pFarg = pExpr->x.pList;
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
pWin = pExpr->pWin;
|
||||
pWin = pExpr->y.pWin;
|
||||
#else
|
||||
pWin = 0;
|
||||
#endif
|
||||
|
||||
+56
-6
@@ -79,6 +79,57 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if column iCol of index pIdx references any of the
|
||||
** columns defined by aXRef and chngRowid. Return true if it does
|
||||
** and false if not. 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 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);
|
||||
}
|
||||
|
||||
/*
|
||||
** Process an UPDATE statement.
|
||||
**
|
||||
@@ -302,19 +353,18 @@ void sqlite3Update(
|
||||
/* 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.
|
||||
**
|
||||
** FIXME: Be smarter about omitting indexes that use expressions.
|
||||
*/
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int reg;
|
||||
if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){
|
||||
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++){
|
||||
i16 iIdxCol = pIdx->aiColumn[i];
|
||||
if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
|
||||
if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
|
||||
reg = ++pParse->nMem;
|
||||
pParse->nMem += pIdx->nColumn;
|
||||
if( (onError==OE_Replace)
|
||||
@@ -863,7 +913,7 @@ static void updateVirtualTable(
|
||||
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
|
||||
sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */
|
||||
}
|
||||
}
|
||||
if( HasRowid(pTab) ){
|
||||
|
||||
+26
-12
@@ -2894,17 +2894,25 @@ case OP_MakeRecord: {
|
||||
if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
|
||||
}
|
||||
nByte = nHdr+nData;
|
||||
if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
goto too_big;
|
||||
}
|
||||
|
||||
/* Make sure the output register has a buffer large enough to store
|
||||
** the new record. The output register (pOp->p3) is not allowed to
|
||||
** be one of the input registers (because the following call to
|
||||
** sqlite3VdbeMemClearAndResize() could clobber the value before it is used).
|
||||
*/
|
||||
if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
|
||||
goto no_mem;
|
||||
if( nByte+nZero<=pOut->szMalloc ){
|
||||
/* The output register is already large enough to hold the record.
|
||||
** No error checks or buffer enlargement is required */
|
||||
pOut->z = pOut->zMalloc;
|
||||
}else{
|
||||
/* Need to make sure that the output is not too big and then enlarge
|
||||
** the output register to hold the full result */
|
||||
if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
goto too_big;
|
||||
}
|
||||
if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
|
||||
goto no_mem;
|
||||
}
|
||||
}
|
||||
zNewRecord = (u8 *)pOut->z;
|
||||
|
||||
@@ -5760,7 +5768,7 @@ case OP_ParseSchema: {
|
||||
{
|
||||
zMaster = MASTER_NAME;
|
||||
initData.db = db;
|
||||
initData.iDb = pOp->p1;
|
||||
initData.iDb = iDb;
|
||||
initData.pzErrMsg = &p->zErrMsg;
|
||||
initData.mInitFlags = 0;
|
||||
zSql = sqlite3MPrintf(db,
|
||||
@@ -6957,10 +6965,11 @@ case OP_VFilter: { /* jump */
|
||||
**
|
||||
** If the VColumn opcode is being used to fetch the value of
|
||||
** an unchanging column during an UPDATE operation, then the P5
|
||||
** value is 1. Otherwise, P5 is 0. The P5 value is returned
|
||||
** by sqlite3_vtab_nochange() routine and can be used
|
||||
** by virtual table implementations to return special "no-change"
|
||||
** marks which can be more efficient, depending on the virtual table.
|
||||
** 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: {
|
||||
sqlite3_vtab *pVtab;
|
||||
@@ -6982,7 +6991,8 @@ case OP_VColumn: {
|
||||
assert( pModule->xColumn );
|
||||
memset(&sContext, 0, sizeof(sContext));
|
||||
sContext.pOut = pDest;
|
||||
if( pOp->p5 ){
|
||||
testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 );
|
||||
if( pOp->p5 & OPFLAG_NOCHNG ){
|
||||
sqlite3VdbeMemSetNull(pDest);
|
||||
pDest->flags = MEM_Null|MEM_Zero;
|
||||
pDest->u.nZero = 0;
|
||||
@@ -7059,7 +7069,10 @@ case OP_VNext: { /* jump */
|
||||
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 );
|
||||
@@ -7073,6 +7086,7 @@ case OP_VRename: {
|
||||
rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
rc = pVtab->pModule->xRename(pVtab, pName->z);
|
||||
if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter;
|
||||
sqlite3VtabImportErrmsg(p, pVtab);
|
||||
p->expired = 0;
|
||||
if( rc ) goto abort_due_to_error;
|
||||
|
||||
+3
-1
@@ -4557,7 +4557,9 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
|
||||
(void)getVarint32((u8*)m.z, szHdr);
|
||||
testcase( szHdr==3 );
|
||||
testcase( szHdr==m.n );
|
||||
if( unlikely(szHdr<3 || (int)szHdr>m.n) ){
|
||||
testcase( szHdr>0x7fffffff );
|
||||
assert( m.n>=0 );
|
||||
if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
|
||||
goto idx_rowid_corruption;
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -328,7 +328,6 @@ void sqlite3VtabBeginParse(
|
||||
Token *pModuleName, /* Name of the module for the virtual table */
|
||||
int ifNotExists /* No error if the table already exists */
|
||||
){
|
||||
int iDb; /* The database the table is being created in */
|
||||
Table *pTable; /* The new virtual table */
|
||||
sqlite3 *db; /* Database connection */
|
||||
|
||||
@@ -338,8 +337,6 @@ void sqlite3VtabBeginParse(
|
||||
assert( 0==pTable->pIndex );
|
||||
|
||||
db = pParse->db;
|
||||
iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
|
||||
assert( iDb>=0 );
|
||||
|
||||
assert( pTable->nModuleArg==0 );
|
||||
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
|
||||
@@ -359,6 +356,8 @@ void sqlite3VtabBeginParse(
|
||||
** The second call, to obtain permission to create the table, is made now.
|
||||
*/
|
||||
if( pTable->azModuleArg ){
|
||||
int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
|
||||
assert( iDb>=0 ); /* The database the table is being created in */
|
||||
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
|
||||
pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
|
||||
}
|
||||
@@ -1053,7 +1052,7 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
/* Check to see the left operand is a column in a virtual table */
|
||||
if( NEVER(pExpr==0) ) return pDef;
|
||||
if( pExpr->op!=TK_COLUMN ) return pDef;
|
||||
pTab = pExpr->pTab;
|
||||
pTab = pExpr->y.pTab;
|
||||
if( pTab==0 ) return pDef;
|
||||
if( !IsVirtual(pTab) ) return pDef;
|
||||
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
|
||||
|
||||
+2
-2
@@ -55,8 +55,8 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
|
||||
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){
|
||||
Window *pWin = pExpr->pWin;
|
||||
if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
||||
Window *pWin = pExpr->y.pWin;
|
||||
if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
|
||||
if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
|
||||
if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
|
||||
|
||||
+19
-1
@@ -2126,6 +2126,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
||||
sqlite3 *db = pWInfo->pParse->db;
|
||||
int rc;
|
||||
|
||||
/* Stop the search once we hit the query planner search limit */
|
||||
if( pBuilder->iPlanLimit==0 ){
|
||||
WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n"));
|
||||
if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0;
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
pBuilder->iPlanLimit--;
|
||||
|
||||
/* If pBuilder->pOrSet is defined, then only keep track of the costs
|
||||
** and prereqs.
|
||||
*/
|
||||
@@ -3532,9 +3540,11 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
|
||||
/* Loop over the tables in the join, from left to right */
|
||||
pNew = pBuilder->pNew;
|
||||
whereLoopInit(pNew);
|
||||
pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT;
|
||||
for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
|
||||
Bitmask mUnusable = 0;
|
||||
pNew->iTab = iTab;
|
||||
pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
|
||||
pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
|
||||
if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
|
||||
/* This condition is true when pItem is the FROM clause term on the
|
||||
@@ -3560,7 +3570,15 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
|
||||
rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
|
||||
}
|
||||
mPrior |= pNew->maskSelf;
|
||||
if( rc || db->mallocFailed ) break;
|
||||
if( rc || db->mallocFailed ){
|
||||
if( rc==SQLITE_DONE ){
|
||||
/* We hit the query planner search limit set by iPlanLimit */
|
||||
sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search");
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
whereLoopClear(db, pNew);
|
||||
|
||||
@@ -402,12 +402,33 @@ struct WhereLoopBuilder {
|
||||
int nRecValid; /* Number of valid fields currently in pRec */
|
||||
#endif
|
||||
unsigned int bldFlags; /* SQLITE_BLDF_* flags */
|
||||
unsigned int iPlanLimit; /* Search limiter */
|
||||
};
|
||||
|
||||
/* Allowed values for WhereLoopBuider.bldFlags */
|
||||
#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
|
||||
#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
|
||||
|
||||
/* The 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
|
||||
|
||||
+1
-1
@@ -1117,7 +1117,7 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
|
||||
pExpr->op = TK_COLUMN;
|
||||
pExpr->iTable = pX->iIdxCur;
|
||||
pExpr->iColumn = pX->iIdxCol;
|
||||
pExpr->pTab = 0;
|
||||
pExpr->y.pTab = 0;
|
||||
return WRC_Prune;
|
||||
}else{
|
||||
return WRC_Continue;
|
||||
|
||||
+7
-7
@@ -281,7 +281,7 @@ static int isLikeOrGlob(
|
||||
){
|
||||
if( pLeft->op!=TK_COLUMN
|
||||
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|
||||
|| IsVirtual(pLeft->pTab) /* Value might be numeric */
|
||||
|| IsVirtual(pLeft->y.pTab) /* Value might be numeric */
|
||||
){
|
||||
sqlite3ExprDelete(db, pPrefix);
|
||||
sqlite3ValueFree(pVal);
|
||||
@@ -382,7 +382,7 @@ static int isAuxiliaryVtabOperator(
|
||||
** MATCH(expression,vtab_column)
|
||||
*/
|
||||
pCol = pList->a[1].pExpr;
|
||||
if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
|
||||
if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
|
||||
for(i=0; i<ArraySize(aOp); i++){
|
||||
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
|
||||
*peOp2 = aOp[i].eOp2;
|
||||
@@ -404,12 +404,12 @@ static int isAuxiliaryVtabOperator(
|
||||
** with function names in an arbitrary case.
|
||||
*/
|
||||
pCol = pList->a[0].pExpr;
|
||||
if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
|
||||
if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
|
||||
sqlite3_vtab *pVtab;
|
||||
sqlite3_module *pMod;
|
||||
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
|
||||
void *pNotUsed;
|
||||
pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab;
|
||||
pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
|
||||
assert( pVtab!=0 );
|
||||
assert( pVtab->pModule!=0 );
|
||||
pMod = (sqlite3_module *)pVtab->pModule;
|
||||
@@ -427,10 +427,10 @@ static int isAuxiliaryVtabOperator(
|
||||
int res = 0;
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
Expr *pRight = pExpr->pRight;
|
||||
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
|
||||
if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){
|
||||
res++;
|
||||
}
|
||||
if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
|
||||
if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){
|
||||
res++;
|
||||
SWAP(Expr*, pLeft, pRight);
|
||||
}
|
||||
@@ -1583,7 +1583,7 @@ void sqlite3WhereTabFuncArgs(
|
||||
if( pColRef==0 ) return;
|
||||
pColRef->iTable = pItem->iCursor;
|
||||
pColRef->iColumn = k++;
|
||||
pColRef->pTab = pTab;
|
||||
pColRef->y.pTab = pTab;
|
||||
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
|
||||
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0));
|
||||
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
|
||||
|
||||
+6
-4
@@ -624,12 +624,12 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
|
||||
switch( pExpr->op ){
|
||||
|
||||
case TK_FUNCTION:
|
||||
if( pExpr->pWin==0 ){
|
||||
if( !ExprHasProperty(pExpr, EP_WinFunc) ){
|
||||
break;
|
||||
}else{
|
||||
Window *pWin;
|
||||
for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){
|
||||
if( pExpr->pWin==pWin ){
|
||||
if( pExpr->y.pWin==pWin ){
|
||||
assert( pWin->pOwner==pExpr );
|
||||
return WRC_Prune;
|
||||
}
|
||||
@@ -959,11 +959,13 @@ windowAllocErr:
|
||||
*/
|
||||
void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
|
||||
if( p ){
|
||||
assert( p->op==TK_FUNCTION );
|
||||
/* This routine is only called for the parser. If pWin was not
|
||||
** allocated due to an OOM, then the parser would fail before ever
|
||||
** invoking this routine */
|
||||
if( ALWAYS(pWin) ){
|
||||
p->pWin = pWin;
|
||||
p->y.pWin = pWin;
|
||||
ExprSetProperty(p, EP_WinFunc);
|
||||
pWin->pOwner = p;
|
||||
if( p->flags & EP_Distinct ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
@@ -2126,7 +2128,7 @@ static void windowCodeDefaultStep(
|
||||
*/
|
||||
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
|
||||
Window *pNew = 0;
|
||||
if( p ){
|
||||
if( ALWAYS(p) ){
|
||||
pNew = sqlite3DbMallocZero(db, sizeof(Window));
|
||||
if( pNew ){
|
||||
pNew->zName = sqlite3DbStrDup(db, p->zName);
|
||||
|
||||
+19
-1
@@ -875,5 +875,23 @@ do_execsql_test alter-16.2 {
|
||||
SELECT * FROM t16a_rn ORDER BY a;
|
||||
} {abc 1.25 99 xyzzy cba 5.5 98 fizzle}
|
||||
|
||||
finish_test
|
||||
# 2018-09-16 ticket b41031ea2b5372378cb3d2d43cf9fe2a4a5c2510
|
||||
#
|
||||
ifcapable rtree {
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test alter-17.100 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE VIRTUAL TABLE t2 USING rtree(id,x0,x1);
|
||||
INSERT INTO t1 VALUES(1,'apple'),(2,'fig'),(3,'pear');
|
||||
INSERT INTO t2 VALUES(1,1.0,2.0),(2,2.0,3.0),(3,1.5,3.5);
|
||||
CREATE TRIGGER r1 AFTER UPDATE ON t1 BEGIN
|
||||
DELETE FROM t2 WHERE id = OLD.a;
|
||||
END;
|
||||
ALTER TABLE t1 RENAME TO t3;
|
||||
UPDATE t3 SET b='peach' WHERE a=2;
|
||||
SELECT * FROM t2 ORDER BY 1;
|
||||
} {1 1.0 2.0 3 1.5 3.5}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ set testprefix alterauth
|
||||
set ::auth [list]
|
||||
proc xAuth {type args} {
|
||||
if {$type == "SQLITE_ALTER_TABLE"} {
|
||||
lappend ::auth [concat $type $args]
|
||||
lappend ::auth [concat $type [lrange $args 0 3]]
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# 2018 October 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
|
||||
ifcapable !altertable {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
set testprefix alterauth2
|
||||
|
||||
set ::auth [list]
|
||||
proc xAuth {type args} {
|
||||
lappend ::auth [concat $type [lrange $args 0 3]]
|
||||
if {$type=="SQLITE_READ" && [lindex $args 0] == "t2"} breakpoint
|
||||
return SQLITE_OK
|
||||
}
|
||||
db auth xAuth
|
||||
|
||||
proc do_auth_test {tn sql authcode} {
|
||||
set script "
|
||||
set ::auth \[list\]
|
||||
execsql {$sql}
|
||||
lsort -unique \[set ::auth\]
|
||||
"
|
||||
|
||||
set normal [list {*}$authcode]
|
||||
uplevel [list do_test $tn $script $normal]
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
|
||||
DELETE FROM t1 WHERE a<new.a;
|
||||
END;
|
||||
|
||||
CREATE TEMP TRIGGER tr2 AFTER UPDATE OF a, b ON t1 BEGIN
|
||||
UPDATE t1 SET a=a+1 WHERE new.b<b;
|
||||
END;
|
||||
}
|
||||
|
||||
do_auth_test 1.1 {
|
||||
ALTER TABLE t1 RENAME TO t2;
|
||||
} {
|
||||
{SQLITE_ALTER_TABLE main t1 {} {}}
|
||||
}
|
||||
|
||||
do_auth_test 1.2 {
|
||||
ALTER TABLE t2 RENAME a TO aaa;
|
||||
} {
|
||||
{SQLITE_ALTER_TABLE main t2 {} {}}
|
||||
}
|
||||
|
||||
do_auth_test 1.3 {
|
||||
ALTER TABLE t2 ADD COLUMN d;
|
||||
} {
|
||||
{SQLITE_ALTER_TABLE main t2 {} {}}
|
||||
}
|
||||
|
||||
do_auth_test 1.4 {
|
||||
ALTER TABLE t2 RENAME TO t3;
|
||||
} {
|
||||
{SQLITE_ALTER_TABLE main t2 {} {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,470 @@
|
||||
# 2018 September 20
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix alterlegacy
|
||||
|
||||
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
|
||||
ifcapable !altertable {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE TABLE t1(a, b, CHECK(t1.a != t1.b));
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE INDEX t2expr ON t2(a) WHERE t2.b>0;
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT sql FROM sqlite_master
|
||||
} {
|
||||
{CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))}
|
||||
{CREATE TABLE t2(a, b)}
|
||||
{CREATE INDEX t2expr ON t2(a) WHERE t2.b>0}
|
||||
}
|
||||
|
||||
# Legacy behavior is to corrupt the schema in this case, as the table name in
|
||||
# the CHECK constraint is incorrect after "t1" is renamed. This version is
|
||||
# slightly different - it rejects the change and rolls back the transaction.
|
||||
do_catchsql_test 1.2 {
|
||||
ALTER TABLE t1 RENAME TO t1new;
|
||||
} {1 {no such column: t1.a}}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
CREATE TABLE t3(c, d);
|
||||
ALTER TABLE t3 RENAME TO t3new;
|
||||
DROP TABLE t3new;
|
||||
}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT sql FROM sqlite_master
|
||||
} {
|
||||
{CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))}
|
||||
{CREATE TABLE t2(a, b)}
|
||||
{CREATE INDEX t2expr ON t2(a) WHERE t2.b>0}
|
||||
}
|
||||
|
||||
|
||||
do_catchsql_test 1.3 {
|
||||
ALTER TABLE t2 RENAME TO t2new;
|
||||
} {1 {no such column: t2.b}}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT sql FROM sqlite_master
|
||||
} {
|
||||
{CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))}
|
||||
{CREATE TABLE t2(a, b)}
|
||||
{CREATE INDEX t2expr ON t2(a) WHERE t2.b>0}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
ifcapable vtab {
|
||||
register_echo_module db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE TABLE abc(a, b, c);
|
||||
INSERT INTO abc VALUES(1, 2, 3);
|
||||
CREATE VIRTUAL TABLE eee USING echo('abc');
|
||||
SELECT * FROM eee;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
ALTER TABLE eee RENAME TO fff;
|
||||
SELECT * FROM fff;
|
||||
} {1 2 3}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 2.2 {
|
||||
ALTER TABLE fff RENAME TO ggg;
|
||||
} {1 {no such module: echo}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE TABLE txx(a, b, c);
|
||||
INSERT INTO txx VALUES(1, 2, 3);
|
||||
CREATE VIEW vvv AS SELECT main.txx.a, txx.b, c FROM txx;
|
||||
CREATE VIEW uuu AS SELECT main.one.a, one.b, c FROM txx AS one;
|
||||
CREATE VIEW temp.ttt AS SELECT main.txx.a, txx.b, one.b, main.one.a FROM txx AS one, txx;
|
||||
}
|
||||
|
||||
do_execsql_test 3.1.1 {
|
||||
SELECT * FROM vvv;
|
||||
} {1 2 3}
|
||||
do_execsql_test 3.1.2a {
|
||||
ALTER TABLE txx RENAME TO "t xx";
|
||||
}
|
||||
do_catchsql_test 3.1.2b {
|
||||
SELECT * FROM vvv;
|
||||
} {1 {no such table: main.txx}}
|
||||
do_execsql_test 3.1.3 {
|
||||
SELECT sql FROM sqlite_master WHERE name='vvv';
|
||||
} {{CREATE VIEW vvv AS SELECT main.txx.a, txx.b, c FROM txx}}
|
||||
|
||||
|
||||
do_catchsql_test 3.2.1 {
|
||||
SELECT * FROM uuu;
|
||||
} {1 {no such table: main.txx}}
|
||||
do_execsql_test 3.2.2 {
|
||||
SELECT sql FROM sqlite_master WHERE name='uuu';;
|
||||
} {{CREATE VIEW uuu AS SELECT main.one.a, one.b, c FROM txx AS one}}
|
||||
|
||||
do_catchsql_test 3.3.1 {
|
||||
SELECT * FROM ttt;
|
||||
} {1 {no such table: txx}}
|
||||
do_execsql_test 3.3.2 {
|
||||
SELECT sql FROM sqlite_temp_master WHERE name='ttt';
|
||||
} {{CREATE VIEW ttt AS SELECT main.txx.a, txx.b, one.b, main.one.a FROM txx AS one, txx}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE table t1(x, y);
|
||||
CREATE table t2(a, b);
|
||||
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
|
||||
SELECT t1.x, * FROM t1, t2;
|
||||
INSERT INTO t2 VALUES(new.x, new.y);
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
ALTER TABLE t1 RENAME TO t11;
|
||||
}
|
||||
do_catchsql_test 4.1a {
|
||||
INSERT INTO t11 VALUES(2, 2);
|
||||
} {1 {no such table: main.t1}}
|
||||
do_execsql_test 4.1b {
|
||||
ALTER TABLE t11 RENAME TO t1;
|
||||
ALTER TABLE t2 RENAME TO t22;
|
||||
}
|
||||
do_catchsql_test 4.1c {
|
||||
INSERT INTO t1 VALUES(3, 3);
|
||||
} {1 {no such table: main.t2}}
|
||||
|
||||
proc squish {a} {
|
||||
string trim [regsub -all {[[:space:]][[:space:]]*} $a { }]
|
||||
}
|
||||
db func squish squish
|
||||
do_test 4.2 {
|
||||
execsql { SELECT squish(sql) FROM sqlite_master WHERE name = 'tr1' }
|
||||
} [list [squish {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON "t1" BEGIN
|
||||
SELECT t1.x, * FROM t1, t2;
|
||||
INSERT INTO t2 VALUES(new.x, new.y);
|
||||
END
|
||||
}]]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE TABLE t9(a, b, c);
|
||||
CREATE TABLE t10(a, b, c);
|
||||
CREATE TEMP TABLE t9(a, b, c);
|
||||
|
||||
CREATE TRIGGER temp.t9t AFTER INSERT ON temp.t9 BEGIN
|
||||
INSERT INTO t10 VALUES(new.a, new.b, new.c);
|
||||
END;
|
||||
|
||||
INSERT INTO temp.t9 VALUES(1, 2, 3);
|
||||
SELECT * FROM t10;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
ALTER TABLE temp.t9 RENAME TO 't1234567890'
|
||||
}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
CREATE VIEW v AS SELECT one.a, one.b, t2.a, t2.b FROM t1 AS one, t2;
|
||||
SELECT * FROM v;
|
||||
} {1 2 3 4}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
ALTER TABLE t2 RENAME TO one;
|
||||
} {}
|
||||
|
||||
do_catchsql_test 5.4 {
|
||||
SELECT * FROM v
|
||||
} {1 {no such table: main.t2}}
|
||||
|
||||
do_execsql_test 5.5 {
|
||||
ALTER TABLE one RENAME TO t2;
|
||||
DROP VIEW v;
|
||||
CREATE VIEW temp.vv AS SELECT one.a, one.b, t2.a, t2.b FROM t1 AS one, t2;
|
||||
SELECT * FROM vv;
|
||||
} {1 2 3 4}
|
||||
|
||||
do_execsql_test 5.6 {
|
||||
ALTER TABLE t2 RENAME TO one;
|
||||
} {}
|
||||
do_catchsql_test 5.7 {
|
||||
SELECT * FROM vv
|
||||
} {1 {no such table: t2}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
ifcapable vtab {
|
||||
register_tcl_module db
|
||||
proc tcl_command {method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
return "CREATE TABLE t1(a, b, c)"
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING tcl(tcl_command);
|
||||
}
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
ALTER TABLE x1 RENAME TO x2;
|
||||
SELECT sql FROM sqlite_master WHERE name = 'x2'
|
||||
} {{CREATE VIRTUAL TABLE "x2" USING tcl(tcl_command)}}
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
CREATE TABLE ddd(db, sql, zOld, zNew, bTemp);
|
||||
INSERT INTO ddd VALUES(
|
||||
'main', 'CREATE TABLE x1(i INTEGER, t TEXT)', 'ddd', NULL, 0
|
||||
), (
|
||||
'main', 'CREATE TABLE x1(i INTEGER, t TEXT)', NULL, 'eee', 0
|
||||
), (
|
||||
'main', NULL, 'ddd', 'eee', 0
|
||||
);
|
||||
} {}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 8.1 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
ATTACH 'test.db2' AS aux;
|
||||
PRAGMA foreign_keys = on;
|
||||
CREATE TABLE aux.p1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE aux.c1(x INTEGER PRIMARY KEY, y REFERENCES p1(a));
|
||||
INSERT INTO aux.p1 VALUES(1, 1);
|
||||
INSERT INTO aux.p1 VALUES(2, 2);
|
||||
INSERT INTO aux.c1 VALUES(NULL, 2);
|
||||
CREATE TABLE aux.c2(x INTEGER PRIMARY KEY, y REFERENCES c1(a));
|
||||
}
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
ALTER TABLE aux.p1 RENAME TO ppp;
|
||||
}
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
INSERT INTO aux.c1 VALUES(NULL, 1);
|
||||
SELECT sql FROM aux.sqlite_master WHERE name = 'c1';
|
||||
} {{CREATE TABLE c1(x INTEGER PRIMARY KEY, y REFERENCES "ppp"(a))}}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 9.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t2;
|
||||
}
|
||||
do_execsql_test 9.1 {
|
||||
ALTER TABLE t1 RENAME TO t3;
|
||||
} {}
|
||||
do_execsql_test 9.1b {
|
||||
ALTER TABLE t3 RENAME TO t1;
|
||||
} {}
|
||||
do_execsql_test 9.2 {
|
||||
DROP VIEW v1;
|
||||
CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN
|
||||
INSERT INTO t2 VALUES(new.a);
|
||||
END;
|
||||
}
|
||||
do_execsql_test 9.3 {
|
||||
ALTER TABLE t1 RENAME TO t3;
|
||||
} {}
|
||||
|
||||
forcedelete test.db2
|
||||
do_execsql_test 9.4 {
|
||||
ALTER TABLE t3 RENAME TO t1;
|
||||
DROP TRIGGER tr;
|
||||
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TRIGGER tr AFTER INSERT ON t1 WHEN new.a IS NULL BEGIN SELECT 1, 2, 3; END;
|
||||
|
||||
CREATE TABLE aux.t1(x);
|
||||
CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN SELECT 1, 2, 3; END;
|
||||
}
|
||||
do_execsql_test 9.5 {
|
||||
ALTER TABLE main.t1 RENAME TO t3;
|
||||
}
|
||||
do_execsql_test 9.6 {
|
||||
SELECT sql FROM sqlite_temp_master;
|
||||
SELECT sql FROM sqlite_master WHERE type='trigger';
|
||||
} {
|
||||
{CREATE TRIGGER tr AFTER INSERT ON aux.t1 BEGIN SELECT 1, 2, 3; END}
|
||||
{CREATE TRIGGER tr AFTER INSERT ON "t3" WHEN new.a IS NULL BEGIN SELECT 1, 2, 3; END}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 10.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE VIRTUAL TABLE fff USING fts5(x, y, z);
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
BEGIN;
|
||||
INSERT INTO fff VALUES('a', 'b', 'c');
|
||||
ALTER TABLE fff RENAME TO ggg;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
SELECT * FROM ggg;
|
||||
} {a b c}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
db func trigger trigger
|
||||
set ::trigger [list]
|
||||
proc trigger {args} {
|
||||
lappend ::trigger $args
|
||||
}
|
||||
do_execsql_test 11.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE aux.t1(a, b, c);
|
||||
CREATE TABLE main.t1(a, b, c);
|
||||
CREATE TEMP TRIGGER tr AFTER INSERT ON aux.t1 BEGIN
|
||||
SELECT trigger(new.a, new.b, new.c);
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 11.1 {
|
||||
INSERT INTO main.t1 VALUES(1, 2, 3);
|
||||
INSERT INTO aux.t1 VALUES(4, 5, 6);
|
||||
}
|
||||
do_test 11.2 { set ::trigger } {{4 5 6}}
|
||||
|
||||
do_execsql_test 11.3 {
|
||||
SELECT name, tbl_name FROM sqlite_temp_master;
|
||||
} {tr t1}
|
||||
|
||||
do_execsql_test 11.4 {
|
||||
ALTER TABLE main.t1 RENAME TO t2;
|
||||
SELECT name, tbl_name FROM sqlite_temp_master;
|
||||
} {tr t1}
|
||||
|
||||
do_execsql_test 11.5 {
|
||||
ALTER TABLE aux.t1 RENAME TO t2;
|
||||
SELECT name, tbl_name FROM sqlite_temp_master;
|
||||
} {tr t2}
|
||||
|
||||
do_execsql_test 11.6 {
|
||||
INSERT INTO aux.t2 VALUES(7, 8, 9);
|
||||
}
|
||||
do_test 11.7 { set ::trigger } {{4 5 6} {7 8 9}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 12.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE TABLE t1(a);
|
||||
CREATE TABLE t2(w);
|
||||
CREATE TRIGGER temp.r1 AFTER INSERT ON main.t2 BEGIN
|
||||
INSERT INTO t1(a) VALUES(new.w);
|
||||
END;
|
||||
CREATE TEMP TABLE t2(x);
|
||||
}
|
||||
|
||||
do_execsql_test 12.1 {
|
||||
ALTER TABLE main.t2 RENAME TO t3;
|
||||
}
|
||||
|
||||
do_execsql_test 12.2 {
|
||||
INSERT INTO t3 VALUES('WWW');
|
||||
SELECT * FROM t1;
|
||||
} {WWW}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
ifcapable rtree {
|
||||
do_execsql_test 14.0 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy);
|
||||
|
||||
CREATE TABLE "mytable" ( "fid" INTEGER PRIMARY KEY, "geom" BLOB);
|
||||
|
||||
CREATE TRIGGER tr1 AFTER UPDATE OF "geom" ON "mytable"
|
||||
WHEN OLD."fid" = NEW."fid" AND NEW."geom" IS NULL BEGIN
|
||||
DELETE FROM rt WHERE id = OLD."fid";
|
||||
END;
|
||||
|
||||
INSERT INTO mytable VALUES(1, X'abcd');
|
||||
}
|
||||
|
||||
do_execsql_test 14.1 {
|
||||
UPDATE mytable SET geom = X'1234'
|
||||
}
|
||||
|
||||
do_execsql_test 14.2 {
|
||||
ALTER TABLE mytable RENAME TO mytable_renamed;
|
||||
}
|
||||
|
||||
do_execsql_test 14.3 {
|
||||
CREATE TRIGGER tr2 AFTER INSERT ON mytable_renamed BEGIN
|
||||
DELETE FROM rt WHERE id=(SELECT min(id) FROM rt);
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 14.4 {
|
||||
ALTER TABLE mytable_renamed RENAME TO mytable2;
|
||||
}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 14.5 {
|
||||
PRAGMA legacy_alter_table = 1;
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
CREATE TRIGGER xyz AFTER INSERT ON t1 BEGIN
|
||||
SELECT a, b FROM v1;
|
||||
END;
|
||||
}
|
||||
do_execsql_test 14.6 {
|
||||
ALTER TABLE t1 RENAME TO tt1;
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -19,7 +19,7 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
|
||||
ifcapable !altertable||!memdebug {
|
||||
ifcapable !altertable {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
@@ -72,4 +72,30 @@ do_faultsim_test 3 -prep {
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE rr(a, b);
|
||||
CREATE VIEW vv AS SELECT * FROM rr;
|
||||
|
||||
CREATE TRIGGER vv1 INSTEAD OF INSERT ON vv BEGIN
|
||||
SELECT 1, 2, 3;
|
||||
END;
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON rr BEGIN
|
||||
INSERT INTO vv VALUES(new.a, new.b);
|
||||
END;
|
||||
} {}
|
||||
|
||||
faultsim_save_and_close
|
||||
do_faultsim_test 4 -faults oom-* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql { SELECT * FROM sqlite_master }
|
||||
} -body {
|
||||
execsql {
|
||||
ALTER TABLE rr RENAME a TO c;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -411,5 +411,98 @@ do_catchsql_test 13.2 {
|
||||
ALTER TABLE t2 RENAME b TO y;
|
||||
} {1 {error in trigger tr1 after rename: ambiguous column name: y}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
ifcapable rtree {
|
||||
do_execsql_test 14.0 {
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy);
|
||||
|
||||
CREATE TABLE "mytable" ( "fid" INTEGER PRIMARY KEY, "geom" BLOB);
|
||||
|
||||
CREATE TRIGGER tr1 AFTER UPDATE OF "geom" ON "mytable"
|
||||
WHEN OLD."fid" = NEW."fid" AND NEW."geom" IS NULL BEGIN
|
||||
DELETE FROM rt WHERE id = OLD."fid";
|
||||
END;
|
||||
|
||||
INSERT INTO mytable VALUES(1, X'abcd');
|
||||
}
|
||||
|
||||
do_execsql_test 14.1 {
|
||||
UPDATE mytable SET geom = X'1234'
|
||||
}
|
||||
|
||||
do_execsql_test 14.2 {
|
||||
ALTER TABLE mytable RENAME TO mytable_renamed;
|
||||
}
|
||||
|
||||
do_execsql_test 14.3 {
|
||||
CREATE TRIGGER tr2 AFTER INSERT ON mytable_renamed BEGIN
|
||||
DELETE FROM rt WHERE id=(SELECT min(id) FROM rt);
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 14.4 {
|
||||
ALTER TABLE mytable_renamed RENAME TO mytable2;
|
||||
}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 14.5 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
CREATE TRIGGER xyz AFTER INSERT ON t1 BEGIN
|
||||
SELECT a, b FROM v1;
|
||||
END;
|
||||
}
|
||||
do_execsql_test 14.6 {
|
||||
ALTER TABLE t1 RENAME TO tt1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 15.0 {
|
||||
CREATE TABLE t1(a integer NOT NULL PRIMARY KEY);
|
||||
CREATE VIEW v1 AS SELECT a FROM t1;
|
||||
CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
|
||||
UPDATE t1 SET a = NEW.a;
|
||||
END;
|
||||
CREATE TRIGGER tr2 INSTEAD OF INSERT ON v1 BEGIN
|
||||
SELECT new.a;
|
||||
END;
|
||||
CREATE TABLE t2 (b);
|
||||
}
|
||||
|
||||
do_execsql_test 15.1 {
|
||||
INSERT INTO v1 VALUES(1);
|
||||
ALTER TABLE t2 RENAME TO t3;
|
||||
}
|
||||
|
||||
do_execsql_test 15.2 {
|
||||
CREATE TABLE x(f1 integer NOT NULL);
|
||||
CREATE VIEW y AS SELECT f1 AS f1 FROM x;
|
||||
CREATE TRIGGER t INSTEAD OF UPDATE OF f1 ON y BEGIN
|
||||
UPDATE x SET f1 = NEW.f1;
|
||||
END;
|
||||
CREATE TABLE z (f1 integer NOT NULL PRIMARY KEY);
|
||||
ALTER TABLE z RENAME TO z2;
|
||||
}
|
||||
|
||||
do_execsql_test 15.3 {
|
||||
INSERT INTO x VALUES(1), (2), (3);
|
||||
ALTER TABLE x RENAME f1 TO f2;
|
||||
SELECT * FROM x;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 15.4 {
|
||||
UPDATE y SET f1 = 'x' WHERE f1 = 1;
|
||||
SELECT * FROM x;
|
||||
} {x x x}
|
||||
|
||||
do_execsql_test 15.5 {
|
||||
SELECT sql FROM sqlite_master WHERE name = 'y';
|
||||
} {{CREATE VIEW y AS SELECT f2 AS f1 FROM x}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# 2018 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix altertab
|
||||
|
||||
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
|
||||
ifcapable !altertable {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE rr(a, b);
|
||||
CREATE VIRTUAL TABLE ff USING fts5(a, b);
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON rr BEGIN
|
||||
INSERT INTO ff VALUES(new.a, new.b);
|
||||
END;
|
||||
INSERT INTO rr VALUES('hello', 'world');
|
||||
SELECT * FROM ff;
|
||||
} {hello world}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
ALTER TABLE ff RENAME TO ffff;
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
INSERT INTO rr VALUES('in', 'tcl');
|
||||
SELECT * FROM ffff;
|
||||
} {hello world in tcl}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !memdebug||!attach {
|
||||
ifcapable !attach {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
+2
-1
@@ -2598,7 +2598,8 @@ do_test auth-8.2 {
|
||||
# invocation with no column name specified, compilation fails.
|
||||
#
|
||||
set ::authargs [list]
|
||||
proc auth {op a b c d} {
|
||||
proc auth {op args} {
|
||||
foreach {a b c d} $args break
|
||||
lappend ::authargs $op $a $b $c $d
|
||||
if {$op == "SQLITE_READ"} { return "SQLITE_DENY" }
|
||||
return "SQLITE_OK"
|
||||
|
||||
@@ -811,7 +811,6 @@ foreach {code english} $code2english {
|
||||
|
||||
# Test the error message when a "real" out of memory occurs.
|
||||
if { [permutation] != "nofaultsim" } {
|
||||
ifcapable memdebug {
|
||||
do_test capi3-10-1 {
|
||||
sqlite3 db test.db
|
||||
set DB [sqlite3_connection_pointer db]
|
||||
@@ -849,7 +848,6 @@ ifcapable memdebug {
|
||||
db close
|
||||
sqlite3_memdebug_fail -1
|
||||
}
|
||||
}
|
||||
|
||||
# The following tests - capi3-11.* - test that a COMMIT or ROLLBACK
|
||||
# statement issued while there are still outstanding VMs that are part of
|
||||
|
||||
@@ -757,7 +757,6 @@ foreach {code english} $code2english {
|
||||
|
||||
# Test the error message when a "real" out of memory occurs.
|
||||
if { [permutation] != "nofaultsim" } {
|
||||
ifcapable memdebug {
|
||||
do_test capi3c-10-1 {
|
||||
sqlite3 db test.db
|
||||
set DB [sqlite3_connection_pointer db]
|
||||
@@ -777,7 +776,6 @@ ifcapable memdebug {
|
||||
db close
|
||||
sqlite3_memdebug_fail -1
|
||||
}
|
||||
}
|
||||
|
||||
# The following tests - capi3c-11.* - test that a COMMIT or ROLLBACK
|
||||
# statement issued while there are still outstanding VMs that are part of
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ source $testdir/tester.tcl
|
||||
|
||||
# Only run these tests if memory debugging is turned on.
|
||||
#
|
||||
ifcapable !memdebug||!crashtest||!memorymanage {
|
||||
ifcapable !crashtest||!memorymanage {
|
||||
puts "Skipping crash5 tests: not compiled with -DSQLITE_MEMDEBUG..."
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -17,11 +17,6 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !memdebug {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/fuzz_common.tcl
|
||||
|
||||
|
||||
Binary file not shown.
@@ -16,7 +16,7 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix incrblob_err
|
||||
|
||||
ifcapable {!incrblob || !memdebug || !tclvar} {
|
||||
ifcapable {!incrblob || !tclvar} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
@@ -159,5 +159,75 @@ do_execsql_test 3.4.6 {
|
||||
SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE binary;
|
||||
} {.ABC1 1 .ABC3 3 .abc2 2 .abc4 4}
|
||||
|
||||
# 2014-09-15: Verify that UPDATEs of columns not referenced by a
|
||||
# index on expression do not modify the index.
|
||||
#
|
||||
unset -nocomplain cnt
|
||||
set cnt 0
|
||||
proc refcnt {x} {
|
||||
global cnt
|
||||
incr cnt
|
||||
return $x
|
||||
}
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
db function refcnt -deterministic refcnt
|
||||
do_test 4.100 {
|
||||
db eval {
|
||||
CREATE TABLE t1(a,b,c,d,e,f);
|
||||
CREATE INDEX t1abc ON t1(refcnt(a+b+c));
|
||||
}
|
||||
set ::cnt
|
||||
} {0}
|
||||
do_test 4.110 {
|
||||
db eval {INSERT INTO t1 VALUES(1,2,3,4,5,6);}
|
||||
set ::cnt
|
||||
# The refcnt() function is invoked once to compute the index value
|
||||
} {1}
|
||||
do_test 4.120 {
|
||||
set ::cnt 0
|
||||
db eval {UPDATE t1 SET b=b+1;}
|
||||
set ::cnt
|
||||
# The refcnt() function is invoked twice, once to remove the old index
|
||||
# entry and a second time to insert the new one.
|
||||
} {2}
|
||||
do_test 4.130 {
|
||||
set ::cnt 0
|
||||
db eval {UPDATE t1 SET d=d+1;}
|
||||
set ::cnt
|
||||
# Refcnt() should not be invoked because that index does not change.
|
||||
} {0}
|
||||
|
||||
# Additional test cases to show that UPDATE does not modify indexes that
|
||||
# do not involve unchanged columns.
|
||||
#
|
||||
load_static_extension db explain
|
||||
do_execsql_test 4.200 {
|
||||
CREATE TABLE t2(a,b,c,d,e,f);
|
||||
INSERT INTO t2 VALUES(2,3,4,5,6,7);
|
||||
CREATE INDEX t2abc ON t2(a+b+c);
|
||||
CREATE INDEX t2cd ON t2(c*d);
|
||||
CREATE INDEX t2def ON t2(d,e+25*f);
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET b=b+1')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc}
|
||||
do_execsql_test 4.210 {
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET c=c+1')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc t2cd}
|
||||
do_execsql_test 4.220 {
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET c=c+1, f=NULL')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc t2cd t2def}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -130,12 +130,14 @@ do_eqp_test like3-5.101 {
|
||||
do_execsql_test like3-5.110 {
|
||||
SELECT x FROM t5a WHERE x LIKE '/a%';
|
||||
} {/abc}
|
||||
ifcapable !icu {
|
||||
do_eqp_test like3-5.111 {
|
||||
SELECT x FROM t5a WHERE x LIKE '/a%';
|
||||
} {
|
||||
QUERY PLAN
|
||||
`--SEARCH TABLE t5a USING COVERING INDEX sqlite_autoindex_t5a_1 (x>? AND x<?)
|
||||
}
|
||||
}
|
||||
do_execsql_test like3-5.120 {
|
||||
SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
|
||||
} {123}
|
||||
|
||||
+4
-1
@@ -24,7 +24,7 @@ ifcapable !lookaside {
|
||||
# The tests in this file configure the lookaside allocator after a
|
||||
# connection is opened. This will not work if there is any "presql"
|
||||
# configured (SQL run within the [sqlite3] wrapper in tester.tcl).
|
||||
if {[info exists ::G(perm:presql)]} {
|
||||
if {[info exists ::G(perm:dbconfig)] && $::G(perm:dbconfig)!=""} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
@@ -35,7 +35,9 @@ catch {db close}
|
||||
sqlite3_shutdown
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
|
||||
sqlite3 db test.db
|
||||
db cache size 4
|
||||
|
||||
# Make sure sqlite3_db_config() and sqlite3_db_status are working.
|
||||
#
|
||||
@@ -99,6 +101,7 @@ do_test lookaside-2.2 {
|
||||
expr {$x==0 && $y<$z && $z>10 && $z<100}
|
||||
} {1}
|
||||
do_test lookaside-2.3 {
|
||||
db eval {SELECT 1}
|
||||
sqlite3_db_config_lookaside db 0 50 50
|
||||
} {5} ;# SQLITE_BUSY
|
||||
do_test lookaside-2.4 {
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
|
||||
package require sqlite3
|
||||
package require Tk
|
||||
|
||||
#############################################################################
|
||||
# Code to set up scrollbars for widgets. This is generic, boring stuff.
|
||||
#
|
||||
namespace eval autoscroll {
|
||||
proc scrollable {widget path args} {
|
||||
::ttk::frame $path
|
||||
set w [$widget ${path}.widget {*}$args]
|
||||
set vs [::ttk::scrollbar ${path}.vs]
|
||||
set hs [::ttk::scrollbar ${path}.hs -orient horizontal]
|
||||
grid $w -row 0 -column 0 -sticky nsew
|
||||
|
||||
grid rowconfigure $path 0 -weight 1
|
||||
grid columnconfigure $path 0 -weight 1
|
||||
|
||||
set grid [list grid $vs -row 0 -column 1 -sticky nsew]
|
||||
$w configure -yscrollcommand [list ::autoscroll::scrollcommand $grid $vs]
|
||||
$vs configure -command [list $w yview]
|
||||
set grid [list grid $hs -row 1 -column 0 -sticky nsew]
|
||||
$w configure -xscrollcommand [list ::autoscroll::scrollcommand $grid $hs]
|
||||
$hs configure -command [list $w xview]
|
||||
|
||||
return $w
|
||||
}
|
||||
proc scrollcommand {grid sb args} {
|
||||
$sb set {*}$args
|
||||
set isRequired [expr {[lindex $args 0] != 0.0 || [lindex $args 1] != 1.0}]
|
||||
if {$isRequired && ![winfo ismapped $sb]} {
|
||||
{*}$grid
|
||||
}
|
||||
if {!$isRequired && [winfo ismapped $sb]} {
|
||||
grid forget $sb
|
||||
}
|
||||
}
|
||||
namespace export scrollable
|
||||
}
|
||||
namespace import ::autoscroll::*
|
||||
#############################################################################
|
||||
|
||||
proc populate_text_widget {db} {
|
||||
$::O(text) configure -state normal
|
||||
set id [lindex [$::O(tree) selection] 0]
|
||||
set frame [lindex $id end]
|
||||
|
||||
set line [$db one {SELECT line FROM frame WHERE frame = $frame}]
|
||||
if {$line ne ""} {
|
||||
foreach {file line} [split $line :] {}
|
||||
set content [$db one "SELECT content FROM file WHERE name = '$file'"]
|
||||
$::O(text) delete 0.0 end
|
||||
|
||||
set iLine 1
|
||||
foreach L [split $content "\n"] {
|
||||
if {$iLine == $line} {
|
||||
$::O(text) insert end "$L\n" highlight
|
||||
} else {
|
||||
$::O(text) insert end "$L\n"
|
||||
}
|
||||
incr iLine
|
||||
}
|
||||
$::O(text) yview -pickplace ${line}.0
|
||||
}
|
||||
$::O(text) configure -state disabled
|
||||
}
|
||||
|
||||
proc populate_index {db} {
|
||||
$::O(text) configure -state normal
|
||||
|
||||
$::O(text) delete 0.0 end
|
||||
$::O(text) insert end "\n\n"
|
||||
|
||||
set L [format " % -40s%12s%12s\n" "Test Case" "Allocations" "Bytes"]
|
||||
$::O(text) insert end $L
|
||||
$::O(text) insert end " [string repeat - 64]\n"
|
||||
|
||||
$db eval {
|
||||
SELECT 'TOTAL' AS ztest, sum(ncall) AS calls, sum(nbyte) AS bytes
|
||||
FROM malloc
|
||||
UNION ALL
|
||||
SELECT ztest AS ztest, sum(ncall) AS calls, sum(nbyte) AS bytes
|
||||
FROM malloc
|
||||
GROUP BY ztest
|
||||
|
||||
ORDER BY 3 DESC
|
||||
} {
|
||||
set tags [list $ztest]
|
||||
if {$ztest eq $::O(current)} {
|
||||
lappend tags highlight
|
||||
}
|
||||
set L [format " % -40s%12s%12s\n" $ztest $calls $bytes]
|
||||
$::O(text) insert end $L $tags
|
||||
|
||||
$::O(text) tag bind $ztest <1> [list populate_tree_widget $db $ztest]
|
||||
$::O(text) tag bind $ztest <Enter> [list $::O(text) configure -cursor hand2]
|
||||
$::O(text) tag bind $ztest <Leave> [list $::O(text) configure -cursor ""]
|
||||
}
|
||||
|
||||
$::O(text) configure -state disabled
|
||||
}
|
||||
|
||||
proc sort_tree_compare {iLeft iRight} {
|
||||
global O
|
||||
switch -- [expr (int($O(tree_sort)/2))] {
|
||||
0 {
|
||||
set left [$O(tree) item $iLeft -text]
|
||||
set right [$O(tree) item $iRight -text]
|
||||
set res [string compare $left $right]
|
||||
}
|
||||
1 {
|
||||
set left [lindex [$O(tree) item $iLeft -values] 0]
|
||||
set right [lindex [$O(tree) item $iRight -values] 0]
|
||||
set res [expr $left - $right]
|
||||
}
|
||||
2 {
|
||||
set left [lindex [$O(tree) item $iLeft -values] 1]
|
||||
set right [lindex [$O(tree) item $iRight -values] 1]
|
||||
set res [expr $left - $right]
|
||||
}
|
||||
}
|
||||
if {$O(tree_sort)&0x01} {
|
||||
set res [expr -1 * $res]
|
||||
}
|
||||
return $res
|
||||
}
|
||||
|
||||
proc sort_tree {iMode} {
|
||||
global O
|
||||
if {$O(tree_sort) == $iMode} {
|
||||
incr O(tree_sort)
|
||||
} else {
|
||||
set O(tree_sort) $iMode
|
||||
}
|
||||
set T $O(tree)
|
||||
set items [$T children {}]
|
||||
set items [lsort -command sort_tree_compare $items]
|
||||
for {set ii 0} {$ii < [llength $items]} {incr ii} {
|
||||
$T move [lindex $items $ii] {} $ii
|
||||
}
|
||||
}
|
||||
|
||||
proc trim_frames {stack} {
|
||||
while {[info exists ::O(ignore.[lindex $stack 0])]} {
|
||||
set stack [lrange $stack 1 end]
|
||||
}
|
||||
return $stack
|
||||
}
|
||||
|
||||
proc populate_tree_widget {db zTest} {
|
||||
$::O(tree) delete [$::O(tree) children {}]
|
||||
|
||||
for {set ii 0} {$ii < 15} {incr ii} {
|
||||
$db eval {
|
||||
SELECT
|
||||
sum(ncall) AS calls,
|
||||
sum(nbyte) AS bytes,
|
||||
trim_frames(lrange(lstack, 0, $ii)) AS stack
|
||||
FROM malloc
|
||||
WHERE (zTest = $zTest OR $zTest = 'TOTAL') AND llength(lstack)>$ii
|
||||
GROUP BY stack
|
||||
HAVING stack != ''
|
||||
} {
|
||||
set parent_id [lrange $stack 0 end-1]
|
||||
set frame [lindex $stack end]
|
||||
set line [$db one {SELECT line FROM frame WHERE frame = $frame}]
|
||||
set line [lindex [split $line /] end]
|
||||
set v [list $calls $bytes]
|
||||
|
||||
catch {
|
||||
$::O(tree) insert $parent_id end -id $stack -text $line -values $v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set ::O(current) $zTest
|
||||
populate_index $db
|
||||
}
|
||||
|
||||
|
||||
|
||||
set O(tree_sort) 0
|
||||
|
||||
::ttk::panedwindow .pan -orient horizontal
|
||||
set O(tree) [scrollable ::ttk::treeview .pan.tree]
|
||||
|
||||
frame .pan.right
|
||||
set O(text) [scrollable text .pan.right.text]
|
||||
button .pan.right.index -command {populate_index mddb} -text "Show Index"
|
||||
pack .pan.right.index -side top -fill x
|
||||
pack .pan.right.text -fill both -expand true
|
||||
|
||||
$O(text) tag configure highlight -background wheat
|
||||
$O(text) configure -wrap none -height 35
|
||||
|
||||
.pan add .pan.tree
|
||||
.pan add .pan.right
|
||||
|
||||
$O(tree) configure -columns {calls bytes}
|
||||
$O(tree) heading #0 -text Line -anchor w -command {sort_tree 0}
|
||||
$O(tree) heading calls -text Calls -anchor w -command {sort_tree 2}
|
||||
$O(tree) heading bytes -text Bytes -anchor w -command {sort_tree 4}
|
||||
$O(tree) column #0 -width 150
|
||||
$O(tree) column calls -width 100
|
||||
$O(tree) column bytes -width 100
|
||||
|
||||
pack .pan -fill both -expand 1
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Open the database containing the malloc data. The user specifies the
|
||||
# database to use by passing the file-name on the command line.
|
||||
#
|
||||
proc open_database {} {
|
||||
if {[info exists ::BUILTIN]} {
|
||||
sqlite3 mddb :memory:
|
||||
mddb eval $::BUILTIN
|
||||
wm title . $::argv0
|
||||
} else {
|
||||
set zFilename [lindex $::argv 0]
|
||||
if {$zFilename eq ""} {
|
||||
set zFilename mallocs.sql
|
||||
}
|
||||
set fd [open $zFilename]
|
||||
set zHdr [read $fd 15]
|
||||
if {$zHdr eq "SQLite format 3"} {
|
||||
close $fd
|
||||
sqlite3 mddb $zFilename
|
||||
} else {
|
||||
seek $fd 0
|
||||
sqlite3 mddb :memory:
|
||||
mddb eval [read $fd]
|
||||
close $fd
|
||||
}
|
||||
wm title . $zFilename
|
||||
}
|
||||
|
||||
mddb function lrange -argcount 3 lrange
|
||||
mddb function llength -argcount 1 llength
|
||||
mddb function trim_frames -argcount 1 trim_frames
|
||||
|
||||
mddb eval {
|
||||
SELECT frame FROM frame
|
||||
WHERE line LIKE '%malloc.c:%' OR line LIKE '%mem2.c:%'
|
||||
} {
|
||||
set ::O(ignore.$frame) 1
|
||||
}
|
||||
}
|
||||
|
||||
open_database
|
||||
bind $O(tree) <<TreeviewSelect>> [list populate_text_widget mddb]
|
||||
|
||||
populate_tree_widget mddb [mddb one {SELECT zTest FROM malloc LIMIT 1}]
|
||||
|
||||
+67
-63
@@ -48,6 +48,13 @@ proc test_suite {name args} {
|
||||
set options([lindex $o 0]) $v
|
||||
}
|
||||
|
||||
# Transform "-presql" into a "dbconfig" script
|
||||
#
|
||||
if {[info exists options(-presql)]} {
|
||||
append options(-dbconfig) "\n\$::dbhandle eval { $options(-presql) }"
|
||||
unset options(-presql)
|
||||
}
|
||||
|
||||
set ::testspec($name) [array get options]
|
||||
lappend ::testsuitelist $name
|
||||
}
|
||||
@@ -289,12 +296,6 @@ test_suite "window" -prefix "" -description {
|
||||
test_set [glob -nocomplain $::testdir/window*.test]
|
||||
]
|
||||
|
||||
test_suite "alter" -prefix "" -description {
|
||||
All ALTER function related tests .
|
||||
} -files [
|
||||
test_set [glob -nocomplain $::testdir/alter*.test]
|
||||
]
|
||||
|
||||
test_suite "lsm1" -prefix "" -description {
|
||||
All LSM1 tests.
|
||||
} -files [glob -nocomplain $::testdir/../ext/lsm1/test/*.test]
|
||||
@@ -560,21 +561,12 @@ test_suite "singlethread" -description {
|
||||
test_suite "nomutex" -description {
|
||||
Tests run with the SQLITE_OPEN_MULTITHREADED flag passed to sqlite3_open().
|
||||
} -initialize {
|
||||
rename sqlite3 sqlite3_nomutex
|
||||
proc sqlite3 {args} {
|
||||
if {[string range [lindex $args 0] 0 0] ne "-"} {
|
||||
lappend args -fullmutex 0 -nomutex 1
|
||||
}
|
||||
uplevel [concat sqlite3_nomutex $args]
|
||||
}
|
||||
set ::G(perm:sqlite3_args) [list -fullmutex 0 -nomutex 1]
|
||||
} -files {
|
||||
delete.test delete2.test insert.test rollback.test select1.test
|
||||
select2.test trans.test update.test vacuum.test types.test
|
||||
types2.test types3.test
|
||||
} -shutdown {
|
||||
rename sqlite3 {}
|
||||
rename sqlite3_nomutex sqlite3
|
||||
}
|
||||
}
|
||||
|
||||
# Run some tests in SQLITE_CONFIG_MULTITHREAD mode.
|
||||
#
|
||||
@@ -603,20 +595,11 @@ test_suite "multithread" -description {
|
||||
test_suite "fullmutex" -description {
|
||||
Tests run in SQLITE_OPEN_FULLMUTEX mode
|
||||
} -initialize {
|
||||
rename sqlite3 sqlite3_fullmutex
|
||||
proc sqlite3 {args} {
|
||||
if {[string range [lindex $args 0] 0 0] ne "-"} {
|
||||
lappend args -nomutex 0 -fullmutex 1
|
||||
}
|
||||
uplevel [concat sqlite3_fullmutex $args]
|
||||
}
|
||||
set ::G(perm:sqlite3_args) [list -nomutex 0 -fullmutex 1]
|
||||
} -files {
|
||||
delete.test delete2.test insert.test rollback.test select1.test
|
||||
select2.test trans.test update.test vacuum.test types.test
|
||||
types2.test types3.test
|
||||
} -shutdown {
|
||||
rename sqlite3 {}
|
||||
rename sqlite3_fullmutex sqlite3
|
||||
}
|
||||
|
||||
# Run some tests using the "onefile" demo.
|
||||
@@ -624,19 +607,10 @@ test_suite "fullmutex" -description {
|
||||
test_suite "onefile" -description {
|
||||
Run some tests using the "test_onefile.c" demo
|
||||
} -initialize {
|
||||
rename sqlite3 sqlite3_onefile
|
||||
proc sqlite3 {args} {
|
||||
if {[string range [lindex $args 0] 0 0] ne "-"} {
|
||||
lappend args -vfs fs
|
||||
}
|
||||
uplevel [concat sqlite3_onefile $args]
|
||||
}
|
||||
set ::G(perm:sqlite3_args) [list -vfs fs]
|
||||
} -files {
|
||||
conflict.test insert.test insert2.test insert3.test
|
||||
rollback.test select1.test select2.test select3.test
|
||||
} -shutdown {
|
||||
rename sqlite3 {}
|
||||
rename sqlite3_onefile sqlite3
|
||||
}
|
||||
|
||||
# Run some tests using UTF-16 databases.
|
||||
@@ -938,17 +912,8 @@ ifcapable threadsafe {
|
||||
test_suite "safe_append" -description {
|
||||
Run some tests on a SAFE_APPEND file-system.
|
||||
} -initialize {
|
||||
rename sqlite3 sqlite3_safeappend
|
||||
proc sqlite3 {args} {
|
||||
if {[string range [lindex $args 0] 0 0] ne "-"} {
|
||||
lappend args -vfs devsym
|
||||
}
|
||||
uplevel [concat sqlite3_safeappend $args]
|
||||
}
|
||||
set ::G(perm:sqlite3_args) [list -vfs devsym]
|
||||
sqlite3_simulate_device -char safe_append
|
||||
} -shutdown {
|
||||
rename sqlite3 {}
|
||||
rename sqlite3_shutdown sqlite3
|
||||
} -files [
|
||||
test_set $::allquicktests shared_err.test -exclude async3.test
|
||||
]
|
||||
@@ -1115,16 +1080,20 @@ test_suite "sorterref" -prefix "" -description {
|
||||
# -description TITLE
|
||||
# -initialize SCRIPT
|
||||
# -shutdown SCRIPT
|
||||
# -presql SQL
|
||||
# -files LIST-OF-FILES
|
||||
# -prefix NAME
|
||||
# -dbconfig SCRIPT
|
||||
#
|
||||
proc run_tests {name args} {
|
||||
set options(-initialize) ""
|
||||
set options(-shutdown) ""
|
||||
set options(-prefix) ""
|
||||
set options(-dbconfig) ""
|
||||
|
||||
array set options $args
|
||||
|
||||
set ::G(perm:name) $name
|
||||
set ::G(perm:prefix) $options(-prefix)
|
||||
set ::G(perm:presql) $options(-presql)
|
||||
set ::G(isquick) 1
|
||||
set ::G(perm:dbconfig) $options(-dbconfig)
|
||||
|
||||
@@ -1133,11 +1102,12 @@ proc run_tests {name args} {
|
||||
if {[file tail $file] == $file} { set file [file join $::testdir $file] }
|
||||
slave_test_file $file
|
||||
uplevel $options(-shutdown)
|
||||
|
||||
unset -nocomplain ::G(perm:sqlite3_args)
|
||||
}
|
||||
|
||||
unset ::G(perm:name)
|
||||
unset ::G(perm:prefix)
|
||||
unset ::G(perm:presql)
|
||||
unset ::G(perm:dbconfig)
|
||||
}
|
||||
|
||||
@@ -1152,19 +1122,29 @@ proc help {} {
|
||||
puts "Usage: $::argv0 TESTSUITE ?TESTFILE?"
|
||||
puts ""
|
||||
puts "Available test-suites are:"
|
||||
|
||||
set iPos 0
|
||||
foreach k $::testsuitelist {
|
||||
if {[info exists ::testspec($k)]==0} {
|
||||
puts " ----------------------------------------"
|
||||
puts ""
|
||||
} else {
|
||||
array set o $::testspec($k)
|
||||
puts "Test suite: \"$k\""
|
||||
set d [string trim $o(-description)]
|
||||
set d [regsub {\n *} $d "\n "]
|
||||
puts " $d"
|
||||
puts ""
|
||||
if {[info exists ::testspec($k)]} {
|
||||
switch $iPos {
|
||||
0 {
|
||||
puts ""
|
||||
puts -nonewline " [format %-30s $k]"
|
||||
}
|
||||
|
||||
1 {
|
||||
puts -nonewline [format %-30s $k]
|
||||
}
|
||||
|
||||
2 {
|
||||
puts -nonewline $k
|
||||
}
|
||||
}
|
||||
|
||||
set iPos [expr (($iPos+1) % 3)]
|
||||
}
|
||||
}
|
||||
puts ""
|
||||
exit -1
|
||||
}
|
||||
|
||||
@@ -1173,11 +1153,35 @@ if {[file tail $argv0] == "permutations.test"} {
|
||||
if {[llength $argv]==0} {
|
||||
help
|
||||
} else {
|
||||
|
||||
# See if the first argument is a named test-suite.
|
||||
#
|
||||
set suite [file tail [lindex $argv 0]]
|
||||
if {[info exists ::testspec($suite)]==0} help
|
||||
if {[info exists ::testspec($suite)]} {
|
||||
set S $::testspec($suite)
|
||||
set i 1
|
||||
} else {
|
||||
set S [list]
|
||||
set i 0
|
||||
}
|
||||
|
||||
set extra ""
|
||||
if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] }
|
||||
eval run_tests $suite $::testspec($suite) $extra
|
||||
if {$i < [llength $argv] && [string range [lindex $argv $i] 0 0]!="-" } {
|
||||
set files [list]
|
||||
for {} {$i < [llength $argv]} {incr i} {
|
||||
set pattern [string map {% *} [lindex $argv $i]]
|
||||
if {[string range $pattern 0 0]=="-"} break
|
||||
foreach f $::alltests {
|
||||
set tail [file tail $f]
|
||||
if {[lsearch $files $f]<0 && [string match $pattern $tail]} {
|
||||
lappend files $f
|
||||
}
|
||||
}
|
||||
}
|
||||
set extra [list -files $files]
|
||||
}
|
||||
|
||||
eval run_tests $suite $S $extra
|
||||
}
|
||||
}
|
||||
main $argv
|
||||
|
||||
+17
-19
@@ -3757,25 +3757,23 @@ do_test printf-15.3 {
|
||||
|
||||
# Now test malloc() failure within a sqlite3_mprintf():
|
||||
#
|
||||
ifcapable memdebug {
|
||||
foreach var {a b c d} {
|
||||
set $var [string repeat $var 400]
|
||||
}
|
||||
set str1 "[string repeat A 360]%d%d%s"
|
||||
set str2 [string repeat B 5000]
|
||||
set zSuccess "[string repeat A 360]11[string repeat B 5000]"
|
||||
foreach ::iRepeat {0 1} {
|
||||
set nTestNum 1
|
||||
while {1} {
|
||||
sqlite3_memdebug_fail $nTestNum -repeat $::iRepeat
|
||||
set z [sqlite3_mprintf_str $str1 1 1 $str2]
|
||||
set nFail [sqlite3_memdebug_fail -1 -benign nBenign]
|
||||
do_test printf-malloc-$::iRepeat.$nTestNum {
|
||||
expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)}
|
||||
} {1}
|
||||
if {$nFail == 0} break
|
||||
incr nTestNum
|
||||
}
|
||||
foreach var {a b c d} {
|
||||
set $var [string repeat $var 400]
|
||||
}
|
||||
set str1 "[string repeat A 360]%d%d%s"
|
||||
set str2 [string repeat B 5000]
|
||||
set zSuccess "[string repeat A 360]11[string repeat B 5000]"
|
||||
foreach ::iRepeat {0 1} {
|
||||
set nTestNum 1
|
||||
while {1} {
|
||||
sqlite3_memdebug_fail $nTestNum -repeat $::iRepeat
|
||||
set z [sqlite3_mprintf_str $str1 1 1 $str2]
|
||||
set nFail [sqlite3_memdebug_fail -1 -benign nBenign]
|
||||
do_test printf-malloc-$::iRepeat.$nTestNum {
|
||||
expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)}
|
||||
} {1}
|
||||
if {$nFail == 0} break
|
||||
incr nTestNum
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
-DSQLITE_THREADSAFE
|
||||
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
|
||||
-DSQLITE_USER_AUTHENTICATION=1
|
||||
}
|
||||
"Secure-Delete" {
|
||||
-O2
|
||||
|
||||
+1
-1
@@ -378,7 +378,7 @@ do_test shell1-3.10.1 {
|
||||
} {1 1 1}
|
||||
do_test shell1-3.10.2 {
|
||||
# we allow .help to take extra args (it is help after all)
|
||||
set res [catchcmd "test.db" ".help BAD"]
|
||||
set res [catchcmd "test.db" ".help *"]
|
||||
# look for a few of the possible help commands
|
||||
list [regexp {.help} $res] \
|
||||
[regexp {.quit} $res] \
|
||||
|
||||
@@ -28,6 +28,9 @@ load_static_extension db remember
|
||||
do_execsql_test tabfunc01-1.1 {
|
||||
SELECT *, '|' FROM generate_series WHERE start=1 AND stop=9 AND step=2;
|
||||
} {1 | 3 | 5 | 7 | 9 |}
|
||||
do_execsql_test tabfunc01-1.1b {
|
||||
PRAGMA table_xinfo(generate_series);
|
||||
} {0 value {} 0 {} 0 0 1 start {} 0 {} 0 1 2 stop {} 0 {} 0 1 3 step {} 0 {} 0 1}
|
||||
do_execsql_test tabfunc01-1.2 {
|
||||
SELECT *, '|' FROM generate_series LIMIT 5;
|
||||
} {0 | 1 | 2 | 3 | 4 |}
|
||||
|
||||
+11
-15
@@ -22,9 +22,7 @@ ifcapable !gettable {
|
||||
return
|
||||
}
|
||||
|
||||
ifcapable memdebug {
|
||||
source $testdir/malloc_common.tcl
|
||||
}
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
do_test tableapi-1.0 {
|
||||
set ::dbx [sqlite3_open test.db]
|
||||
@@ -239,18 +237,16 @@ do_test tableapi-99.0 {
|
||||
sqlite3_close $::dbx
|
||||
} {SQLITE_OK}
|
||||
|
||||
ifcapable memdebug {
|
||||
do_malloc_test tableapi-7 -sqlprep {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t1 VALUES(3,4);
|
||||
INSERT INTO t1 SELECT a+4, b+4 FROM t1;
|
||||
INSERT INTO t1 SELECT a+8, b+8 FROM t1;
|
||||
} -tclbody {
|
||||
set r [sqlite3_get_table_printf db {SELECT rowid, a, b FROM t1} {}]
|
||||
if {[llength $r]<26} {error "out of memory"}
|
||||
}
|
||||
do_malloc_test tableapi-7 -sqlprep {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t1 VALUES(3,4);
|
||||
INSERT INTO t1 SELECT a+4, b+4 FROM t1;
|
||||
INSERT INTO t1 SELECT a+8, b+8 FROM t1;
|
||||
} -tclbody {
|
||||
set r [sqlite3_get_table_printf db {SELECT rowid, a, b FROM t1} {}]
|
||||
if {[llength $r]<26} {error "out of memory"}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#
|
||||
# $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $
|
||||
|
||||
catch {sqlite3}
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
@@ -31,6 +33,11 @@ do_test tcl-1.1 {
|
||||
regsub {really_sqlite3} $msg {sqlite3} msg
|
||||
lappend v $msg
|
||||
} [list 1 "wrong # args: should be \"$r\""]
|
||||
do_test tcl-1.1.1 {
|
||||
set v [catch {sqlite3} msg]
|
||||
regsub {really_sqlite3} $msg {sqlite3} msg
|
||||
lappend v $msg
|
||||
} [list 1 "wrong # args: should be \"$r\""]
|
||||
do_test tcl-1.2 {
|
||||
set v [catch {db bogus} msg]
|
||||
lappend v $msg
|
||||
|
||||
+23
-9
@@ -456,6 +456,11 @@ if {[info exists cmdlinearg]==0} {
|
||||
{^-+malloctrace=.+$} {
|
||||
foreach {dummy cmdlinearg(malloctrace)} [split $a =] break
|
||||
if {$cmdlinearg(malloctrace)} {
|
||||
if {0==$::sqlite_options(memdebug)} {
|
||||
set err "Error: --malloctrace=1 requires an SQLITE_MEMDEBUG build"
|
||||
puts stderr $err
|
||||
exit 1
|
||||
}
|
||||
sqlite3_memdebug_log start
|
||||
}
|
||||
}
|
||||
@@ -1258,13 +1263,13 @@ proc finalize_testing {} {
|
||||
output2 "Unfreed memory: [sqlite3_memory_used] bytes in\
|
||||
[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations"
|
||||
incr nErr
|
||||
ifcapable memdebug||mem5||(mem3&&debug) {
|
||||
ifcapable mem5||(mem3&&debug) {
|
||||
output2 "Writing unfreed memory log to \"./memleak.txt\""
|
||||
sqlite3_memdebug_dump ./memleak.txt
|
||||
}
|
||||
} else {
|
||||
output2 "All memory allocations freed - no leaks"
|
||||
ifcapable memdebug||mem5 {
|
||||
ifcapable mem5 {
|
||||
sqlite3_memdebug_dump ./memusage.txt
|
||||
}
|
||||
}
|
||||
@@ -1275,15 +1280,14 @@ proc finalize_testing {} {
|
||||
output2 "Number of malloc() : [sqlite3_memdebug_malloc_count] calls"
|
||||
}
|
||||
if {$::cmdlinearg(malloctrace)} {
|
||||
output2 "Writing mallocs.sql..."
|
||||
memdebug_log_sql
|
||||
output2 "Writing mallocs.tcl..."
|
||||
memdebug_log_sql mallocs.tcl
|
||||
sqlite3_memdebug_log stop
|
||||
sqlite3_memdebug_log clear
|
||||
|
||||
if {[sqlite3_memory_used]>0} {
|
||||
output2 "Writing leaks.sql..."
|
||||
output2 "Writing leaks.tcl..."
|
||||
sqlite3_memdebug_log sync
|
||||
memdebug_log_sql leaks.sql
|
||||
memdebug_log_sql leaks.tcl
|
||||
}
|
||||
}
|
||||
foreach f [glob -nocomplain test.db-*-journal] {
|
||||
@@ -2019,7 +2023,7 @@ proc dbcksum {db dbname} {
|
||||
return [md5 $txt]
|
||||
}
|
||||
|
||||
proc memdebug_log_sql {{filename mallocs.sql}} {
|
||||
proc memdebug_log_sql {filename} {
|
||||
|
||||
set data [sqlite3_memdebug_log dump]
|
||||
set nFrame [expr [llength [lindex $data 0]]-2]
|
||||
@@ -2065,8 +2069,18 @@ proc memdebug_log_sql {{filename mallocs.sql}} {
|
||||
append sql "INSERT INTO ${database}.file VALUES('$f', '$contents');\n"
|
||||
}
|
||||
|
||||
set escaped "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
|
||||
set escaped [string map [list "{" "\\{" "}" "\\}"] $escaped]
|
||||
|
||||
set fd [open $filename w]
|
||||
puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
|
||||
puts $fd "set BUILTIN {"
|
||||
puts $fd $escaped
|
||||
puts $fd "}"
|
||||
puts $fd {set BUILTIN [string map [list "\\{" "{" "\\}" "}"] $BUILTIN]}
|
||||
set mtv [open $::testdir/malloctraceviewer.tcl]
|
||||
set txt [read $mtv]
|
||||
close $mtv
|
||||
puts $fd $txt
|
||||
close $fd
|
||||
}
|
||||
|
||||
|
||||
@@ -200,13 +200,6 @@ do_test triggerA-2.11 {
|
||||
}
|
||||
} {3 305 3 9900305 4 404 4 9900404 5 504 5 9900504}
|
||||
|
||||
# Only run the reamining tests if memory debugging is turned on.
|
||||
#
|
||||
ifcapable !memdebug {
|
||||
puts "Skipping triggerA malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
# Save a copy of the current database configuration.
|
||||
|
||||
+4
-3
@@ -682,7 +682,8 @@ do_test view-25.1 {
|
||||
}
|
||||
proc authLogDelete {code arg1 arg2 arg3 arg4 args} {
|
||||
if {$code=="SQLITE_DELETE" && [string match sqlite_stat* $arg1]} {
|
||||
lappend ::log [list $code $arg1 $arg2 $arg3 $arg4 $args]
|
||||
# lappend ::log [list $code $arg1 $arg2 $arg3 $arg4 $args]
|
||||
lappend ::log [list $code $arg1 $arg2 $arg3 $arg4]
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
@@ -692,8 +693,8 @@ do_test view-25.1 {
|
||||
set log
|
||||
} {}
|
||||
|
||||
set res [list {SQLITE_DELETE sqlite_stat1 {} main {} {}}]
|
||||
ifcapable stat4 { lappend res {SQLITE_DELETE sqlite_stat4 {} main {} {}} }
|
||||
set res [list {SQLITE_DELETE sqlite_stat1 {} main {}}]
|
||||
ifcapable stat4 { lappend res {SQLITE_DELETE sqlite_stat4 {} main {}} }
|
||||
do_test view-25.2 {
|
||||
set log ""
|
||||
db eval {DROP TABLE t25;}
|
||||
|
||||
@@ -40,11 +40,6 @@ do_ioerr_test vtab_err-1 -tclprep {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
ifcapable !memdebug {
|
||||
puts "Skipping vtab_err-2 tests: not compiled with -DSQLITE_MEMDEBUG..."
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
|
||||
|
||||
+23
-1
@@ -526,5 +526,27 @@ do_catchsql_test 11.4 {
|
||||
CREATE INDEX t6i ON t6(lead(b) OVER ());
|
||||
} {1 {misuse of window function lead()}}
|
||||
|
||||
finish_test
|
||||
# 2018-09-17 ticket 510cde277783b5fb5de628393959849dff377eb3
|
||||
# Endless loop on a query with window functions and a limit
|
||||
#
|
||||
do_execsql_test 12.100 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(id INT, b VARCHAR, c VARCHAR);
|
||||
INSERT INTO t1 VALUES(1, 'A', 'one');
|
||||
INSERT INTO t1 VALUES(2, 'B', 'two');
|
||||
INSERT INTO t1 VALUES(3, 'C', 'three');
|
||||
INSERT INTO t1 VALUES(4, 'D', 'one');
|
||||
INSERT INTO t1 VALUES(5, 'E', 'two');
|
||||
SELECT id, b, lead(c,1) OVER(ORDER BY c) AS x
|
||||
FROM t1 WHERE id>1
|
||||
ORDER BY b LIMIT 1;
|
||||
} {2 B two}
|
||||
do_execsql_test 12.110 {
|
||||
INSERT INTO t1 VALUES(6, 'F', 'three');
|
||||
INSERT INTO t1 VALUES(7, 'G', 'one');
|
||||
SELECT id, b, lead(c,1) OVER(ORDER BY c) AS x
|
||||
FROM t1 WHERE id>1
|
||||
ORDER BY b LIMIT 2;
|
||||
} {2 B two 3 C three}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -358,6 +358,32 @@ execsql_test 10.3 {
|
||||
SELECT id, lag(b, -1) OVER (PARTITION BY a ORDER BY id) FROM t7;
|
||||
}
|
||||
|
||||
execsql_test 11.0 {
|
||||
DROP VIEW IF EXISTS v8;
|
||||
DROP TABLE IF EXISTS t8;
|
||||
CREATE TABLE t8(t INT, total INT);
|
||||
INSERT INTO t8 VALUES(0,2);
|
||||
INSERT INTO t8 VALUES(5,1);
|
||||
INSERT INTO t8 VALUES(10,1);
|
||||
}
|
||||
|
||||
execsql_test 11.1 {
|
||||
SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8;
|
||||
}
|
||||
|
||||
execsql_test 11.2 {
|
||||
CREATE VIEW v8 AS SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8;
|
||||
}
|
||||
|
||||
execsql_test 11.3 {
|
||||
SELECT * FROM v8;
|
||||
}
|
||||
|
||||
execsql_test 11.4 {
|
||||
SELECT * FROM (
|
||||
SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8
|
||||
) sub;
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+57
-9
@@ -1217,13 +1217,20 @@ do_execsql_test 9.2 {
|
||||
SELECT dense_rank() OVER (PARTITION BY x) FROM t2
|
||||
} {1 1 1 1 1 1 1}
|
||||
|
||||
|
||||
do_test 9.3 {
|
||||
set myres {}
|
||||
foreach r [db eval {SELECT x, percent_rank() OVER (PARTITION BY x ORDER BY x) FROM t2}] {
|
||||
lappend myres [format %.2f [set r]]
|
||||
lappend myres [format %.4f [set r]]
|
||||
}
|
||||
set myres
|
||||
} {1.00 0.00 1.00 0.00 1.00 0.00 4.00 0.00 4.00 0.00 6.00 0.00 7.00 0.00}
|
||||
set res2 {1.0000 0.0000 1.0000 0.0000 1.0000 0.0000 4.0000 0.0000 4.0000 0.0000 6.0000 0.0000 7.0000 0.0000}
|
||||
foreach r [set myres] r2 [set res2] {
|
||||
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
|
||||
error "list element [set i] does not match: got=[set r] expected=[set r2]"
|
||||
}
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
do_execsql_test 9.4 {
|
||||
SELECT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2
|
||||
@@ -1233,21 +1240,35 @@ do_execsql_test 9.5 {
|
||||
SELECT DISTINCT x, rank() OVER (ORDER BY x) FROM t2 ORDER BY 1,2
|
||||
} {1 1 4 4 6 6 7 7}
|
||||
|
||||
|
||||
do_test 9.6 {
|
||||
set myres {}
|
||||
foreach r [db eval {SELECT percent_rank() OVER () FROM t1}] {
|
||||
lappend myres [format %.2f [set r]]
|
||||
lappend myres [format %.4f [set r]]
|
||||
}
|
||||
set myres
|
||||
} {0.00 0.00 0.00}
|
||||
set res2 {0.0000 0.0000 0.0000}
|
||||
foreach r [set myres] r2 [set res2] {
|
||||
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
|
||||
error "list element [set i] does not match: got=[set r] expected=[set r2]"
|
||||
}
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
|
||||
do_test 9.7 {
|
||||
set myres {}
|
||||
foreach r [db eval {SELECT cume_dist() OVER () FROM t1}] {
|
||||
lappend myres [format %.2f [set r]]
|
||||
lappend myres [format %.4f [set r]]
|
||||
}
|
||||
set myres
|
||||
} {1.00 1.00 1.00}
|
||||
set res2 {1.0000 1.0000 1.0000}
|
||||
foreach r [set myres] r2 [set res2] {
|
||||
if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
|
||||
error "list element [set i] does not match: got=[set r] expected=[set r2]"
|
||||
}
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
do_execsql_test 10.0 {
|
||||
DROP TABLE IF EXISTS t7;
|
||||
@@ -1269,4 +1290,31 @@ do_execsql_test 10.3 {
|
||||
SELECT id, lag(b, -1) OVER (PARTITION BY a ORDER BY id) FROM t7;
|
||||
} {1 {} 2 4 3 {} 4 8 5 1 6 {}}
|
||||
|
||||
do_execsql_test 11.0 {
|
||||
DROP VIEW IF EXISTS v8;
|
||||
DROP TABLE IF EXISTS t8;
|
||||
CREATE TABLE t8(t INT, total INT);
|
||||
INSERT INTO t8 VALUES(0,2);
|
||||
INSERT INTO t8 VALUES(5,1);
|
||||
INSERT INTO t8 VALUES(10,1);
|
||||
} {}
|
||||
|
||||
do_execsql_test 11.1 {
|
||||
SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8;
|
||||
} {0 1 2}
|
||||
|
||||
do_execsql_test 11.2 {
|
||||
CREATE VIEW v8 AS SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8;
|
||||
} {}
|
||||
|
||||
do_execsql_test 11.3 {
|
||||
SELECT * FROM v8;
|
||||
} {0 1 2}
|
||||
|
||||
do_execsql_test 11.4 {
|
||||
SELECT * FROM (
|
||||
SELECT NTILE(256) OVER (ORDER BY total) - 1 AS nt FROM t8
|
||||
) sub;
|
||||
} {0 1 2}
|
||||
|
||||
finish_test
|
||||
|
||||
+16
-15
@@ -147,17 +147,17 @@ do_execsql_test 5.5 {
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
SELECT LIKE('!', '', '!') x WHERE x;
|
||||
} {}
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
SELECT LIKE("!","","!")""WHeRE"";
|
||||
} {}
|
||||
|
||||
do_catchsql_test 6.2 {
|
||||
SELECT LIKE("!","","!")""window"";
|
||||
} {1 {near "window": syntax error}}
|
||||
ifcapable !icu {
|
||||
do_execsql_test 6.0 {
|
||||
SELECT LIKE('!', '', '!') x WHERE x;
|
||||
} {}
|
||||
do_execsql_test 6.1 {
|
||||
SELECT LIKE("!","","!")""WHeRE"";
|
||||
} {}
|
||||
do_catchsql_test 6.2 {
|
||||
SELECT LIKE("!","","!")""window"";
|
||||
} {1 {near "window": syntax error}}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
@@ -166,9 +166,11 @@ do_execsql_test 7.0 {
|
||||
INSERT INTO t1 VALUES('');
|
||||
}
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
SELECT count(*) FROM t1 WHERE x LIKE '!' ESCAPE '!';
|
||||
} {0}
|
||||
ifcapable !icu {
|
||||
do_execsql_test 7.1 {
|
||||
SELECT count(*) FROM t1 WHERE x LIKE '!' ESCAPE '!';
|
||||
} {0}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -336,4 +338,3 @@ do_execsql_test 11.2 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -865,6 +865,27 @@ do_catchsql_test 16.1 {
|
||||
SELECT * FROM i;
|
||||
} {1 {recursive aggregate queries not supported}}
|
||||
|
||||
# Or window-function recursive queries. Ticket e8275b41.
|
||||
#
|
||||
ifcapable windowfunc {
|
||||
do_catchsql_test 16.2 {
|
||||
WITH RECURSIVE
|
||||
i(x) AS (VALUES(1) UNION SELECT count(*) OVER () FROM i)
|
||||
SELECT * FROM i;
|
||||
} {1 {cannot use window functions in recursive queries}}
|
||||
do_catchsql_test 16.3 {
|
||||
WITH RECURSIVE
|
||||
t(id, parent) AS (VALUES(1,2)),
|
||||
q(id, parent, rn) AS (
|
||||
VALUES(1,2,3)
|
||||
UNION ALL
|
||||
SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rn
|
||||
FROM q JOIN t ON t.parent = q.id
|
||||
)
|
||||
SELECT * FROM q;
|
||||
} {1 {cannot use window functions in recursive queries}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 17.1 {
|
||||
WITH x(a) AS (
|
||||
|
||||
+41
-8
@@ -220,9 +220,17 @@ set pragma_def {
|
||||
|
||||
NAME: table_info
|
||||
FLAG: NeedSchema Result1 SchemaOpt
|
||||
ARG: 0
|
||||
COLS: cid name type notnull dflt_value pk
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: table_xinfo
|
||||
TYPE: TABLE_INFO
|
||||
FLAG: NeedSchema Result1 SchemaOpt
|
||||
ARG: 1
|
||||
COLS: cid name type notnull dflt_value pk hidden
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: stats
|
||||
FLAG: NeedSchema Result0 SchemaReq
|
||||
COLS: tbl idx wdth hght flgs
|
||||
@@ -382,6 +390,11 @@ set pragma_def {
|
||||
|
||||
NAME: optimize
|
||||
FLAG: Result1 NeedSchema
|
||||
|
||||
NAME: legacy_alter_table
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_LegacyAlter
|
||||
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
||||
}
|
||||
|
||||
# Open the output file
|
||||
@@ -405,20 +418,20 @@ set cols {}
|
||||
set cols_list {}
|
||||
set arg 0
|
||||
proc record_one {} {
|
||||
global name type if arg allbyname typebyif flags cols allcols
|
||||
global name type if arg allbyname typebyif flags cols all_cols
|
||||
global cols_list colUsedBy
|
||||
if {$name==""} return
|
||||
if {$cols!=""} {
|
||||
if {![info exists allcols($cols)]} {
|
||||
if {![info exists all_cols($cols)]} {
|
||||
set all_cols($cols) 1
|
||||
lappend cols_list $cols
|
||||
set allcols($cols) [llength $cols_list]
|
||||
}
|
||||
set cx $allcols($cols)
|
||||
set cx $cols
|
||||
lappend colUsedBy($cols) $name
|
||||
} else {
|
||||
set cx 0
|
||||
}
|
||||
set allbyname($name) [list $type $arg $if $flags $cx]
|
||||
set allbyname($name) [list $type $arg $if $flags $cols]
|
||||
set name {}
|
||||
set type {}
|
||||
set if {}
|
||||
@@ -500,6 +513,13 @@ foreach f [lsort [array names allflags]] {
|
||||
set fv [expr {$fv*2}]
|
||||
}
|
||||
|
||||
# Sort the column lists so that longer column lists occur first
|
||||
#
|
||||
proc colscmp {a b} {
|
||||
return [expr {[llength $b] - [llength $a]}]
|
||||
}
|
||||
set cols_list [lsort -command colscmp $cols_list]
|
||||
|
||||
# Generate the array of column names used by pragmas that act like
|
||||
# queries.
|
||||
#
|
||||
@@ -508,10 +528,23 @@ puts $fd "** or that return single-column results where the name of the"
|
||||
puts $fd "** result column is different from the name of the pragma\n*/"
|
||||
puts $fd "static const char *const pragCName\[\] = {"
|
||||
set offset 0
|
||||
set allcollist {}
|
||||
foreach cols $cols_list {
|
||||
set cols_offset($allcols($cols)) $offset
|
||||
set n [llength $cols]
|
||||
set limit [expr {[llength $allcollist] - $n}]
|
||||
for {set i 0} {$i<$limit} {incr i} {
|
||||
set sublist [lrange $allcollist $i [expr {$i+$n-1}]]
|
||||
if {$sublist==$cols} {
|
||||
puts $fd [format "%27s/* $colUsedBy($cols) reuses $i */" ""]
|
||||
set cols_offset($cols) $i
|
||||
break
|
||||
}
|
||||
}
|
||||
if {$i<$limit} continue
|
||||
set cols_offset($cols) $offset
|
||||
set ub " /* Used by: $colUsedBy($cols) */"
|
||||
foreach c $cols {
|
||||
lappend allcollist $c
|
||||
puts $fd [format " /* %3d */ %-14s%s" $offset \"$c\", $ub]
|
||||
set ub ""
|
||||
incr offset
|
||||
@@ -537,12 +570,12 @@ set current_if {}
|
||||
set spacer [format { %26s } {}]
|
||||
foreach name $allnames {
|
||||
foreach {type arg if flag cx} $allbyname($name) break
|
||||
if {$cx==0} {
|
||||
if {$cx==0 || $cx==""} {
|
||||
set cy 0
|
||||
set nx 0
|
||||
} else {
|
||||
set cy $cols_offset($cx)
|
||||
set nx [llength [lindex $cols_list [expr {$cx-1}]]]
|
||||
set nx [llength $cx]
|
||||
}
|
||||
if {$if!=$current_if} {
|
||||
if {$current_if!=""} {
|
||||
|
||||
Reference in New Issue
Block a user