Compare commits

..

2 Commits

Author SHA1 Message Date
dan d49a37a8ef Fix an RBU problem with restarting an update after the *-oal file is already larger than 4GiB.
FossilOrigin-Name: 56869f54f31186231a4467f10208bcc08d9edae23c6e21831d6d3dff47da51de
2021-08-11 18:56:49 +00:00
dan 86732babe3 If the special "sqlite_rbu_replace_hack" table is present in an RBU database, use REPLACE instead of INSERT when writing index entries to imposter tables.
FossilOrigin-Name: 4b73e151cdb4b89bdd2f1bab5c0378500234ce6c479cc1d8cd4e006be79d1162
2021-08-11 18:44:50 +00:00
72 changed files with 898 additions and 2320 deletions
+5 -1
View File
@@ -1242,6 +1242,10 @@ fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuz
./fuzzcheck$(TEXE) $(FUZZDATA)
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
@@ -1259,7 +1263,7 @@ quicktest: ./testfixture$(TEXE)
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: fuzztest sourcetest $(TESTPROGS) tcltest
test: fastfuzztest sourcetest $(TESTPROGS) tcltest
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
+4 -1
View File
@@ -2404,6 +2404,9 @@ queryplantest: testfixture.exe shell
fuzztest: fuzzcheck.exe
.\fuzzcheck.exe $(FUZZDATA)
fastfuzztest: fuzzcheck.exe
.\fuzzcheck.exe --limit-mem 100M $(FUZZDATA)
# Minimal testing that runs in less than 3 minutes (on a fast machine)
#
quicktest: testfixture.exe sourcetest
@@ -2413,7 +2416,7 @@ quicktest: testfixture.exe sourcetest
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: $(TESTPROGS) sourcetest fuzztest
test: $(TESTPROGS) sourcetest fastfuzztest
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
+1 -1
View File
@@ -1 +1 @@
3.31.0
3.30.0
+1
View File
@@ -282,6 +282,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.31.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.30.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.31.0'
PACKAGE_STRING='sqlite 3.31.0'
PACKAGE_VERSION='3.30.0'
PACKAGE_STRING='sqlite 3.30.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.31.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.30.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.31.0:";;
short | recursive ) echo "Configuration of sqlite 3.30.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.31.0
sqlite configure 3.30.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.31.0, which was
It was created by sqlite $as_me 3.30.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.31.0, which was
This file was extended by sqlite $as_me 3.30.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.31.0
sqlite config.status 3.30.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+11 -25
View File
@@ -3482,10 +3482,7 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
int rc;
sqlite3_stmt *pAllLangid = 0;
rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK ){
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
}
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
if( rc==SQLITE_OK ){
int rc2;
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
@@ -3506,6 +3503,7 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
}
sqlite3Fts3SegmentsClose(p);
sqlite3Fts3PendingTermsClear(p);
return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
}
@@ -4950,15 +4948,8 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
}
if( SQLITE_OK==rc && pCsr->nSegment==nSeg
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
){
int bEmpty = 0;
rc = sqlite3Fts3SegReaderStep(p, pCsr);
if( rc==SQLITE_OK ){
bEmpty = 1;
}else if( rc!=SQLITE_ROW ){
sqlite3Fts3SegReaderFinish(pCsr);
break;
}
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
@@ -4969,13 +4960,11 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
if( rc==SQLITE_OK && pWriter->nLeafEst ){
fts3LogMerge(nSeg, iAbsLevel);
if( bEmpty==0 ){
do {
rc = fts3IncrmergeAppend(p, pWriter, pCsr);
if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
}while( rc==SQLITE_ROW );
}
do {
rc = fts3IncrmergeAppend(p, pWriter, pCsr);
if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
}while( rc==SQLITE_ROW );
/* Update or delete the input segments */
if( rc==SQLITE_OK ){
@@ -5182,11 +5171,7 @@ static u64 fts3ChecksumIndex(
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
}else{
pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
if( p->bDescIdx ){
iDocid -= iVal;
}else{
iDocid += iVal;
}
iDocid += iVal;
}
}else{
iPos += (iVal - 2);
@@ -5259,9 +5244,10 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
if( p->abNotindexed[iCol]==0 ){
const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
int nText = sqlite3_column_bytes(pStmt, iCol+1);
sqlite3_tokenizer_cursor *pT = 0;
rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT);
rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
int nToken = 0; /* Number of bytes in token */
-10
View File
@@ -61,11 +61,6 @@ typedef sqlite3_uint64 u64;
*/
#define FTS5_MAX_PREFIX_INDEXES 31
/*
** Maximum segments permitted in a single index
*/
#define FTS5_MAX_SEGMENT 2000
#define FTS5_DEFAULT_NEARDIST 10
#define FTS5_DEFAULT_RANK "bm25"
@@ -422,11 +417,6 @@ int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch);
*/
void sqlite3Fts5IterClose(Fts5IndexIter*);
/*
** Close the reader blob handle, if it is open.
*/
void sqlite3Fts5IndexCloseReader(Fts5Index*);
/*
** This interface is used by the fts5vocab module.
*/
+2 -3
View File
@@ -23,7 +23,7 @@
#define FTS5_DEFAULT_HASHSIZE (1024*1024)
/* Maximum allowed page size */
#define FTS5_MAX_PAGE_SIZE (64*1024)
#define FTS5_MAX_PAGE_SIZE (128*1024)
static int fts5_iswhitespace(char x){
return (x==' ');
@@ -828,7 +828,7 @@ int sqlite3Fts5ConfigSetValue(
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
pgsz = sqlite3_value_int(pVal);
}
if( pgsz<32 || pgsz>FTS5_MAX_PAGE_SIZE ){
if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){
*pbBadkey = 1;
}else{
pConfig->pgsz = pgsz;
@@ -881,7 +881,6 @@ int sqlite3Fts5ConfigSetValue(
*pbBadkey = 1;
}else{
if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
if( nCrisisMerge>=FTS5_MAX_SEGMENT ) nCrisisMerge = FTS5_MAX_SEGMENT-1;
pConfig->nCrisisMerge = nCrisisMerge;
}
}
+12 -10
View File
@@ -239,6 +239,11 @@
#define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno)
#define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno)
/*
** Maximum segments permitted in a single index
*/
#define FTS5_MAX_SEGMENT 2000
#ifdef SQLITE_DEBUG
int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; }
#endif
@@ -614,7 +619,7 @@ static int fts5LeafFirstTermOff(Fts5Data *pLeaf){
/*
** Close the read-only blob handle, if it is open.
*/
void sqlite3Fts5IndexCloseReader(Fts5Index *p){
static void fts5CloseReader(Fts5Index *p){
if( p->pReader ){
sqlite3_blob *pReader = p->pReader;
p->pReader = 0;
@@ -643,7 +648,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
assert( p->pReader==0 );
p->pReader = pBlob;
if( rc!=SQLITE_OK ){
sqlite3Fts5IndexCloseReader(p);
fts5CloseReader(p);
}
if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
}
@@ -5204,7 +5209,7 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
int sqlite3Fts5IndexSync(Fts5Index *p){
assert( p->rc==SQLITE_OK );
fts5IndexFlush(p);
sqlite3Fts5IndexCloseReader(p);
fts5CloseReader(p);
return fts5IndexReturn(p);
}
@@ -5215,7 +5220,7 @@ int sqlite3Fts5IndexSync(Fts5Index *p){
** records must be invalidated.
*/
int sqlite3Fts5IndexRollback(Fts5Index *p){
sqlite3Fts5IndexCloseReader(p);
fts5CloseReader(p);
fts5IndexDiscardData(p);
fts5StructureInvalidate(p);
/* assert( p->rc==SQLITE_OK ); */
@@ -5230,7 +5235,6 @@ int sqlite3Fts5IndexRollback(Fts5Index *p){
int sqlite3Fts5IndexReinit(Fts5Index *p){
Fts5Structure s;
fts5StructureInvalidate(p);
fts5IndexDiscardData(p);
memset(&s, 0, sizeof(Fts5Structure));
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
fts5StructureWrite(p, &s);
@@ -5318,7 +5322,6 @@ int sqlite3Fts5IndexCharlenToBytelen(
for(i=0; i<nChar; i++){
if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
if( (unsigned char)p[n++]>=0xc0 ){
if( n>=nByte ) break;
while( (p[n] & 0xc0)==0x80 ){
n++;
if( n>=nByte ) break;
@@ -5457,7 +5460,7 @@ int sqlite3Fts5IndexQuery(
if( p->rc ){
sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
pRet = 0;
sqlite3Fts5IndexCloseReader(p);
fts5CloseReader(p);
}
*ppIter = (Fts5IndexIter*)pRet;
@@ -5530,7 +5533,7 @@ void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5Index *pIndex = pIter->pIndex;
fts5MultiIterFree(pIter);
sqlite3Fts5IndexCloseReader(pIndex);
fts5CloseReader(pIndex);
}
}
@@ -5887,8 +5890,7 @@ static void fts5IndexIntegrityCheckSegment(
if( pSeg->pgnoFirst==0 ) return;
fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
"SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d "
"ORDER BY 1, 2",
"SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d",
pConfig->zDb, pConfig->zName, pSeg->iSegid
));
-1
View File
@@ -744,7 +744,6 @@ static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
sqlite3_free(pCsr->zRankArgs);
}
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr));
}
-2
View File
@@ -560,8 +560,6 @@ int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
Fts5Config *pConfig = p->pConfig;
int rc;
p->bTotalsValid = 0;
/* Delete the contents of the %_data and %_docsize tables. */
rc = fts5ExecPrintf(pConfig->db, 0,
"DELETE FROM %Q.'%q_data';"
+1 -1
View File
@@ -4484,7 +4484,7 @@ do_test 36.0 {
do_catchsql_test 36.1 {
INSERT INTO t1(b) VALUES(
x'78de3fa24af3733ca8769291a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bfef346e6a');
} {0 {}}
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
+1 -1
View File
@@ -36,7 +36,7 @@ do_test 1.1 {
execsql { INSERT INTO x8 VALUES( rnddoc(5) ); }
}
} msg] $msg
} {0 {}}
} {1 {database or disk is full}}
finish_test
-26
View File
@@ -491,30 +491,4 @@ do_catchsql_test 14.2 {
SELECT matchinfo(x1, 'd') FROM x1('a b c');
} {1 {unrecognized matchinfo flag: d}}
#-------------------------------------------------------------------------
# Test using matchinfo() and similar on a non-full-text query
#
do_execsql_test 15.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x, y);
INSERT INTO t1 VALUES('a', 'b');
INSERT INTO t1 VALUES('c', 'd');
}
do_execsql_test 15.1 {
SELECT quote(matchinfo(t1, 'n')) FROM t1 LIMIT 1;
} {X'02000000'}
do_execsql_test 15.2 {
DELETE FROM t1_content WHERE rowid=1;
SELECT quote(matchinfo(t1, 'n')) FROM t1 LIMIT 1;
} {X'02000000'}
fts5_aux_test_functions db
do_execsql_test 15.3 {
SELECT fts5_test_all(t1) FROM t1 LIMIT 1;
} {
{columnsize {0 0} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
}
finish_test
-173
View File
@@ -59,178 +59,5 @@ do_catchsql_test 1.3.3 {
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
} {1 {no such cursor: 1}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE TABLE t0(c0);
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
}
do_execsql_test 2.1.1 {
BEGIN TRANSACTION;
INSERT INTO vt0(c0) VALUES ('xyz');
}
do_execsql_test 2.1.2 {
ALTER TABLE t0 ADD COLUMN c5;
}
do_execsql_test 2.1.3 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 2.1.4 {
INSERT INTO vt0(c0) VALUES ('abc');
COMMIT
}
do_execsql_test 2.1.5 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
reset_db
do_execsql_test 2.2.1 {
CREATE TABLE t0(c0);
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
BEGIN TRANSACTION;
INSERT INTO vt0(c0) VALUES ('xyz');
}
breakpoint
do_execsql_test 2.2.2 {
ALTER TABLE t0 RENAME TO t1;
}
do_execsql_test 2.2.3 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 2.2.4 {
INSERT INTO vt0(c0) VALUES ('abc');
COMMIT;
}
do_execsql_test 2.2.5 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE vt0 USING fts5(a);
PRAGMA reverse_unordered_selects = true;
INSERT INTO vt0 VALUES('365062398'), (0), (0);
INSERT INTO vt0(vt0, rank) VALUES('pgsz', '38');
}
do_execsql_test 3.1 {
UPDATE vt0 SET a = 399905135; -- unexpected: database disk image is malformed
}
do_execsql_test 3.2 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
INSERT INTO vt0(c0) VALUES ('xyz');
}
do_execsql_test 4.1 {
BEGIN;
INSERT INTO vt0(c0) VALUES ('abc');
INSERT INTO vt0(vt0) VALUES('rebuild');
COMMIT;
}
do_execsql_test 4.2 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 4.3 {
BEGIN;
INSERT INTO vt0(vt0) VALUES('rebuild');
INSERT INTO vt0(vt0) VALUES('rebuild');
COMMIT;
}
do_execsql_test 4.4 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
# Ticket [81a7f7b9].
#
reset_db
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE vt0 USING fts5(c0, c1);
INSERT INTO vt0(vt0, rank) VALUES('pgsz', '65536');
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1236
)
INSERT INTO vt0(c0) SELECT '0' FROM s;
} {}
do_execsql_test 5.1 {
UPDATE vt0 SET c1 = 'T,D&p^y/7#3*v<b<4j7|f';
}
do_execsql_test 5.2 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_catchsql_test 5.3 {
INSERT INTO vt0(vt0, rank) VALUES('pgsz', '65537');
} {1 {SQL logic error}}
#-------------------------------------------------------------------------
# Ticket [d392017c].
#
reset_db
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
)
INSERT INTO vt0(c0) SELECT '0' FROM s;
INSERT INTO vt0(vt0, rank) VALUES('crisismerge', 2000);
INSERT INTO vt0(vt0, rank) VALUES('automerge', 0);
} {}
do_execsql_test 6.1 {
INSERT INTO vt0(vt0) VALUES('rebuild');
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
INSERT INTO t1(rowid, x) VALUES(1, 'hello world');
INSERT INTO t1(rowid, x) VALUES(2, 'well said');
INSERT INTO t1(rowid, x) VALUES(3, 'hello said');
INSERT INTO t1(rowid, x) VALUES(4, 'well world');
CREATE TABLE t2 (a, b);
INSERT INTO t2 VALUES(1, 'hello');
INSERT INTO t2 VALUES(2, 'world');
INSERT INTO t2 VALUES(3, 'said');
INSERT INTO t2 VALUES(4, 'hello');
}
do_execsql_test 7.1 {
SELECT rowid FROM t1 WHERE (rowid, x) IN (SELECT a, b FROM t2);
}
do_execsql_test 7.2 {
SELECT rowid FROM t1 WHERE rowid=2 AND t1 = 'hello';
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.0 {
CREATE VIRTUAL TABLE vt0 USING fts5(c0, tokenize = "ascii", prefix = 1);
INSERT INTO vt0(c0) VALUES (x'd1');
}
breakpoint
do_execsql_test 8.1 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
finish_test
-231
View File
@@ -1,231 +0,0 @@
/*
** 2019-10-23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This SQLite extension implements functions that handling RFC-4122 UUIDs
** Three SQL functions are implemented:
**
** uuid() - generate a version 4 UUID as a string
** uuid_str(X) - convert a UUID X into a well-formed UUID string
** uuid_blob(X) - convert a UUID X into a 16-byte blob
**
** The output from uuid() and uuid_str(X) are always well-formed RFC-4122
** UUID strings in this format:
**
** xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
**
** All of the 'x', 'M', and 'N' values are lower-case hexadecimal digits.
** The M digit indicates the "version". For uuid()-generated UUIDs, the
** version is always "4" (a random UUID). The upper three bits of N digit
** are the "variant". This library only supports variant 1 (indicated
** by values of N between '8' and 'b') as those are overwhelming the most
** common. Other variants are for legacy compatibility only.
**
** The output of uuid_blob(X) is always a 16-byte blob. The UUID input
** string is converted in network byte order (big-endian) in accordance
** with RFC-4122 specifications for variant-1 UUIDs. Note that network
** byte order is *always* used, even if the input self-identifies as a
** variant-2 UUID.
**
** The input X to the uuid_str() and uuid_blob() functions can be either
** a string or a BLOB. If it is a BLOB it must be exactly 16 bytes in
** length or else a NULL is returned. If the input is a string it must
** consist of 32 hexadecimal digits, upper or lower case, optionally
** surrounded by {...} and with optional "-" characters interposed in the
** middle. The flexibility of input is inspired by the PostgreSQL
** implementation of UUID functions that accept in all of the following
** formats:
**
** A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
** {a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
** a0eebc999c0b4ef8bb6d6bb9bd380a11
** a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
** {a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
**
** If any of the above inputs are passed into uuid_str(), the output will
** always be in the canonical RFC-4122 format:
**
** a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
**
** If the X input string has too few or too many digits or contains
** stray characters other than {, }, or -, then NULL is returned.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>
#if !defined(SQLITE_ASCII) && !defined(SQLITE_EBCDIC)
# define SQLITE_ASCII 1
#endif
/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character: 0..9a..fA..F
*/
static unsigned char sqlite3UuidHexToInt(int h){
assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
h += 9*(1&(h>>6));
#endif
#ifdef SQLITE_EBCDIC
h += 9*(1&~(h>>4));
#endif
return (unsigned char)(h & 0xf);
}
/*
** Convert a 16-byte BLOB into a well-formed RFC-4122 UUID. The output
** buffer zStr should be at least 37 bytes in length. The output will
** be zero-terminated.
*/
static void sqlite3UuidBlobToStr(
const unsigned char *aBlob, /* Input blob */
unsigned char *zStr /* Write the answer here */
){
static const char zDigits[] = "0123456789abcdef";
int i, k;
unsigned char x;
k = 0;
for(i=0, k=0x550; i<16; i++, k=k>>1){
if( k&1 ){
zStr[0] = '-';
zStr++;
}
x = aBlob[i];
zStr[0] = zDigits[x>>4];
zStr[1] = zDigits[x&0xf];
zStr += 2;
}
*zStr = 0;
}
/*
** Attempt to parse a zero-terminated input string zStr into a binary
** UUID. Return 0 on success, or non-zero if the input string is not
** parsable.
*/
static int sqlite3UuidStrToBlob(
const unsigned char *zStr, /* Input string */
unsigned char *aBlob /* Write results here */
){
int i;
if( zStr[0]=='{' ) zStr++;
for(i=0; i<16; i++){
if( zStr[0]=='-' ) zStr++;
if( isxdigit(zStr[0]) && isxdigit(zStr[1]) ){
aBlob[i] = (sqlite3UuidHexToInt(zStr[0])<<4)
+ sqlite3UuidHexToInt(zStr[1]);
zStr += 2;
}else{
return 1;
}
}
if( zStr[0]=='}' ) zStr++;
return zStr[0]!=0;
}
/*
** Render sqlite3_value pIn as a 16-byte UUID blob. Return a pointer
** to the blob, or NULL if the input is not well-formed.
*/
static const unsigned char *sqlite3UuidInputToBlob(
sqlite3_value *pIn, /* Input text */
unsigned char *pBuf /* output buffer */
){
switch( sqlite3_value_type(pIn) ){
case SQLITE_TEXT: {
const unsigned char *z = sqlite3_value_text(pIn);
if( sqlite3UuidStrToBlob(z, pBuf) ) return 0;
return pBuf;
}
case SQLITE_BLOB: {
int n = sqlite3_value_bytes(pIn);
return n==16 ? sqlite3_value_blob(pIn) : 0;
}
default: {
return 0;
}
}
}
/* Implementation of uuid() */
static void sqlite3UuidFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
unsigned char aBlob[16];
unsigned char zStr[37];
(void)argc;
(void)argv;
sqlite3_randomness(16, aBlob);
aBlob[6] = (aBlob[6]&0x0f) + 0x40;
aBlob[8] = (aBlob[8]&0x3f) + 0x80;
sqlite3UuidBlobToStr(aBlob, zStr);
sqlite3_result_text(context, (char*)zStr, 36, SQLITE_TRANSIENT);
}
/* Implementation of uuid_str() */
static void sqlite3UuidStrFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
unsigned char aBlob[16];
unsigned char zStr[37];
const unsigned char *pBlob;
(void)argc;
pBlob = sqlite3UuidInputToBlob(argv[0], aBlob);
if( pBlob==0 ) return;
sqlite3UuidBlobToStr(pBlob, zStr);
sqlite3_result_text(context, (char*)zStr, 36, SQLITE_TRANSIENT);
}
/* Implementation of uuid_blob() */
static void sqlite3UuidBlobFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
unsigned char aBlob[16];
const unsigned char *pBlob;
(void)argc;
pBlob = sqlite3UuidInputToBlob(argv[0], aBlob);
if( pBlob==0 ) return;
sqlite3_result_blob(context, pBlob, 16, SQLITE_TRANSIENT);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_uuid_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "uuid", 0, SQLITE_UTF8, 0,
sqlite3UuidFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "uuid_str", 1, SQLITE_UTF8, 0,
sqlite3UuidStrFunc, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "uuid_blob", 1, SQLITE_UTF8, 0,
sqlite3UuidBlobFunc, 0, 0);
}
return rc;
}
+8 -9
View File
@@ -981,26 +981,25 @@ static int zipfileDeflate(
u8 **ppOut, int *pnOut, /* Output */
char **pzErr /* OUT: Error message */
){
int rc = SQLITE_OK;
sqlite3_int64 nAlloc;
z_stream str;
sqlite3_int64 nAlloc = compressBound(nIn);
u8 *aOut;
int rc = SQLITE_OK;
memset(&str, 0, sizeof(str));
str.next_in = (Bytef*)aIn;
str.avail_in = nIn;
deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
nAlloc = deflateBound(&str, nIn);
aOut = (u8*)sqlite3_malloc64(nAlloc);
if( aOut==0 ){
rc = SQLITE_NOMEM;
}else{
int res;
z_stream str;
memset(&str, 0, sizeof(str));
str.next_in = (Bytef*)aIn;
str.avail_in = nIn;
str.next_out = aOut;
str.avail_out = nAlloc;
deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
res = deflate(&str, Z_FINISH);
if( res==Z_STREAM_END ){
*ppOut = aOut;
*pnOut = (int)str.total_out;
+165
View File
@@ -0,0 +1,165 @@
# 2014 August 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.
#
#***********************************************************************
#
source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rbu1
forcedelete test.db2
do_execsql_test 1.0 {
CREATE TABLE t1(a INTEGER, b, c, PRIMARY KEY(a));
CREATE INDEX t1b ON t1(b); -- root=3
CREATE INDEX t1c ON t1(c); -- root=4
ATTACH 'test.db2' AS 'rbu';
CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(1, 1, 1, 0);
INSERT INTO data_t1 VALUES(2, 2, 2, 0);
INSERT INTO data_t1 VALUES(3, 3, 3, 0);
}
do_test 1.1 {
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 3
execsql {
CREATE TABLE imp1(b, id, PRIMARY KEY(b, id)) WITHOUT ROWID;
INSERT INTO imp1 VALUES(2, 2);
}
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 3
} {}
db close
sqlite3 db test.db
do_test 1.2 {
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 4
execsql {
CREATE TABLE imp1(b, id, PRIMARY KEY(b, id)) WITHOUT ROWID;
INSERT INTO imp1 VALUES(3, 3);
}
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 4
} {}
db close
db_save
sqlite3 db test.db
do_catchsql_test 1.3 { PRAGMA integrity_check } {0 {{wrong # of entries in index t1c} {wrong # of entries in index t1b}}}
db close
do_test 1.4 {
sqlite3rbu rbu test.db test.db2
while 1 {
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
}
list [catch { rbu close } msg] $msg
} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: t1.b, t1.a}}
db_restore
sqlite3 db test.db2
do_execsql_test 1.5 {
PRAGMA writable_schema = 1;
CREATE TABLE sqlite_rbu_replace_hack('v');
}
db close
do_test 1.6 {
sqlite3rbu rbu test.db test.db2
while 1 {
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
}
list [catch { rbu close } msg] $msg
} {0 SQLITE_DONE}
sqlite3 db test.db
do_execsql_test 1.7 {
PRAGMA integrity_check;
SELECT count(*) FROM t1;
} {ok 3}
#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
do_execsql_test 2.0 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
CREATE INDEX t1c ON t1(c); -- root=4
ATTACH 'test.db2' AS 'rbu';
CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES(1, 1, 1, 0);
INSERT INTO data_t1 VALUES(2, 2, 2, 0);
INSERT INTO data_t1 VALUES(3, 3, 3, 0);
}
do_test 2.1 {
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 3
execsql {
CREATE TABLE imp1(a, b, id, PRIMARY KEY(b, id)) WITHOUT ROWID;
INSERT INTO imp1 VALUES(2, 2, 2);
}
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 3
} {}
db close
sqlite3 db test.db
do_test 2.2 {
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 4
execsql {
CREATE TABLE imp1(c, id, PRIMARY KEY(c, id)) WITHOUT ROWID;
INSERT INTO imp1 VALUES(3, 3);
}
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 4
} {}
db close
db_save
sqlite3 db test.db
do_catchsql_test 2.3 { PRAGMA integrity_check } {0 {{wrong # of entries in index t1c} {wrong # of entries in index sqlite_autoindex_t1_1}}}
db close
do_test 2.4 {
sqlite3rbu rbu test.db test.db2
while 1 {
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
}
list [catch { rbu close } msg] $msg
} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: t1.a, t1.b}}
db_restore
sqlite3 db test.db2
do_execsql_test 2.5 {
PRAGMA writable_schema = 1;
CREATE TABLE sqlite_rbu_replace_hack('v');
}
db close
do_test 2.6 {
sqlite3rbu rbu test.db test.db2
while 1 {
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
}
list [catch { rbu close } msg] $msg
} {0 SQLITE_DONE}
sqlite3 db test.db
do_execsql_test 2.7 {
PRAGMA integrity_check;
SELECT count(*) FROM t1;
} {ok 3}
finish_test
+28 -3
View File
@@ -103,6 +103,8 @@
# define RBU_ENABLE_DELTA_CKSUM 0
#endif
#define RBU_REPLACE_HACK_TABLE "sqlite_rbu_replace_hack"
/*
** Swap two objects of type TYPE.
*/
@@ -376,6 +378,7 @@ struct sqlite3rbu {
char *zRbu; /* Path to rbu db */
char *zState; /* Path to state db (or NULL if zRbu) */
char zStateDb[5]; /* Db name for state ("stat" or "main") */
int bRbuReplaceHack; /* Do the REPLACE hack */
int rc; /* Value returned by last rbu_step() call */
char *zErrmsg; /* Error message if rc!=SQLITE_OK */
int nStep; /* Rows processed for current object */
@@ -2350,7 +2353,10 @@ static int rbuObjIterPrepareAll(
if( p->rc==SQLITE_OK ){
p->rc = prepareFreeAndCollectError(
p->dbMain, &pIter->pInsert, &p->zErrmsg,
sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind)
sqlite3_mprintf("%s INTO \"rbu_imp_%w\" VALUES(%s)",
p->bRbuReplaceHack ? "REPLACE" : "INSERT",
zTbl, zBind
)
);
}
@@ -2442,7 +2448,8 @@ static int rbuObjIterPrepareAll(
if( p->rc==SQLITE_OK ){
p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz,
sqlite3_mprintf(
"INSERT INTO \"%s%w\"(%s%s) VALUES(%s)",
"%s INTO \"%s%w\"(%s%s) VALUES(%s)",
p->bRbuReplaceHack ? "REPLACE" : "INSERT",
zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings
)
);
@@ -2725,7 +2732,7 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
break;
case RBU_STATE_OALSZ:
pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1);
pRet->iOalSz = sqlite3_column_int64(pStmt, 1);
break;
case RBU_STATE_PHASEONESTEP:
@@ -2744,6 +2751,24 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
rc2 = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK ) rc = rc2;
/* If this is not a vacuum operation, search for the special table
** "sqlite_rbu_replace_hack". Set the flag if it is found.
*/
if( rc==SQLITE_OK && !rbuIsVacuum(p) ){
sqlite3_stmt *pQuery = 0;
rc = prepareFreeAndCollectError(p->dbRbu, &pQuery, &p->zErrmsg,
sqlite3_mprintf("SELECT 1 FROM main.sqlite_master WHERE name='%s'",
RBU_REPLACE_HACK_TABLE
)
);
if( rc==SQLITE_OK ){
if( sqlite3_step(pQuery)==SQLITE_ROW ){
p->bRbuReplaceHack = 1;
}
rc = sqlite3_finalize(pQuery);
}
}
p->rc = rc;
return pRet;
}
+5 -1
View File
@@ -934,6 +934,10 @@ fuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-
./fuzzcheck$(EXE) $(FUZZDATA)
./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA)
./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db
valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
valgrind ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db
@@ -951,7 +955,7 @@ quicktest: ./testfixture$(EXE)
# The default test case. Runs most of the faster standard TCL tests,
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
test: fuzztest sourcetest $(TESTPROGS) tcltest
test: fastfuzztest sourcetest $(TESTPROGS) tcltest
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
+75 -75
View File
@@ -1,13 +1,13 @@
C Merge\sfixes\sfrom\strunk.
D 2019-10-24T23:43:32.999
C Fix\san\sRBU\sproblem\swith\srestarting\san\supdate\safter\sthe\s*-oal\sfile\sis\salready\slarger\sthan\s4GiB.
D 2021-08-11T18:56:49.597
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in bf24a9abbb277afa2fbe6bac80a181f22be6c48de771cd260c9851ecf6165dc1
F Makefile.in 578f123620087ea459aa08fa872810a25ca7c0aaf16331de985bfcddb5f1e747
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
F Makefile.msc c7e3548d5c9dc12bedf47366ca3f1438196f635d81f08fda44c6c1f290c4bcf8
F Makefile.msc a463dca3c50d8a36094fe5c8c39077907f530b54edfc5388c66c85e2cfc8dc04
F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
F VERSION 081500f0aeaadc989d85aafbc717af45512018aebc73d89e5c2368fe62a600ff
F VERSION 4c516d84c2a5f26c477ed34c09ac4136630f71c68139631f2eb591b22eea7cf1
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am e14b629addaa1ce372b72043f28f40de2e32b7e211b6e0fc18dbb87989197e40
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.msc 492ea431c411378094593a5225b9a02645455a5d87a26d018b5461b723e52125
F autoconf/Makefile.msc 3804b004efb6abd2d2e0f5f887dfc6ade3d1661f39335c0531df96e1ab61a062
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192
@@ -34,7 +34,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
F configure fdc9f8d53360170679349d8f72fb2e5c79f511424891b7bb8a2f48de41c7a6ef x
F configure 6f5136d2574d7aa08370021ab63be3ef8a8bf32af60594de08393b01feeb4bab x
F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
@@ -99,7 +99,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
F ext/fts3/fts3_write.c aef93982656ef63851470a86c8f145d54dd4ebd9341f7493aefe45ddff0ce600
F ext/fts3/fts3_write.c 13582783abedf905e6946ce95edff7103c07810fb03a9c3b40212d21a3efa09c
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
@@ -110,15 +110,15 @@ F ext/fts3/unicode/mkunicode.tcl bf7fcaa6d68e6d38223467983785d054f1cff4d9e3905dd
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h 7c9da96f2b9dcfa4dd94081fb2d87ec418d8cdb35b25df56756c334b6b558fd7
F ext/fts5/fts5Int.h d7cbc214ee167496f70905667e18f73ea0402f7ef09236ce305e117e0efc866a
F ext/fts5/fts5Int.h 0ec19a906a54c0e53f8a380c0ff70f11a866aa259490bc13aa39f8d2491800fd
F ext/fts5/fts5_aux.c dcc627d8b6e3fc773db528ff67b39955dab7b51628f9dba8e15849e5bedfd7fa
F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70
F ext/fts5/fts5_config.c aab6117f8f85933e051c66f227414fdcaf7f2313688e16276b895f9d42d28e5c
F ext/fts5/fts5_config.c 606a29f2962a8f4508923e6ad833974b32a3ab4093f63fd6de0fb33a87eed54c
F ext/fts5/fts5_expr.c 5661fe64f4f5a499710df9561075de84b743f01e808af46df4130a9ec343a0fd
F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75
F ext/fts5/fts5_index.c 99b77ae1f503978ca76985bcfff7345c822aed8bbaa8edb3747f804f614685b5
F ext/fts5/fts5_main.c 1b2d41fd7cc2e8277f60e4156826f41fe5d6b1ccc2e54d70450883ab2ca697d2
F ext/fts5/fts5_storage.c 167e3d8f8052a71032d498e32a2f2ed5ffe489e5d4d47e298adfa02ed55c7882
F ext/fts5/fts5_index.c 6601d085d8e8cf4750ee49e2e1d18907582cc0aab78233d3b21bc240ba76a199
F ext/fts5/fts5_main.c bf637030722badf06667d28f7159e4c209dbafd7aa76c33f387104b78ad147e1
F ext/fts5/fts5_storage.c 801b4e3cd33786a60a07b6b01f86d0fbdf7e68325054e08d17176293a8081e99
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
F ext/fts5/fts5_test_tok.c f96c6e193c466711d6d7828d5f190407fe7ab897062d371426dd3036f01258e7
@@ -157,7 +157,7 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 9517cc527a8e8a33949652d5c7b5e251f8c3d5ae3f23f01d4320e30f29a0336b
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
F ext/fts5/test/fts5corrupt3.test 4100ac398eefbf033ebdf5a5a9399b37b4f8e1285fa35ab9d0119d4c7f21dc0c
F ext/fts5/test/fts5corrupt3.test e188a43cecb3ff53b6236f862f82b2ec36962b9e39f20cb620dfa07aed70afa4
F ext/fts5/test/fts5corrupt4.test ea805c4d7c68b5f185b9db5d2060a7ae5875339738dd48203c92162f41e7ca91
F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
@@ -179,17 +179,17 @@ F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c
F ext/fts5/test/fts5faultB.test d606bdb8e81aaeb6f41de3fc9fc7ae315733f0903fbff05cf54f5b045b729ab5
F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079
F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717
F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b
F ext/fts5/test/fts5integrity.test 4317561cd25eca7df16aa1f7d1a700ee958059fa639785f94aba0a84df9ab17b
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
F ext/fts5/test/fts5matchinfo.test 50d86da66ec5b27603dcd90ba0227f5d9deb10351cbc52974a88e24f6fc9b076
F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8975d15c279374e82e35
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
F ext/fts5/test/fts5misc.test 1aefd6607106659a87dbce9f4766616c91e790ea84b9fa42e65096b7c99a132e
F ext/fts5/test/fts5misc.test 5becd134b66f7370042968a2b127b92ea7748e249f16cb6a996f450812e89eec
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
@@ -318,13 +318,12 @@ F ext/misc/stmt.c 8a8dc4675042e4551e4afe99b8d0cc7a4a2fc1a8dacc0a9ce1b1bbff145da9
F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9
F ext/misc/uuid.c db4db81e8c6a92ad6176ebd9f81dcb6870e331e1a286d0452f4319e3ba3df812
F ext/misc/vfslog.c 3b25c2f56ba60788db247287be6ab024b53c4afffd412b4876db563389be0d35
F ext/misc/vfsstat.c 77b5b4235c9f7f11eddf82487c0a422944ac2f132dafd5af3be7a68a057b1cdb
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/misc/zipfile.c 7ad29133e304e40c8fe239bea10e101580ed56bc68c16d992af514cce19572d0
F ext/misc/zipfile.c c1ca8f52330b4564207036b978edac8141c737bf612659bf6f7bee3ddd563a03
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce
F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
@@ -354,6 +353,7 @@ F ext/rbu/rbufault2.test c81327a3ac2c385b9b954db3644d4e0df93eeebfc3de9f1f29975a1
F ext/rbu/rbufault3.test b2fcc9db5c982b869f67d1d4688d8cb515d5b92f58011fff95665f2e62cec179
F ext/rbu/rbufault4.test 03d2849c3df7d7bd14a622e789ff049e5080edd34a79cd432e01204db2a5930a
F ext/rbu/rbufts.test 0ae8d1da191c75bd776b86e24456db0fb6e97b7c944259fae5407ea55d23c31d
F ext/rbu/rbuhack.test 95e7b35e58d5b2a8d182dde1a404949edf077c07485e6c2bce8a7f582941e729
F ext/rbu/rbumisc.test 329986cf5dd51890c4eb906c2f960ebb773a79a64bed90f506b7c417825b37eb
F ext/rbu/rbumulti.test 5fb139058f37ddc5a113c5b93238de915b769b7792de41b44c983bc7c18cf5b9
F ext/rbu/rbupartial.test f25df014b8dbe3c5345851fba6e66f79ab237f57dc201b2d5f0dbae658ae5a4c
@@ -366,7 +366,7 @@ F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697
F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10
F ext/rbu/sqlite3rbu.c f3a3e09f575157052813be667d6ab3b54f47fb02e6e1c9f767ad7bb8f1fb90b3
F ext/rbu/sqlite3rbu.c d175cbd98baba39cdea85df1de376277ab207ef1e4af8071aa1c208bb4fccc84
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -448,7 +448,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 7ce055f3df31a4f7d21e38f493f907c21db1f673863a573e231f55e2ab005023
F main.mk 09716d345766a55b25ed157b14786526cf67c761c61d99c53e117196fb3b391a
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -460,38 +460,38 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 0fdf14a1d1c61315a6d727252c579bc8cbfe62de195df6979dd784374e22032b
F src/analyze.c fd70b9c7a683230a7f7936af64dd25308e93d7c9819a3168493a7c7703481f80
F src/alter.c 5c3031e45e80f79d7d54c2d32dd3c44926544d4f6a478858bfe4ee3191570190
F src/analyze.c a3f4ea45cdb4e9df78d4ea7beb87ec8a7a46f494173b641cd28512a40a97bff2
F src/attach.c 3ca19504849c2d9be10fc5899d6811f9d6e848665d1a41ffb53df0cd6e7c13ed
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c a8a9c2ce62bdf54c8cf9795143d7cb10b7473a1230a0572f702d061ffcceefe5
F src/btree.h f27a33c49280209a93385e218306c4ee5f46ba8d7649d2f81a7166b282232484
F src/btreeInt.h 91806f01fd1145a9a86ba3042f25c38d8faf6002701bf5e780742cf88bcff437
F src/build.c 0c9704f95817aa585fdad2668c611280d0b62bc4c1c836cd1c797ba96879a7d6
F src/callback.c 88615dfc0a82167b65b452b4b305dbf86be77200b3343c6ffc6d03e92a01d181
F src/btree.c fdc4389b271bca30138db27dc2dfb9f52c2a7baaa44845aaf31a3c54663d837f
F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89
F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f
F src/build.c 4814d55abb5553ac82763f6df9e185503d913f912cc0abea00965bb02912cc2d
F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251
F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319
F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf
F src/expr.c 91429fb52958fd2ff0f5360a2cc9f41dd811dc8666d22cbb033f1557dd5fdbc2
F src/expr.c 1e9a6da29e3e13c14783891e867e19a54e2731c6a9b58d011cc4f3b4742a59e4
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c ac56f02ffe7a3dff311654f86e3c2fd1ff2eb38862b0c07fd908d8cc0fb4a9a2
F src/fkey.c 6b79f4c2447691aa9ac86e2a6a774b65f3b3dd053d4220a4893051a0de20f82e
F src/func.c ed33e38cd642058182a31a3f518f2e34f4bbe53aa483335705c153c4d3e50b12
F src/global.c a1a8d698762ddd9a1543aac26c1e0029b20fcc3fcb56bfa41ec8cea2368f2798
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 4c934e7f46c14e662e31613fb5bc5d1847c4b2fd7b6a878ab173ca6ef362d4ab
F src/insert.c 40557ebd69f4115e7a273f9304a8ab637a47ce44f3c6923396928f023967b5e8
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 4ddc65ae13c0d93db0ceedc8b14a28c8c260513448b0eb8c5a2ac375e3b6a85d
F src/main.c 3e01f6a1c96643381b5f9d79e4ff7f2520bc5712197746fb0852283e78cccf66
F src/malloc.c b7640bcf8992cf2e98447da0d27e372abdc4621a6760418bad6d1470f041ada9
F src/main.c 3851950717170ade4f6d718c18c6c7400ef5994c2a654679af2cff2ffd0fb2b9
F src/malloc.c 0f9da2a66b230a5785af94b9672126845099b57b70a32c987d04ac28c69da990
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -515,23 +515,23 @@ F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
F src/parse.y 97d46c41ea4185e8711560d7484cf5b4887fd2317dec79637be23454b5147647
F src/parse.y 50bfcb34be7320dd0cb875021a93ae6451c8f0b083f21b71934a1a3a9108015a
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 62714cbd1b7299a6e6a27a587b66b4fd3a836a84e1181e7f96f5c34a50917848
F src/pragma.c 986fdd27f1ddb712eaf7af4ac5c4d7e0ad97ce9c5d2f069e02f89bb7e7d06496
F src/pragma.c b47bc7db02ab13d04c680aee424466b4e34f4ef5aa7b2e464876ec005806f98f
F src/pragma.h 40962d65b645bb3f08c1f4c456effd01c6e7f073f68ea25177e0c95e181cff75
F src/prepare.c 6049beb71385f017af6fc320d2c75a4e50b75e280c54232442b785fbb83df057
F src/prepare.c 132484635a30f873ee7eccd47f93ed1932503863b93b28423b42332d81adffaf
F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 9d6a3bdca1ebc759c4616fee0d7dd4cf62741f53db3a6b0117600f27c5b1406a
F src/resolve.c e021be0c1c4a2125fa38aabcd8dbb764bf5b2c889a948c30d3708430ec6ccd00
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c 9c81d168b5a7ddc2277a6f6d3daec9ddd0ff5cebf12628d7e342f3c337231e7e
F src/shell.c.in 3093bdf5eedd91da08f0268f1442aa510a60798c9441868149ddbecdf8bcaa79
F src/select.c f509982c96bb24ccf57a0155fbe1e6184e0b8fb8866a04397dc41baa400e5240
F src/shell.c.in d70bcf630c4073eaa994fa74be98886c781918e794cb8b562be8df10f018e274
F src/sqlite.h.in 5725a6b20190a1e8d662077a1c1c8ea889ad7be90dd803f914c2de226f5fe6ab
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h cef696ce3293242c67b2339763608427bf72ee66f1f3a05389ac2a7b46001c31
F src/sqliteInt.h 5b2d25ba23135ece06886d82f60d9a16869506592e5950f3c09257b3b5d28d5c
F src/sqliteInt.h 246740eab76d3ac87f856f8d979567089e8749104c12932143a6ba570e38e415
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -590,32 +590,32 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d
F src/treeview.c 19e660b3a4ff8ae7dda426795020f0d2e1b349fa8cad19af9c9bf2a9063f2ef9
F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e
F src/treeview.c fddeb413159c3eeeaea3f496172f121cf3695606c461dc4e6dcee51417952df5
F src/trigger.c 845ccc08f60716c58aa28fe6470385c18ef8c4e1d88c93dcf449bc13d464eb2e
F src/update.c ae657f0db6a255011759ab9345ded7b54b828329a9dba04f94b4d4fa6e70e1ad
F src/upsert.c b445315c8958d8f17ec3297d06842e61dacaad0633ccaec1e4e160de7e562212
F src/update.c 7f05fad5e145248a00048aeb0bac78b8fdb4ed17216e14a6eb24c55596e87ee7
F src/upsert.c 710c91bb13e3c3fed5b6fe17cb13e09560bdd003ad8b8c51e6b16c80cfc48b10
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
F src/util.c 10d910e04a4f3842042485e0df01a484f57f912c10b60b3a09ccddd5019bd138
F src/util.c fffdfa627be74d69ef425f92db124e7148af449bb8a3286e79577c42bca84061
F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf
F src/vdbe.c 9e4ba6bb8e5b827b9ae771ba62a92f3099adaacd36838d54042eb2499cd7f6f5
F src/vdbe.h 2a49df699f305afa94f338f14bf6e1bfbca8112ce9c4d522abffd9493fc22a25
F src/vdbeInt.h bd589b8b7273286858950717e0e1ec5c88b18af45079a3366dc1371865cea704
F src/vdbeapi.c 1252d80c548711e47a6d84dae88ed4e95d3fbb4e7bd0eaa1347299af7efddf02
F src/vdbeaux.c e3ed5475d4611f28f3cad06c0454a354148f3bb0ce21c75659ce737dc13f7968
F src/vdbe.c 7f43ed8e055a4290535d2e4520d33f0ac6cc00ef76a0c099e4c6bd85be74a6b9
F src/vdbe.h 3f2b571e702e77e6bf031f0236e554aedfae643e991f69000320f481408455cf
F src/vdbeInt.h e95de5129124d77f01439e6635012adfaf23c0017bff47296126143cf18bd0c6
F src/vdbeapi.c 95001d0f84ee3cda344fed98ca0d7961deb4fc836b83495630d0af1f7cc4789e
F src/vdbeaux.c 7ccf418141df1c7f87b0d69510523ae522abbe47c769d1b2c15120e88fac3eb9
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
F src/vdbemem.c d8e10d1773806105e62094c4ede0a4684f46caaf07667a45e6d461e94306b530
F src/vdbesort.c a3be032cc3fee0e3af31773af4a7a6f931b7230a34f53282ccf1d9a2a72343be
F src/vdbesort.c da75f505aba230060ce6472605a4aa6494f73eeb1071e1cc2643c3d4035e671b
F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0
F src/vtab.c 108f79166d4a232a8bfb9d46e2fbec191f83a87fe97f7b93fc4de976c3fa3434
F src/vtab.c 5a0b7193d586991b3db30e343d6b59959906bfe8658a6a0a85709b20ca50bb49
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c bbd6838bd79c0a32144d482fb0b6a9d2d1a252fb3b16d5005ec30f2f80413b0d
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
F src/walker.c d5a94907dcac990e31976be9dc769d17f6a806782593d6aec9d760ee01ec22cd
F src/where.c 6ff3ef076485dd71efbbabcc7ddc0473c04a9bdcb524128939757b002466f2d1
F src/whereInt.h 4a296fd4fa79fdcbc2b5e8c1b898901617655811223e1082b899c23ecb092217
F src/wherecode.c 28a3f27b44165e05bac3031f9a9ee9901305647b6c9dfc0214544578066ab097
F src/whereexpr.c 0705f608f6dbbd4e95d440528d6c760b91b6f402ba4eb8b8d964c110e2010780
F src/where.c 9f3f23efc45934e7b7ea6c0c1042420b73053e7c3264feef6faf9ce6fbd5df61
F src/whereInt.h 2c6bae136a7c0be6ff75dc36950d1968c67d005c8e51d7a9d77cb996bb4843d9
F src/wherecode.c 535c8e228478fd971b9a5b6cb6773995b0fbf7020d5989508a5094ce5b8cd95b
F src/whereexpr.c 05c283d26aa9c3f5d1bf13a5f6a573b43295b9db280eff18e26f97d7d7f119b4
F src/window.c 064f251451c8e2a1c76b6269229d911a651e119c6a5f522b6eaebf8dc8714041
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -733,7 +733,7 @@ F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b13
F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
F test/collate1.test 4178fda6f4cd757b7a278e6b83805868fb1eb46edafb6e3d4bcc2419f8d93202
F test/collate1.test f9b653f515ef3324a0c4e3c6adbf136bb1903622af678d482a60c11c9c054e6c
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5
F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd
@@ -770,7 +770,7 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
F test/corruptL.test a22a7bbf8da7603960f0bfcc62a68d1c3c41963786bd832ff804ba5e2458fb9c
F test/corruptL.test dfad96373bf9264d73039315ea6013994b90bf6776847adc7ec06b6fad3c04b2
F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
F test/cost.test 51f4fcaae6e78ad5a57096831259ed6c760e2ac6876836e91c00030fad385b34
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
@@ -860,7 +860,7 @@ F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
F test/filter1.test edd797ab2ef38de16064c9e3945efd941cba72d27e8f070c349501ff95d2727d
F test/filter1.test c2f34e58ee82a60c3ee9b5b4c4f2004ec2f529dff2f473706eeffa684cbb6719
F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f93393e8
F test/filter2.test 485cf95d1f6d6ceee5632201ca52a71868599836f430cdee42e5f7f14666e30a
F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b
@@ -959,7 +959,7 @@ F test/fts3fuzz001.test e3c7b0ce9b04cc02281dcc96812a277f02df03cd7dc082055d87e11e
F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
F test/fts3misc.test a418198b2c3c56bddcaf657f41644715f6ad27ffa72a8ba8f542e93030517744
F test/fts3misc.test 0b20083efab36a42804bf8017a003f72f963c46163403dae7256493367d2f9d3
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
@@ -982,7 +982,7 @@ F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
F test/fts4langid.test 2168ba330af34f8a1c8832de0aab4c4b6fa195a16419c9c0c8aad59ceb6ff714
F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7
F test/fts4merge.test e2b2ec21e287d54ec09824ccfb41e66896eeca568fc818ba0e0eb2efd94c35d2
F test/fts4merge.test 1096e30b58ad616bd502141bfe5bfe4c3a518df89e958d41a5ed1ce322369b9c
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
@@ -1016,7 +1016,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db e7a86fd83dda151d160445d542e32e5c6019c541b3a74c2a525b6ac640639711
F test/fuzzdata8.db 7a8baf778cbaf9c9744c9dd9b7aa66c4365d96c0ef8e1900e99a48a48f19778c
F test/fuzzdata8.db c75b0fd1d28c262f9c3a9428393ff9c420ea5bdbe0b33c557a971915a94bab71
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
@@ -1061,7 +1061,7 @@ F test/indexexpr1.test c26c8b352311c1deb30642cd0379e5cb94e416c7e9e0885e92d9e0155
F test/indexexpr2.test b580f378423bca443ffab47ada677203cfcf8a60f48a8aa20065f27c8f7739b5
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test c0e1b23f6359e06316b3a49f7747c5d65c0b6473619011e4fb86f6801edba6df
F test/insert.test 72004f6a900a25bd3f1ce9a72e73d02749644666a8ce6d6d2dba061137e5aa63
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test 7802ada6ba8738661b9f6c0e26858d3375b40cc7180289fd350644cd7a08fec9
@@ -1082,7 +1082,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test 75327829744e65cc8700e69340b8e6c192e10e39dfae7ccb0e970d3c4f49090a
F test/join.test b515753842b739f8310e718ff5a1581d0f80fd7c731c7e642c5af4310d8db94d
F test/join.test 6ce8296a08e78632c322cde0add78a7ce05466c3d9ec7d5130b38b5b489e7c27
F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -1181,7 +1181,7 @@ F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
F test/normalize.test f23b6c5926c59548635fcf39678ac613e726121e073dd902a3062fbb83903b72
F test/normalize.test 422027884ffb67ebba32bb78487c67cf67643496d19c077b07044bdba071a3f6
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
@@ -1261,7 +1261,7 @@ F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test bfbd7b97d9267660be3c8f28507c4ed7f205196b8877c0db42df347c2e8845e3
F test/rowvalue.test 92dc2c5fad808d6764c8e5fa14360b89dacb3cb33ba1498a52f226f89a04a868
F test/rowvalue.test a3e729d5c1f32da03bba15af1e3128218d2ba3c40d4f4ed5fa0497a713df68ea
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
F test/rowvalue4.test 02e35f7762371c2f57ebd856aa056eac56cb27ef7715a0bb31eac1895a745356
@@ -1271,7 +1271,6 @@ F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
F test/rowvalue9.test d8dd2c6ecac432dadaa79e41dc2434f007be1b6b
F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504
F test/rowvaluevtab.test 751a224b86d5c66d1d0bfa9887da9d6ab9a1c09e1268b5abe0ffdfdd418f122f
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
F test/savepoint.test 1f8a6b1aea9a0d05837adc463d4bf47bd9d0f1c842f1c2a9caccd639baf34bf9
@@ -1570,7 +1569,7 @@ F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
F test/trigger1.test 746dc327e2a0817a22bfc6f5a5e423483d3e77b3733ac20a8fe939e6541b5e53
F test/trigger1.test 6be279c9d48b25320eab68c30fd5268ab787955679f4c584128f71800247fb50
F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
@@ -1709,7 +1708,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 453bb9dcb1b447eddbb4777c97620f02543a4375359723b7372ff09dcf847045
F test/window1.test 376a7c9c5b9df9868d92a6d9d455262e1b769f4410b19006f5f8c5507c2a7ed7
F test/window2.tcl 66db96fd9fd202bc31ee7f8ce7904cb469564864cff3f74e009bfef8102333f4
F test/window2.test af2a001ded703bb8f2474fb0edfef170d5aba00f5c1f2aa9f65935b5da13df90
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@ -1768,7 +1767,7 @@ F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c 9ec344d29cbeb03fdc0fce668eedfb7495792170de933adf95cf8d6904a166ad
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c 61d5f0af1eff8f754b75ddca668c9897fd30759e389bfffb42ce9e4d38fd4746
F tool/lempar.c 34b136b281ae022277738d8b51061237fb330deaa317010d89375117e3a028aa
F tool/lempar.c eb2841e2a7fd484cf44b1f526b06e7ab0f216d2f41818bf9485e8f38e3d1db19
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1776,7 +1775,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
F tool/mkkeywordhash.c 8973d556c5ee984b510269623c316ce0767f61dbd789075a05f213f3a576d840
F tool/mkkeywordhash.c bc5bcc92ebcaf15345346be7cf2204b83ed649b5208234adb5e543c061209bbf
F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
@@ -1848,7 +1847,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P b99d5701312f7472e6b606bd824f9273617e2655920485bf50aa96d408064721 8d964e1c21d4cea699023e02b0616a75c5859dd083c9365cdcbc0676ebbdaae4
R 6be8af4fed012ba4b6cd154b1c5c04cd
U drh
Z 9721b48c1c0b317285dab74d2e56c0b3
P 4b73e151cdb4b89bdd2f1bab5c0378500234ce6c479cc1d8cd4e006be79d1162
Q +087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a
R f1bc15780a98eb9fb1abdadc164e3b34
U dan
Z 02ec0c40b41079c9dff32d6e22ece993
+1 -1
View File
@@ -1 +1 @@
4ec57d88415fa4ea2e99d4a5671074ec6829d6824bc8509d5ae9c978d47d1419
56869f54f31186231a4467f10208bcc08d9edae23c6e21831d6d3dff47da51de
+34 -46
View File
@@ -298,6 +298,14 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
}
#endif
/* If the default value for the new column was specified with a
** literal NULL, then set pDflt to 0. This simplifies checking
** for an SQL NULL default below.
*/
assert( pDflt==0 || pDflt->op==TK_SPAN );
if( pDflt && pDflt->pLeft->op==TK_NULL ){
pDflt = 0;
}
/* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
** If there is a NOT NULL constraint, then the default value for the
@@ -311,49 +319,35 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
return;
}
if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){
/* If the default value for the new column was specified with a
** literal NULL, then set pDflt to 0. This simplifies checking
** for an SQL NULL default below.
*/
assert( pDflt==0 || pDflt->op==TK_SPAN );
if( pDflt && pDflt->pLeft->op==TK_NULL ){
pDflt = 0;
}
if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
sqlite3ErrorMsg(pParse,
"Cannot add a REFERENCES column with non-NULL default value");
return;
}
if( pCol->notNull && !pDflt ){
sqlite3ErrorMsg(pParse,
"Cannot add a NOT NULL column with default value NULL");
return;
}
/* Ensure the default expression is something that sqlite3ValueFromExpr()
** can handle (i.e. not CURRENT_TIME etc.)
*/
if( pDflt ){
sqlite3_value *pVal = 0;
int rc;
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
if( rc!=SQLITE_OK ){
assert( db->mallocFailed == 1 );
return;
}
if( !pVal ){
sqlite3ErrorMsg(pParse,"Cannot add a column with non-constant default");
return;
}
sqlite3ValueFree(pVal);
}
}else if( pCol->colFlags & COLFLAG_STORED ){
sqlite3ErrorMsg(pParse, "cannot add a STORED column");
if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
sqlite3ErrorMsg(pParse,
"Cannot add a REFERENCES column with non-NULL default value");
return;
}
if( pCol->notNull && !pDflt ){
sqlite3ErrorMsg(pParse,
"Cannot add a NOT NULL column with default value NULL");
return;
}
/* Ensure the default expression is something that sqlite3ValueFromExpr()
** can handle (i.e. not CURRENT_TIME etc.)
*/
if( pDflt ){
sqlite3_value *pVal = 0;
int rc;
rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
if( rc!=SQLITE_OK ){
assert( db->mallocFailed == 1 );
return;
}
if( !pVal ){
sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
return;
}
sqlite3ValueFree(pVal);
}
/* Modify the CREATE TABLE statement. */
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
@@ -441,7 +435,6 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
goto exit_begin_add_column;
}
sqlite3MayAbort(pParse);
assert( pTab->addColOffset>0 );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -1337,11 +1330,6 @@ static void renameColumnFunc(
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
for(i=0; i<sParse.pNewTable->nCol; i++){
sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
}
#endif
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
for(i=0; i<pFKey->nCol; i++){
+3 -3
View File
@@ -1182,7 +1182,7 @@ static void analyzeOneTable(
int j, k, regKey;
regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
assert( k>=0 && k<pIdx->nColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
@@ -1854,9 +1854,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT4
if( rc==SQLITE_OK ){
DisableLookaside;
db->lookaside.bDisable++;
rc = loadStat4(db, sInfo.zDatabase);
EnableLookaside;
db->lookaside.bDisable--;
}
for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
+2 -5
View File
@@ -9459,7 +9459,7 @@ int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */
@@ -9472,7 +9472,7 @@ int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
/* Unless an error occurs, the following loop runs one iteration for each
** page in the B-Tree structure (not including overflow pages).
*/
while( rc==SQLITE_OK && !db->u1.isInterrupted ){
while( rc==SQLITE_OK ){
int iIdx; /* Index of child node in parent */
MemPage *pPage; /* Current page of the b-tree */
@@ -9598,7 +9598,6 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage){
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
return 1;
}
if( pCheck->db->u1.isInterrupted ) return 1;
setPageReferenced(pCheck, iPage);
return 0;
}
@@ -10042,7 +10041,6 @@ end_of_check:
** returned. If a memory allocation error occurs, NULL is returned.
*/
char *sqlite3BtreeIntegrityCheck(
sqlite3 *db, /* Database connection that is running the check */
Btree *p, /* The btree to be checked */
int *aRoot, /* An array of root pages numbers for individual trees */
int nRoot, /* Number of entries in aRoot[] */
@@ -10060,7 +10058,6 @@ char *sqlite3BtreeIntegrityCheck(
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
assert( nRef>=0 );
sCheck.db = db;
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = btreePagecount(sCheck.pBt);
+2 -2
View File
@@ -314,7 +314,7 @@ const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
u32 sqlite3BtreePayloadSize(BtCursor*);
sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
char *sqlite3BtreeIntegrityCheck(sqlite3*,Btree*,int*aRoot,int nRoot,int,int*);
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
struct Pager *sqlite3BtreePager(Btree*);
i64 sqlite3BtreeRowCountEst(BtCursor*);
@@ -335,7 +335,7 @@ int sqlite3BtreeCursorIsValid(BtCursor*);
int sqlite3BtreeCursorIsValidNN(BtCursor*);
#ifndef SQLITE_OMIT_BTREECOUNT
int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
int sqlite3BtreeCount(BtCursor *, i64 *);
#endif
#ifdef SQLITE_TEST
-1
View File
@@ -685,7 +685,6 @@ struct IntegrityCk {
int v1, v2; /* Values for up to two %d fields in zPfx */
StrAccum errMsg; /* Accumulate the error message text here */
u32 *heap; /* Min-heap used for analyzing cell coverage */
sqlite3 *db; /* Database connection running the check */
};
/*
+52 -195
View File
@@ -877,12 +877,10 @@ Index *sqlite3PrimaryKeyIndex(Table *pTab){
}
/*
** Convert an table column number into a index column number. That is,
** for the column iCol in the table (as defined by the CREATE TABLE statement)
** find the (first) offset of that column in index pIdx. Or return -1
** if column iCol is not used in index pIdx.
** Return the column of index pIdx that corresponds to table
** column iCol. Return -1 if not found.
*/
i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
int i;
for(i=0; i<pIdx->nColumn; i++){
if( iCol==pIdx->aiColumn[i] ) return i;
@@ -890,82 +888,6 @@ i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
return -1;
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Convert a storage column number into a table column number.
**
** The storage column number (0,1,2,....) is the index of the value
** as it appears in the record on disk. The true column number
** is the index (0,1,2,...) of the column in the CREATE TABLE statement.
**
** The storage column number is less than the table column number if
** and only there are VIRTUAL columns to the left.
**
** If SQLITE_OMIT_GENERATED_COLUMNS, this routine is a no-op macro.
*/
i16 sqlite3StorageColumnToTable(Table *pTab, i16 iCol){
if( pTab->tabFlags & TF_HasVirtual ){
int i;
for(i=0; i<=iCol; i++){
if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) iCol++;
}
}
return iCol;
}
#endif
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Convert a table column number into a storage column number.
**
** The storage column number (0,1,2,....) is the index of the value
** as it appears in the record on disk. Or, if the input column is
** the N-th virtual column (zero-based) then the storage number is
** the number of non-virtual columns in the table plus N.
**
** The true column number is the index (0,1,2,...) of the column in
** the CREATE TABLE statement.
**
** If the input column is a VIRTUAL column, then it should not appear
** in storage. But the value sometimes is cached in registers that
** follow the range of registers used to construct storage. This
** avoids computing the same VIRTUAL column multiple times, and provides
** values for use by OP_Param opcodes in triggers. Hence, if the
** input column is a VIRTUAL table, put it after all the other columns.
**
** In the following, N means "normal column", S means STORED, and
** V means VIRTUAL. Suppose the CREATE TABLE has columns like this:
**
** CREATE TABLE ex(N,S,V,N,S,V,N,S,V);
** -- 0 1 2 3 4 5 6 7 8
**
** Then the mapping from this function is as follows:
**
** INPUTS: 0 1 2 3 4 5 6 7 8
** OUTPUTS: 0 1 6 2 3 7 4 5 8
**
** So, in other words, this routine shifts all the virtual columns to
** the end.
**
** If SQLITE_OMIT_GENERATED_COLUMNS then there are no virtual columns and
** this routine is a no-op macro.
*/
i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
int i;
i16 n;
assert( iCol<pTab->nCol );
if( (pTab->tabFlags & TF_HasVirtual)==0 ) return iCol;
for(i=0, n=0; i<iCol; i++){
if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) n++;
}
if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ){
/* iCol is a virtual column itself */
return pTab->nNVCol + i - n;
}else{
/* iCol is a normal or stored column */
return n;
}
}
#endif
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
@@ -1256,7 +1178,6 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
pCol->colFlags |= COLFLAG_HASTYPE;
}
p->nCol++;
p->nNVCol++;
pParse->constraintName.n = 0;
}
@@ -1405,12 +1326,6 @@ void sqlite3AddDefaultValue(
if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( pCol->colFlags & COLFLAG_GENERATED ){
testcase( pCol->colFlags & COLFLAG_VIRTUAL );
testcase( pCol->colFlags & COLFLAG_STORED );
sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
#endif
}else{
/* A copy of pExpr is used instead of the original, as pExpr contains
** tokens that point to volatile memory.
@@ -1456,21 +1371,6 @@ static void sqlite3StringToId(Expr *p){
}
}
/*
** Tag the given column as being part of the PRIMARY KEY
*/
static void makeColumnPartOfPrimaryKey(Parse *pParse, Column *pCol){
pCol->colFlags |= COLFLAG_PRIMKEY;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( pCol->colFlags & COLFLAG_GENERATED ){
testcase( pCol->colFlags & COLFLAG_VIRTUAL );
testcase( pCol->colFlags & COLFLAG_STORED );
sqlite3ErrorMsg(pParse,
"generated columns cannot be part of the PRIMARY KEY");
}
#endif
}
/*
** Designate the PRIMARY KEY for the table. pList is a list of names
** of columns that form the primary key. If pList is NULL, then the
@@ -1510,7 +1410,7 @@ void sqlite3AddPrimaryKey(
if( pList==0 ){
iCol = pTab->nCol - 1;
pCol = &pTab->aCol[iCol];
makeColumnPartOfPrimaryKey(pParse, pCol);
pCol->colFlags |= COLFLAG_PRIMKEY;
nTerm = 1;
}else{
nTerm = pList->nExpr;
@@ -1523,7 +1423,7 @@ void sqlite3AddPrimaryKey(
for(iCol=0; iCol<pTab->nCol; iCol++){
if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
pCol = &pTab->aCol[iCol];
makeColumnPartOfPrimaryKey(pParse, pCol);
pCol->colFlags |= COLFLAG_PRIMKEY;
break;
}
}
@@ -1620,52 +1520,41 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
}
}
/* Change the most recently parsed column to be a GENERATED ALWAYS AS
** column.
/*
** This function returns the collation sequence for database native text
** encoding identified by the string zName, length nName.
**
** If the requested collation sequence is not available, or not available
** in the database native encoding, the collation factory is invoked to
** request it. If the collation factory does not supply such a sequence,
** and the sequence is available in another text encoding, then that is
** returned instead.
**
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
**
** This routine is a wrapper around sqlite3FindCollSeq(). This routine
** invokes the collation factory if the named collation cannot be found
** and generates an error message.
**
** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
*/
void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
u8 eType = COLFLAG_VIRTUAL;
Table *pTab = pParse->pNewTable;
Column *pCol;
if( NEVER(pTab==0) ) goto generated_done;
pCol = &(pTab->aCol[pTab->nCol-1]);
if( IN_DECLARE_VTAB ){
sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
goto generated_done;
}
if( pCol->pDflt ) goto generated_error;
if( pType ){
if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){
/* no-op */
}else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
eType = COLFLAG_STORED;
}else{
goto generated_error;
}
}
if( eType==COLFLAG_VIRTUAL ) pTab->nNVCol--;
pCol->colFlags |= eType;
assert( TF_HasVirtual==COLFLAG_VIRTUAL );
assert( TF_HasStored==COLFLAG_STORED );
pTab->tabFlags |= eType;
pCol->pDflt = pExpr;
pExpr = 0;
goto generated_done;
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
sqlite3 *db = pParse->db;
u8 enc = ENC(db);
u8 initbusy = db->init.busy;
CollSeq *pColl;
generated_error:
sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
pCol->zName);
generated_done:
sqlite3ExprDelete(pParse->db, pExpr);
#else
/* Throw and error for the GENERATED ALWAYS AS clause if the
** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
sqlite3ErrorMsg(pParse, "generated columns not supported");
sqlite3ExprDelete(pParse->db, pExpr);
#endif
pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
if( !initbusy && (!pColl || !pColl->xCmp) ){
pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
}
return pColl;
}
/*
** Generate code that will increment the schema cookie.
**
@@ -1923,24 +1812,15 @@ static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){
** high-order bit of colNotIdxed is always 1. All unindexed columns
** of the table have a 1.
**
** 2019-10-24: For the purpose of this computation, virtual columns are
** not considered to be covered by the index, even if they are in the
** index, because we do not trust the logic in whereIndexExprTrans() to be
** able to find all instances of a reference to the indexed table column
** and convert them into references to the index. Hence we always want
** the actual table at hand in order to recompute the virtual column, if
** necessary.
**
** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask
** to determine if the index is covering index.
*/
static void recomputeColumnsNotIndexed(Index *pIdx){
Bitmask m = 0;
int j;
Table *pTab = pIdx->pTable;
for(j=pIdx->nColumn-1; j>=0; j--){
int x = pIdx->aiColumn[j];
if( x>=0 && (pTab->aCol[x].colFlags & COLFLAG_VIRTUAL)==0 ){
if( x>=0 ){
testcase( x==BMS-1 );
testcase( x==BMS-2 );
if( x<BMS-1 ) m |= MASKBIT(x);
@@ -2098,14 +1978,11 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
*/
nExtra = 0;
for(i=0; i<pTab->nCol; i++){
if( !hasColumn(pPk->aiColumn, nPk, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
if( !hasColumn(pPk->aiColumn, nPk, i) ) nExtra++;
}
if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
for(i=0, j=nPk; i<pTab->nCol; i++){
if( !hasColumn(pPk->aiColumn, j, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
){
if( !hasColumn(pPk->aiColumn, j, i) ){
assert( j<pPk->nColumn );
pPk->aiColumn[j] = i;
pPk->azColl[j] = sqlite3StrBINARY;
@@ -2113,7 +1990,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}
}
assert( pPk->nColumn==j );
assert( pTab->nNVCol<=j );
assert( pTab->nCol<=j );
recomputeColumnsNotIndexed(pPk);
}
@@ -2222,11 +2099,12 @@ void sqlite3EndTable(
}
if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
return;
}else{
p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
convertToWithoutRowidTable(pParse, p);
}
p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
convertToWithoutRowidTable(pParse, p);
}
iDb = sqlite3SchemaToIndex(db, p->pSchema);
#ifndef SQLITE_OMIT_CHECK
@@ -2236,22 +2114,6 @@ void sqlite3EndTable(
sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( p->tabFlags & TF_HasGenerated ){
int ii;
testcase( p->tabFlags & TF_HasVirtual );
testcase( p->tabFlags & TF_HasStored );
for(ii=0; ii<p->nCol; ii++){
u32 colFlags = p->aCol[ii].colFlags;
if( (colFlags & COLFLAG_GENERATED)!=0 ){
testcase( colFlags & COLFLAG_VIRTUAL );
testcase( colFlags & COLFLAG_STORED );
sqlite3ResolveSelfReference(pParse, p, NC_GenCol,
p->aCol[ii].pDflt, 0);
}
}
}
#endif
/* Estimate the average row size for the table and for all implied indices */
estimateTableWidth(p);
@@ -2328,7 +2190,7 @@ void sqlite3EndTable(
pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = p->nNVCol = pSelTab->nCol;
p->nCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
@@ -2585,7 +2447,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
DisableLookaside;
db->lookaside.bDisable++;
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
@@ -2616,7 +2478,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** the column names from the SELECT statement that defines the view.
*/
assert( pTable->aCol==0 );
pTable->nCol = pTable->nNVCol = pSelTab->nCol;
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
@@ -2627,7 +2489,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
}
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
EnableLookaside;
db->lookaside.bDisable--;
#ifndef SQLITE_OMIT_ALTERTABLE
pParse->eParseMode = eParseMode;
#endif
@@ -3626,13 +3488,8 @@ void sqlite3CreateIndex(
assert( j<=0x7fff );
if( j<0 ){
j = pTab->iPKey;
}else{
if( pTab->aCol[j].notNull==0 ){
pIndex->uniqNotNull = 0;
}
if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){
pIndex->bHasVCol = 1;
}
}else if( pTab->aCol[j].notNull==0 ){
pIndex->uniqNotNull = 0;
}
pIndex->aiColumn[i] = (i16)j;
}
@@ -3687,13 +3544,13 @@ void sqlite3CreateIndex(
/* If this index contains every column of its table, then mark
** it as a covering index */
assert( HasRowid(pTab)
|| pTab->iPKey<0 || sqlite3TableColumnToIndex(pIndex, pTab->iPKey)>=0 );
|| pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 );
recomputeColumnsNotIndexed(pIndex);
if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){
pIndex->isCovering = 1;
for(j=0; j<pTab->nCol; j++){
if( j==pTab->iPKey ) continue;
if( sqlite3TableColumnToIndex(pIndex,j)>=0 ) continue;
if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue;
pIndex->isCovering = 0;
break;
}
+49 -83
View File
@@ -65,6 +65,51 @@ static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
return SQLITE_ERROR;
}
/*
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the desired encoding.
**
** If it is not NULL, then pColl must point to the database native encoding
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
** sequence can be found. If no collation is found, leave an error message.
**
** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
*/
CollSeq *sqlite3GetCollSeq(
Parse *pParse, /* Parsing context */
u8 enc, /* The desired encoding for the collating sequence */
CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
const char *zName /* Collating sequence name */
){
CollSeq *p;
sqlite3 *db = pParse->db;
p = pColl;
if( !p ){
p = sqlite3FindCollSeq(db, enc, zName, 0);
}
if( !p || !p->xCmp ){
/* No collation sequence of this type for this encoding is registered.
** Call the collation factory to see if it can supply us with one.
*/
callCollNeeded(db, enc, zName);
p = sqlite3FindCollSeq(db, enc, zName, 0);
}
if( p && !p->xCmp && synthCollSeq(db, p) ){
p = 0;
}
assert( !p || p->xCmp );
if( p==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
}
return p;
}
/*
** This routine is called on a collation sequence before it is used to
** check that it is defined. An undefined collation sequence exists when
@@ -157,10 +202,10 @@ static CollSeq *findCollSeqEntry(
** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()
*/
CollSeq *sqlite3FindCollSeq(
sqlite3 *db, /* Database connection to search */
u8 enc, /* Desired text encoding */
const char *zName, /* Name of the collating sequence. Might be NULL */
int create /* True to create CollSeq if doesn't already exist */
sqlite3 *db,
u8 enc,
const char *zName,
int create
){
CollSeq *pColl;
if( zName ){
@@ -174,85 +219,6 @@ CollSeq *sqlite3FindCollSeq(
return pColl;
}
/*
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the desired encoding.
**
** If it is not NULL, then pColl must point to the database native encoding
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
** sequence can be found. If no collation is found, leave an error message.
**
** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
*/
CollSeq *sqlite3GetCollSeq(
Parse *pParse, /* Parsing context */
u8 enc, /* The desired encoding for the collating sequence */
CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
const char *zName /* Collating sequence name */
){
CollSeq *p;
sqlite3 *db = pParse->db;
p = pColl;
if( !p ){
p = sqlite3FindCollSeq(db, enc, zName, 0);
}
if( !p || !p->xCmp ){
/* No collation sequence of this type for this encoding is registered.
** Call the collation factory to see if it can supply us with one.
*/
callCollNeeded(db, enc, zName);
p = sqlite3FindCollSeq(db, enc, zName, 0);
}
if( p && !p->xCmp && synthCollSeq(db, p) ){
p = 0;
}
assert( !p || p->xCmp );
if( p==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
}
return p;
}
/*
** This function returns the collation sequence for database native text
** encoding identified by the string zName.
**
** If the requested collation sequence is not available, or not available
** in the database native encoding, the collation factory is invoked to
** request it. If the collation factory does not supply such a sequence,
** and the sequence is available in another text encoding, then that is
** returned instead.
**
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
**
** This routine is a wrapper around sqlite3FindCollSeq(). This routine
** invokes the collation factory if the named collation cannot be found
** and generates an error message.
**
** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
*/
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
sqlite3 *db = pParse->db;
u8 enc = ENC(db);
u8 initbusy = db->init.busy;
CollSeq *pColl;
pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
if( !initbusy && (!pColl || !pColl->xCmp) ){
pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
}
return pColl;
}
/* During the search for the best function definition, this procedure
** is called to test how well the function passed as the first argument
** matches the request for a function with nArg arguments in a system
+79 -155
View File
@@ -70,9 +70,6 @@ char sqlite3ExprAffinity(Expr *pExpr){
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
if( op==TK_VECTOR ){
return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
}
return pExpr->affExpr;
}
@@ -175,10 +172,6 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
p = p->pLeft;
continue;
}
if( op==TK_VECTOR ){
p = p->x.pList->a[0].pExpr;
continue;
}
if( op==TK_COLLATE ){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
@@ -193,10 +186,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
/* p->flags holds EP_Collate and p->pLeft->flags does not. And
** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
** least one EP_Collate. Thus the following two ALWAYS. */
if( p->x.pList!=0
&& !db->mallocFailed
&& ALWAYS(!ExprHasProperty(p, EP_xIsSelect))
){
if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
int i;
for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
@@ -346,22 +336,6 @@ CollSeq *sqlite3BinaryCompareCollSeq(
return pColl;
}
/* Expresssion p is a comparison operator. Return a collation sequence
** appropriate for the comparison operator.
**
** This is normally just a wrapper around sqlite3BinaryCompareCollSeq().
** However, if the OP_Commuted flag is set, then the order of the operands
** is reversed in the sqlite3BinaryCompareCollSeq() call so that the
** correct collating sequence is found.
*/
CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, Expr *p){
if( ExprHasProperty(p, EP_Commuted) ){
return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft);
}else{
return sqlite3BinaryCompareCollSeq(pParse, p->pLeft, p->pRight);
}
}
/*
** Generate code for a comparison operator.
*/
@@ -372,18 +346,13 @@ static int codeCompare(
int opcode, /* The comparison opcode */
int in1, int in2, /* Register holding operands */
int dest, /* Jump here if true. */
int jumpIfNull, /* If true, jump if either operand is NULL */
int isCommuted /* The comparison has been commuted */
int jumpIfNull /* If true, jump if either operand is NULL */
){
int p5;
int addr;
CollSeq *p4;
if( isCommuted ){
p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft);
}else{
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
}
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
@@ -594,7 +563,6 @@ static void codeVectorCompare(
int regRight = 0;
u8 opx = op;
int addrDone = sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
@@ -624,7 +592,7 @@ static void codeVectorCompare(
assert( i>=0 && i<nLeft );
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5, isCommuted);
codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
@@ -3399,36 +3367,16 @@ void sqlite3ExprCodeLoadIndexColumn(
}
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/*
** Generate code that will compute the value of generated column pCol
** and store the result in register regOut
*/
void sqlite3ExprCodeGeneratedColumn(
Parse *pParse,
Column *pCol,
int regOut
){
sqlite3ExprCode(pParse, pCol->pDflt, regOut);
if( pCol->affinity>=SQLITE_AFF_TEXT ){
sqlite3VdbeAddOp4(pParse->pVdbe, OP_Affinity, regOut, 1, 0,
&pCol->affinity, 1);
}
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
/*
** Generate code to extract the value of the iCol-th column of a table.
*/
void sqlite3ExprCodeGetColumnOfTable(
Vdbe *v, /* Parsing context */
Vdbe *v, /* The VDBE under construction */
Table *pTab, /* The table containing the value */
int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */
int iCol, /* Index of the column to extract */
int regOut /* Extract the value into this register */
){
Column *pCol;
assert( v!=0 );
if( pTab==0 ){
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
return;
@@ -3436,36 +3384,14 @@ void sqlite3ExprCodeGetColumnOfTable(
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
}else{
int op;
int x;
if( IsVirtual(pTab) ){
op = OP_VColumn;
x = iCol;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
Parse *pParse = sqlite3VdbeParser(v);
if( pCol->colFlags & COLFLAG_BUSY ){
sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zName);
}else{
int savedSelfTab = pParse->iSelfTab;
pCol->colFlags |= COLFLAG_BUSY;
pParse->iSelfTab = iTabCur+1;
sqlite3ExprCodeGeneratedColumn(pParse, pCol, regOut);
pParse->iSelfTab = savedSelfTab;
pCol->colFlags &= ~COLFLAG_BUSY;
}
return;
#endif
}else if( !HasRowid(pTab) ){
testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) );
x = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
op = OP_Column;
}else{
x = sqlite3TableColumnToStorage(pTab,iCol);
testcase( x!=iCol );
op = OP_Column;
int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
int x = iCol;
if( !HasRowid(pTab) && !IsVirtual(pTab) ){
x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
}
sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
}
if( iCol>=0 ){
sqlite3ColumnDefault(v, pTab, iCol, regOut);
}
}
@@ -3485,10 +3411,11 @@ int sqlite3ExprCodeGetColumn(
int iReg, /* Store results here */
u8 p5 /* P5 value for OP_Column + FLAGS */
){
assert( pParse->pVdbe!=0 );
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg);
Vdbe *v = pParse->pVdbe;
assert( v!=0 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
if( p5 ){
sqlite3VdbeChangeP5(pParse->pVdbe, p5);
sqlite3VdbeChangeP5(v, p5);
}
return iReg;
}
@@ -3624,46 +3551,19 @@ expr_code_doover:
}
if( iTab<0 ){
if( pParse->iSelfTab<0 ){
/* Other columns in the same row for CHECK constraints or
** generated columns or for inserting into partial index.
** The row is unpacked into registers beginning at
** 0-(pParse->iSelfTab). The rowid (if any) is in a register
** immediately prior to the first column.
*/
Column *pCol;
Table *pTab = pExpr->y.pTab;
int iSrc;
int iCol = pExpr->iColumn;
assert( pTab!=0 );
assert( iCol>=XN_ROWID );
assert( iCol<pExpr->y.pTab->nCol );
if( iCol<0 ){
return -1-pParse->iSelfTab;
}
pCol = pTab->aCol + iCol;
testcase( iCol!=sqlite3TableColumnToStorage(pTab,iCol) );
iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( pCol->colFlags & COLFLAG_GENERATED ){
if( pCol->colFlags & COLFLAG_BUSY ){
sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
pCol->zName);
return 0;
}
pCol->colFlags |= COLFLAG_BUSY;
if( pCol->colFlags & COLFLAG_NOTAVAIL ){
sqlite3ExprCodeGeneratedColumn(pParse, pCol, iSrc);
}
pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL);
return iSrc;
}else
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
if( pCol->affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp2(v, OP_SCopy, iSrc, target);
/* Generating CHECK constraints or inserting into partial index */
assert( pExpr->y.pTab!=0 );
assert( pExpr->iColumn>=XN_ROWID );
assert( pExpr->iColumn<pExpr->y.pTab->nCol );
if( pExpr->iColumn>=0
&& pExpr->y.pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
){
sqlite3VdbeAddOp2(v, OP_SCopy, pExpr->iColumn - pParse->iSelfTab,
target);
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
return target;
}else{
return iSrc;
return pExpr->iColumn - pParse->iSelfTab;
}
}else{
/* Coding an expression that is part of an index where column names
@@ -3762,8 +3662,7 @@ expr_code_doover:
r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2 | p5,
ExprHasProperty(pExpr,EP_Commuted));
r1, r2, inReg, SQLITE_STOREP2 | p5);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
@@ -4131,19 +4030,17 @@ expr_code_doover:
** p1==2 -> old.b p1==5 -> new.b
*/
Table *pTab = pExpr->y.pTab;
int iCol = pExpr->iColumn;
int p1 = pExpr->iTable * (pTab->nCol+1) + 1
+ (iCol>=0 ? sqlite3TableColumnToStorage(pTab, iCol) : -1);
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
assert( pExpr->iTable==0 || pExpr->iTable==1 );
assert( iCol>=-1 && iCol<pTab->nCol );
assert( pTab->iPKey<0 || iCol!=pTab->iPKey );
assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey );
assert( p1>=0 && p1<(pTab->nCol*2+2) );
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "r[%d]=%s.%s", target,
(pExpr->iTable ? "new" : "old"),
(pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zName)
(pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName)
));
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -4152,7 +4049,9 @@ expr_code_doover:
**
** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to
** floating point when extracting it from the record. */
if( iCol>=0 && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){
if( pExpr->iColumn>=0
&& pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
){
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}
#endif
@@ -4385,10 +4284,14 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
int inReg;
assert( target>0 && target<=pParse->nMem );
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
if( inReg!=target && pParse->pVdbe ){
sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
if( pExpr && pExpr->op==TK_REGISTER ){
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
}else{
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
if( inReg!=target && pParse->pVdbe ){
sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
}
}
}
@@ -4418,6 +4321,30 @@ void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
}
}
/*
** Generate code that evaluates the given expression and puts the result
** in register target.
**
** Also make a copy of the expression results into another "cache" register
** and modify the expression so that the next time it is evaluated,
** the result is a copy of the cache register.
**
** This routine is used for expressions that are used multiple
** times. They are evaluated once and the results of the expression
** are reused.
*/
void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
Vdbe *v = pParse->pVdbe;
int iMem;
assert( target>0 );
assert( pExpr->op!=TK_REGISTER );
sqlite3ExprCode(pParse, pExpr, target);
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
exprToRegister(pExpr, iMem);
}
/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
@@ -4655,7 +4582,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr,EP_Commuted));
r1, r2, dest, jumpIfNull);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
@@ -4830,7 +4757,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull,ExprHasProperty(pExpr,EP_Commuted));
r1, r2, dest, jumpIfNull);
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
@@ -5016,8 +4943,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
return 2;
}
}
if( (pA->flags & (EP_Distinct|EP_Commuted))
!= (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2;
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( (combinedFlags & EP_TokenOnly)==0 ){
if( combinedFlags & EP_xIsSelect ) return 2;
if( (combinedFlags & EP_FixedCol)==0
@@ -5220,7 +5146,6 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
case TK_CASE:
case TK_IN:
case TK_FUNCTION:
case TK_TRUTH:
testcase( pExpr->op==TK_ISNOT );
testcase( pExpr->op==TK_ISNULL );
testcase( pExpr->op==TK_NOTNULL );
@@ -5229,7 +5154,6 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_CASE );
testcase( pExpr->op==TK_IN );
testcase( pExpr->op==TK_FUNCTION );
testcase( pExpr->op==TK_TRUTH );
return WRC_Prune;
case TK_COLUMN:
if( pWalker->u.iCur==pExpr->iTable ){
@@ -5239,11 +5163,10 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
return WRC_Prune;
case TK_AND:
assert( pWalker->eCode==0 );
sqlite3WalkExpr(pWalker, pExpr->pLeft);
if( pWalker->eCode ){
pWalker->eCode = 0;
sqlite3WalkExpr(pWalker, pExpr->pRight);
if( sqlite3ExprImpliesNonNullRow(pExpr->pLeft, pWalker->u.iCur)
&& sqlite3ExprImpliesNonNullRow(pExpr->pRight, pWalker->u.iCur)
){
pWalker->eCode = 1;
}
return WRC_Prune;
@@ -5302,13 +5225,14 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
Walker w;
p = sqlite3ExprSkipCollateAndLikely(p);
if( p==0 ) return 0;
if( p->op==TK_NOTNULL ){
p = p->pLeft;
}else{
while( p->op==TK_AND ){
while( p ){
if( p->op==TK_NOTNULL ){
p = p->pLeft;
}else if( p->op==TK_AND ){
if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1;
p = p->pRight;
}else{
break;
}
}
w.xExprCallback = impliesNotNullRow;
@@ -5340,7 +5264,7 @@ struct IdxCover {
static int exprIdxCover(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pWalker->u.pIdxCover->iCur
&& sqlite3TableColumnToIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
&& sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
){
pWalker->eCode = 1;
return WRC_Abort;
+7 -13
View File
@@ -349,7 +349,7 @@ static void fkLookupParent(
VdbeCoverage(v);
}
for(i=0; i<pFKey->nCol; i++){
int iReg = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i]) + regData + 1;
int iReg = aiCol[i] + regData + 1;
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v);
}
@@ -365,8 +365,7 @@ static void fkLookupParent(
** is no matching parent key. Before using MustBeInt, make a copy of
** the value. Otherwise, the value inserted into the child key column
** will have INTEGER affinity applied to it, which may not be correct. */
sqlite3VdbeAddOp2(v, OP_SCopy,
sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[0])+1+regData, regTemp);
sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
VdbeCoverage(v);
@@ -393,9 +392,7 @@ static void fkLookupParent(
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp2(v, OP_Copy,
sqlite3TableColumnToStorage(pFKey->pFrom, aiCol[i])+1+regData,
regTemp+i);
sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
}
/* If the parent table is the same as the child table, and we are about
@@ -411,11 +408,8 @@ static void fkLookupParent(
if( pTab==pFKey->pFrom && nIncr==1 ){
int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
for(i=0; i<nCol; i++){
int iChild = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i])
+1+regData;
int iParent = 1+regData;
iParent += sqlite3TableColumnToStorage(pIdx->pTable,
pIdx->aiColumn[i]);
int iChild = aiCol[i]+1+regData;
int iParent = pIdx->aiColumn[i]+1+regData;
assert( pIdx->aiColumn[i]>=0 );
assert( aiCol[i]!=pTab->iPKey );
if( pIdx->aiColumn[i]==pTab->iPKey ){
@@ -1305,7 +1299,7 @@ static Trigger *fkActionTrigger(
}
/* Disable lookaside memory allocation */
DisableLookaside;
db->lookaside.bDisable++;
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
sizeof(Trigger) + /* struct Trigger */
@@ -1327,7 +1321,7 @@ static Trigger *fkActionTrigger(
}
/* Re-enable the lookaside buffer, if it was disabled earlier. */
EnableLookaside;
db->lookaside.bDisable--;
sqlite3ExprDelete(db, pWhere);
sqlite3ExprDelete(db, pWhen);
+89 -276
View File
@@ -37,7 +37,7 @@ void sqlite3OpenTable(
sqlite3TableLock(pParse, iDb, pTab->tnum,
(opcode==OP_OpenWrite)?1:0, pTab->zName);
if( HasRowid(pTab) ){
sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol);
sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
VdbeComment((v, "%s", pTab->zName));
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
@@ -129,7 +129,7 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
** 'E' REAL
*/
void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
int i, j;
int i;
char *zColAff = pTab->zColAff;
if( zColAff==0 ){
sqlite3 *db = sqlite3VdbeDb(v);
@@ -139,15 +139,13 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
return;
}
for(i=j=0; i<pTab->nCol; i++){
for(i=0; i<pTab->nCol; i++){
assert( pTab->aCol[i].affinity!=0 );
if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
zColAff[j++] = pTab->aCol[i].affinity;
}
zColAff[i] = pTab->aCol[i].affinity;
}
do{
zColAff[j--] = 0;
}while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB );
zColAff[i--] = 0;
}while( i>=0 && zColAff[i]<=SQLITE_AFF_BLOB );
pTab->zColAff = zColAff;
}
assert( zColAff!=0 );
@@ -201,61 +199,6 @@ static int readsTable(Parse *p, int iDb, Table *pTab){
return 0;
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/*
** All regular columns for table pTab have been puts into registers
** starting with iRegStore. The registers that correspond to STORED
** or VIRTUAL columns have not yet been initialized. This routine goes
** back and computes the values for those columns based on the previously
** computed normal columns.
*/
void sqlite3ComputeGeneratedColumns(
Parse *pParse, /* Parsing context */
int iRegStore, /* Register holding the first column */
Table *pTab /* The table */
){
int i;
int nv;
/* Because there can be multiple generated columns that refer to one another,
** this is a two-pass algorithm. On the first pass, mark all generated
** columns as "not available".
*/
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
pTab->aCol[i].colFlags |= COLFLAG_NOTAVAIL;
}
}
/* On the second pass, compute the value of each NOT-AVAILABLE column.
** Companion code in the TK_COLUMN case of sqlite3ExprCodeTarget() will
** compute dependencies and mark remove the COLSPAN_NOTAVAIL mark, as
** they are needed.
*/
pParse->iSelfTab = -iRegStore;
for(i=nv=0; i<pTab->nCol; i++){
u32 colFlags = pTab->aCol[i].colFlags;
if( (colFlags & COLFLAG_NOTAVAIL)!=0 ){
assert( colFlags & COLFLAG_GENERATED );
if( colFlags & COLFLAG_VIRTUAL ){
/* Virtual columns go at the end */
assert( pTab->nNVCol+nv == sqlite3TableColumnToStorage(pTab,i) );
sqlite3ExprCodeGeneratedColumn(pParse, &pTab->aCol[i],
iRegStore+pTab->nNVCol+nv);
}else{
/* Stored columns go in column order */
assert( i-nv == sqlite3TableColumnToStorage(pTab,i) );
sqlite3ExprCodeGeneratedColumn(pParse, &pTab->aCol[i], iRegStore+i-nv);
}
pTab->aCol[i].colFlags &= ~COLFLAG_NOTAVAIL;
}
if( (colFlags & COLFLAG_VIRTUAL)!=0 ) nv++;
}
pParse->iSelfTab = 0;
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
#ifndef SQLITE_OMIT_AUTOINCREMENT
/*
** Locate or create an AutoincInfo structure associated with table pTab
@@ -563,7 +506,7 @@ void sqlite3Insert(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* Name of table into which we are inserting */
Select *pSelect, /* A SELECT statement to use as the data source */
IdList *pColumn, /* Column names corresponding to IDLIST, or NULL. */
IdList *pColumn, /* Column names corresponding to IDLIST. */
int onError, /* How to handle constraint errors */
Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */
){
@@ -588,7 +531,6 @@ void sqlite3Insert(
u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
u8 bIdListInOrder; /* True if IDLIST is in table order */
ExprList *pList = 0; /* List of VALUES() to be inserted */
int iRegStore; /* Register in which to store next column */
/* Register allocations */
int regFromSelect = 0;/* Base register for data coming from SELECT */
@@ -696,8 +638,8 @@ void sqlite3Insert(
*/
regAutoinc = autoIncBegin(pParse, iDb, pTab);
/* Allocate a block registers to hold the rowid and the values
** for all columns of the new row.
/* Allocate registers for holding the rowid of the new row,
** the content of the new row, and the assembled row record.
*/
regRowid = regIns = pParse->nMem+1;
pParse->nMem += pTab->nCol + 1;
@@ -716,17 +658,9 @@ void sqlite3Insert(
** the index into IDLIST of the primary key column. ipkColumn is
** the index of the primary key as it appears in IDLIST, not as
** is appears in the original table. (The index of the INTEGER
** PRIMARY KEY in the original table is pTab->iPKey.) After this
** loop, if ipkColumn==(-1), that means that integer primary key
** is unspecified, and hence the table is either WITHOUT ROWID or
** it will automatically generated an integer primary key.
**
** bIdListInOrder is true if the columns in IDLIST are in storage
** order. This enables an optimization that avoids shuffling the
** columns into storage order. False negatives are harmless,
** but false positives will cause database corruption.
** PRIMARY KEY in the original table is pTab->iPKey.)
*/
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0;
if( pColumn ){
for(i=0; i<pColumn->nId; i++){
pColumn->a[i].idx = -1;
@@ -739,14 +673,6 @@ void sqlite3Insert(
if( j==pTab->iPKey ){
ipkColumn = i; assert( !withoutRowid );
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
sqlite3ErrorMsg(pParse,
"cannot INSERT into generated column \"%s\"",
pTab->aCol[j].zName);
goto insert_cleanup;
}
#endif
break;
}
}
@@ -856,26 +782,13 @@ void sqlite3Insert(
*/
if( pColumn==0 && nColumn>0 ){
ipkColumn = pTab->iPKey;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( ipkColumn>=0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
for(i=ipkColumn-1; i>=0; i--){
if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
ipkColumn--;
}
}
}
#endif
}
/* Make sure the number of columns in the source data matches the number
** of columns to be inserted into the table.
*/
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
}
if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
sqlite3ErrorMsg(pParse,
@@ -960,88 +873,8 @@ void sqlite3Insert(
*/
addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
VdbeCoverage(v);
if( ipkColumn>=0 ){
/* tag-20191021-001: If the INTEGER PRIMARY KEY is being generated by the
** SELECT, go ahead and copy the value into the rowid slot now, so that
** the value does not get overwritten by a NULL at tag-20191021-002. */
sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
}
}
/* Compute data for ordinary columns of the new entry. Values
** are written in storage order into registers starting with regData.
** Only ordinary columns are computed in this loop. The rowid
** (if there is one) is computed later and generated columns are
** computed after the rowid since they might depend on the value
** of the rowid.
*/
nHidden = 0;
iRegStore = regData; assert( regData==regRowid+1 );
for(i=0; i<pTab->nCol; i++, iRegStore++){
int k;
u32 colFlags;
assert( i>=nHidden );
if( i==pTab->iPKey ){
/* tag-20191021-002: References to the INTEGER PRIMARY KEY are filled
** using the rowid. So put a NULL in the IPK slot of the record to avoid
** using excess space. The file format definition requires this extra
** NULL - we cannot optimize further by skipping the column completely */
sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
continue;
}
if( ((colFlags = pTab->aCol[i].colFlags) & COLFLAG_NOINSERT)!=0 ){
nHidden++;
if( (colFlags & COLFLAG_VIRTUAL)!=0 ){
/* Virtual columns do not participate in OP_MakeRecord. So back up
** iRegStore by one slot to compensate for the iRegStore++ in the
** outer for() loop */
iRegStore--;
continue;
}else if( (colFlags & COLFLAG_STORED)!=0 ){
/* Stored columns are computed later. But if there are BEFORE
** triggers, the slots used for stored columns will be OP_Copy-ed
** to a second block of registers, so the register needs to be
** initialized to NULL to avoid an uninitialized register read */
if( tmask & TRIGGER_BEFORE ){
sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
}
continue;
}else if( pColumn==0 ){
/* Hidden columns that are not explicitly named in the INSERT
** get there default value */
sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
continue;
}
}
if( pColumn ){
for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
if( j>=pColumn->nId ){
/* A column not named in the insert column list gets its
** default value */
sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
continue;
}
k = j;
}else if( nColumn==0 ){
/* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
continue;
}else{
k = i - nHidden;
}
if( useTempTable ){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, k, iRegStore);
}else if( pSelect ){
if( regFromSelect!=regData ){
sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
}
}else{
sqlite3ExprCode(pParse, pList->a[k].pExpr, iRegStore);
}
}
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqlite3VdbeMakeLabel(pParse);
@@ -1076,21 +909,25 @@ void sqlite3Insert(
*/
assert( !IsVirtual(pTab) );
/* Copy the new data already generated. */
assert( pTab->nNVCol>0 );
sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Compute the new value for generated columns after all other
** columns have already been computed. This must be done after
** computing the ROWID in case one of the generated columns
** refers to the ROWID. */
if( pTab->tabFlags & TF_HasGenerated ){
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
sqlite3ComputeGeneratedColumns(pParse, regCols+1, pTab);
/* Create the new column data
*/
for(i=j=0; i<pTab->nCol; i++){
if( pColumn ){
for(j=0; j<pColumn->nId; j++){
if( pColumn->a[j].idx==i ) break;
}
}
if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId)
|| (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
}else if( useTempTable ){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
}else{
assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
}
if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++;
}
#endif
/* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
** do not attempt any conversions before assembling the record.
@@ -1108,17 +945,19 @@ void sqlite3Insert(
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
}
/* Compute the content of the next row to insert into a range of
** registers beginning at regIns.
*/
if( !isView ){
if( IsVirtual(pTab) ){
/* The row that the VUpdate opcode will delete: none */
sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
}
if( ipkColumn>=0 ){
/* Compute the new rowid */
if( useTempTable ){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid);
}else if( pSelect ){
/* Rowid already initialized at tag-20191021-001 */
sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
}else{
Expr *pIpk = pList->a[ipkColumn].pExpr;
if( pIpk->op==TK_NULL && !IsVirtual(pTab) ){
@@ -1151,17 +990,45 @@ void sqlite3Insert(
}
autoIncStep(pParse, regAutoinc, regRowid);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Compute the new value for generated columns after all other
** columns have already been computed. This must be done after
** computing the ROWID in case one of the generated columns
** refers to the ROWID. */
if( pTab->tabFlags & TF_HasGenerated ){
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
sqlite3ComputeGeneratedColumns(pParse, regRowid+1, pTab);
/* Compute data for all columns of the new entry, beginning
** with the first column.
*/
nHidden = 0;
for(i=0; i<pTab->nCol; i++){
int iRegStore = regRowid+1+i;
if( i==pTab->iPKey ){
/* The value of the INTEGER PRIMARY KEY column is always a NULL.
** Whenever this column is read, the rowid will be substituted
** in its place. Hence, fill this column with a NULL to avoid
** taking up data space with information that will never be used.
** As there may be shallow copies of this value, make it a soft-NULL */
sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
continue;
}
if( pColumn==0 ){
if( IsHiddenColumn(&pTab->aCol[i]) ){
j = -1;
nHidden++;
}else{
j = i - nHidden;
}
}else{
for(j=0; j<pColumn->nId; j++){
if( pColumn->a[j].idx==i ) break;
}
}
if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
}else if( useTempTable ){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
}else if( pSelect ){
if( regFromSelect!=regData ){
sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
}
}else{
sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
}
}
#endif
/* Generate code to check constraints and generate index keys and
** do the insertion.
@@ -1191,7 +1058,9 @@ void sqlite3Insert(
** cursor that is disturbed. And these instructions both clear the
** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
** functionality. */
bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v));
bUseSeek = (isReplace==0 || (pTrigger==0 &&
((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
));
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
regIns, aRegIdx, 0, appendFlag, bUseSeek
);
@@ -1479,7 +1348,6 @@ void sqlite3GenerateConstraintChecks(
/* Test all NOT NULL constraints.
*/
for(i=0; i<nCol; i++){
int iReg;
if( i==pTab->iPKey ){
continue; /* ROWID is never NULL */
}
@@ -1500,18 +1368,14 @@ void sqlite3GenerateConstraintChecks(
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace );
addr1 = 0;
testcase( i!=sqlite3TableColumnToStorage(pTab, i) );
testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1;
switch( onError ){
case OE_Replace: {
assert( onError==OE_Replace );
addr1 = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_NotNull, iReg, addr1);
sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
VdbeCoverage(v);
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
sqlite3VdbeAddOp2(v, OP_NotNull, iReg, addr1);
sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
VdbeCoverage(v);
onError = OE_Abort;
/* Fall through into the OE_Abort case to generate code that runs
@@ -1525,7 +1389,7 @@ void sqlite3GenerateConstraintChecks(
char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
pTab->aCol[i].zName);
sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
iReg);
regNewData+1+i);
sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
VdbeCoverage(v);
@@ -1534,7 +1398,7 @@ void sqlite3GenerateConstraintChecks(
}
default: {
assert( onError==OE_Ignore );
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, ignoreDest);
sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
VdbeCoverage(v);
break;
}
@@ -1718,9 +1582,6 @@ void sqlite3GenerateConstraintChecks(
sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regNewData, 1, 0, OE_Replace, 1, -1);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
VdbeCoverage(v);
sqlite3RowidConstraint(pParse, OE_Abort, pTab);
}else{
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
assert( HasRowid(pTab) );
@@ -1809,22 +1670,14 @@ void sqlite3GenerateConstraintChecks(
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
pParse->iSelfTab = 0;
VdbeComment((v, "%s column %d", pIdx->zName, i));
}else if( iField==XN_ROWID || iField==pTab->iPKey ){
x = regNewData;
sqlite3VdbeAddOp2(v, OP_IntCopy, x, regIdx+i);
VdbeComment((v, "rowid"));
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( pTab->aCol[iField].colFlags & COLFLAG_VIRTUAL ){
pParse->iSelfTab = -(regNewData+1);
sqlite3ExprCodeCopy(pParse, pTab->aCol[iField].pDflt, regIdx+i);
pParse->iSelfTab = 0;
VdbeComment((v, "%s column %d", pIdx->zName, i));
#endif
}else{
testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField );
x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
VdbeComment((v, "%s", pTab->aCol[iField].zName));
if( iField==XN_ROWID || iField==pTab->iPKey ){
x = regNewData;
}else{
x = iField + regNewData + 1;
}
sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i);
VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
}
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
@@ -1913,7 +1766,7 @@ void sqlite3GenerateConstraintChecks(
if( pIdx!=pPk ){
for(i=0; i<pPk->nKeyCol; i++){
assert( pPk->aiColumn[i]>=0 );
x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
VdbeComment((v, "%s.%s", pTab->zName,
pTab->aCol[pPk->aiColumn[i]].zName));
@@ -1976,23 +1829,16 @@ void sqlite3GenerateConstraintChecks(
}
default: {
Trigger *pTrigger = 0;
int bRetryConstraintCheck = 0;
assert( onError==OE_Replace );
if( db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
bRetryConstraintCheck = 1;
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regR, nPkField, 0, OE_Replace,
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
if( bRetryConstraintCheck ){
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);
}
seenReplace = 1;
break;
}
@@ -2016,7 +1862,7 @@ void sqlite3GenerateConstraintChecks(
/* Generate the table record */
if( HasRowid(pTab) ){
int regRec = aRegIdx[ix];
sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nNVCol, regRec);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nCol, regRec);
sqlite3SetMakeRecordP5(v, pTab);
if( !bAffinityDone ){
sqlite3TableAffinity(v, pTab, 0);
@@ -2410,39 +2256,6 @@ static int xferOptimization(
){
return 0; /* Neither table may have __hidden__ columns */
}
#endif
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Even if tables t1 and t2 have identical schemas, if they contain
** generated columns, then this statement is semantically incorrect:
**
** INSERT INTO t2 SELECT * FROM t1;
**
** The reason is that generated column values are returned by the
** the SELECT statement on the right but the INSERT statement on the
** left wants them to be omitted.
**
** Nevertheless, this is a useful notational shorthand to tell SQLite
** to do a bulk transfer all of the content from t1 over to t2.
**
** We could, in theory, disable this (except for internal use by the
** VACUUM command where it is actually needed). But why do that? It
** seems harmless enough, and provides a useful service.
*/
if( (pDestCol->colFlags & COLFLAG_GENERATED) !=
(pSrcCol->colFlags & COLFLAG_GENERATED) ){
return 0; /* Both columns have the same generated-column type */
}
/* But the transfer is only allowed if both the source and destination
** tables have the exact same expressions for generated columns.
** This requirement could be relaxed for VIRTUAL columns, I suppose.
*/
if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
if( sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
testcase( pDestCol->colFlags & COLFLAG_STORED );
return 0; /* Different generator expressions */
}
}
#endif
if( pDestCol->affinity!=pSrcCol->affinity ){
return 0; /* Affinity must be the same on all columns */
@@ -2454,7 +2267,7 @@ static int xferOptimization(
return 0; /* tab2 must be NOT NULL if tab1 is */
}
/* Default values for second and subsequent columns need to match. */
if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
if( i>0 ){
assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0)
-3
View File
@@ -715,7 +715,6 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
db->lookaside.pInit = 0;
db->lookaside.pFree = 0;
db->lookaside.sz = (u16)sz;
db->lookaside.szTrue = (u16)sz;
if( pStart ){
int i;
LookasideSlot *p;
@@ -734,7 +733,6 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
db->lookaside.pStart = db;
db->lookaside.pEnd = db;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
db->lookaside.bMalloced = 0;
db->lookaside.nSlot = 0;
}
@@ -3066,7 +3064,6 @@ static int openDatabase(
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
+22 -20
View File
@@ -298,7 +298,7 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
return sqlite3GlobalConfig.m.xSize(p);
}else{
assert( sqlite3_mutex_held(db->mutex) );
return db->lookaside.szTrue;
return db->lookaside.sz;
}
}
sqlite3_uint64 sqlite3_msize(void *p){
@@ -350,7 +350,7 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
LookasideSlot *pBuf = (LookasideSlot*)p;
#ifdef SQLITE_DEBUG
/* Trash all content in the buffer being freed */
memset(p, 0xaa, db->lookaside.szTrue);
memset(p, 0xaa, db->lookaside.sz);
#endif
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
@@ -510,21 +510,23 @@ void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
assert( db->pnBytesFreed==0 );
if( n>db->lookaside.sz ){
if( db->lookaside.bDisable ){
return db->mallocFailed ? 0 : dbMallocRawFinish(db, n);
if( db->lookaside.bDisable==0 ){
assert( db->mallocFailed==0 );
if( n>db->lookaside.sz ){
db->lookaside.anStat[1]++;
}else if( (pBuf = db->lookaside.pFree)!=0 ){
db->lookaside.pFree = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
}else if( (pBuf = db->lookaside.pInit)!=0 ){
db->lookaside.pInit = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
}else{
db->lookaside.anStat[2]++;
}
db->lookaside.anStat[1]++;
}else if( (pBuf = db->lookaside.pFree)!=0 ){
db->lookaside.pFree = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
}else if( (pBuf = db->lookaside.pInit)!=0 ){
db->lookaside.pInit = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
}else{
db->lookaside.anStat[2]++;
}else if( db->mallocFailed ){
return 0;
}
#else
assert( db!=0 );
@@ -548,7 +550,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
assert( db!=0 );
if( p==0 ) return sqlite3DbMallocRawNN(db, n);
assert( sqlite3_mutex_held(db->mutex) );
if( isLookaside(db,p) && n<=db->lookaside.szTrue ) return p;
if( isLookaside(db,p) && n<=db->lookaside.sz ) return p;
return dbReallocFinish(db, p, n);
}
static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
@@ -559,7 +561,7 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
if( isLookaside(db, p) ){
pNew = sqlite3DbMallocRawNN(db, n);
if( pNew ){
memcpy(pNew, p, db->lookaside.szTrue);
memcpy(pNew, p, db->lookaside.sz);
sqlite3DbFree(db, p);
}
}else{
@@ -658,7 +660,7 @@ void sqlite3OomFault(sqlite3 *db){
if( db->nVdbeExec>0 ){
db->u1.isInterrupted = 1;
}
DisableLookaside;
db->lookaside.bDisable++;
if( db->pParse ){
db->pParse->rc = SQLITE_NOMEM_BKPT;
}
@@ -677,7 +679,7 @@ void sqlite3OomClear(sqlite3 *db){
db->mallocFailed = 0;
db->u1.isInterrupted = 0;
assert( db->lookaside.bDisable>0 );
EnableLookaside;
db->lookaside.bDisable--;
}
}
+1 -9
View File
@@ -106,9 +106,8 @@ struct FrameBound { int eType; Expr *pExpr; };
** shared across database connections.
*/
static void disableLookaside(Parse *pParse){
sqlite3 *db = pParse->db;
pParse->disableLookaside++;
DisableLookaside;
pParse->db->lookaside.bDisable++;
}
} // end %include
@@ -347,10 +346,6 @@ ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R).
{sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);}
ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);}
ccons ::= GENERATED ALWAYS AS generated.
ccons ::= AS generated.
generated ::= LP expr(E) RP. {sqlite3AddGenerated(pParse,E,0);}
generated ::= LP expr(E) RP ID(TYPE). {sqlite3AddGenerated(pParse,E,&TYPE);}
// The optional AUTOINCREMENT keyword
%type autoinc {int}
@@ -1075,9 +1070,6 @@ expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. {
A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
if( A ){
A->x.pList = pList;
if( pList->nExpr ){
A->flags |= pList->a[0].pExpr->flags & EP_Propagate;
}
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
+7 -16
View File
@@ -1100,19 +1100,10 @@ void sqlite3Pragma(
sqlite3CodeVerifySchema(pParse, iTabDb);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
int isHidden = 0;
if( pCol->colFlags & COLFLAG_NOINSERT ){
if( pPragma->iArg==0 ){
nHidden++;
continue;
}
if( pCol->colFlags & COLFLAG_VIRTUAL ){
isHidden = 2; /* GENERATED ALWAYS AS ... VIRTUAL */
}else if( pCol->colFlags & COLFLAG_STORED ){
isHidden = 3; /* GENERATED ALWAYS AS ... STORED */
}else{ assert( pCol->colFlags & COLFLAG_HIDDEN );
isHidden = 1; /* HIDDEN */
}
int isHidden = IsHiddenColumn(pCol);
if( isHidden && pPragma->iArg==0 ){
nHidden++;
continue;
}
if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
k = 0;
@@ -1121,13 +1112,13 @@ void sqlite3Pragma(
}else{
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN || isHidden>=2 );
assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
i-nHidden,
pCol->zName,
sqlite3ColumnType(pCol,""),
pCol->notNull ? 1 : 0,
pCol->pDflt && isHidden<2 ? pCol->pDflt->u.zToken : 0,
pCol->pDflt ? pCol->pDflt->u.zToken : 0,
k,
isHidden);
}
@@ -1586,7 +1577,7 @@ void sqlite3Pragma(
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
if( !isQuick ){
/* Sanity check on record header decoding */
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
/* Verify that all NOT NULL columns really are NOT NULL */
+47 -39
View File
@@ -57,18 +57,6 @@ int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
return 0;
}
/* forward declaration */
static int sqlite3Prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
Vdbe *pReprepare, /* VM being reprepared */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
);
/*
** This is the callback routine for the code that initializes the
** database. See sqlite3Init() below for additional information.
@@ -118,8 +106,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
db->init.newTnum = sqlite3Atoi(argv[3]);
db->init.orphanTrigger = 0;
db->init.azInit = argv;
pStmt = 0;
TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
TESTONLY(rcp = ) sqlite3_prepare(db, argv[4], -1, &pStmt, 0);
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
@@ -540,7 +527,6 @@ void sqlite3ParserReset(Parse *pParse){
if( db ){
assert( db->lookaside.bDisable >= pParse->disableLookaside );
db->lookaside.bDisable -= pParse->disableLookaside;
db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
}
pParse->disableLookaside = 0;
}
@@ -574,7 +560,7 @@ static int sqlite3Prepare(
*/
if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
sParse.disableLookaside++;
DisableLookaside;
db->lookaside.bDisable++;
}
sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0;
@@ -601,18 +587,16 @@ static int sqlite3Prepare(
** but it does *not* override schema lock detection, so this all still
** works even if READ_UNCOMMITTED is set.
*/
if( !db->noSharedCache ){
for(i=0; i<db->nDb; i++) {
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
assert( sqlite3BtreeHoldsMutex(pBt) );
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
const char *zDb = db->aDb[i].zDbSName;
sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
testcase( db->flags & SQLITE_ReadUncommit );
goto end_prepare;
}
for(i=0; i<db->nDb; i++) {
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
assert( sqlite3BtreeHoldsMutex(pBt) );
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
const char *zDb = db->aDb[i].zDbSName;
sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
testcase( db->flags & SQLITE_ReadUncommit );
goto end_prepare;
}
}
}
@@ -643,24 +627,48 @@ static int sqlite3Prepare(
}
assert( 0==sParse.nQueryLoop );
if( sParse.rc==SQLITE_DONE ){
sParse.rc = SQLITE_OK;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.checkSchema ){
schemaIsValid(&sParse);
}
if( pzTail ){
*pzTail = sParse.zTail;
}
if( db->init.busy==0 ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
}
if( pzTail ){
*pzTail = sParse.zTail;
}
rc = sParse.rc;
if( rc!=SQLITE_OK ){
#ifndef SQLITE_OMIT_EXPLAIN
/* Justification for the ALWAYS(): The only way for rc to be SQLITE_OK and
** sParse.pVdbe to be NULL is if the input SQL is an empty string, but in
** that case, sParse.explain will be false. */
if( sParse.explain && rc==SQLITE_OK && ALWAYS(sParse.pVdbe) ){
static const char * const azColName[] = {
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
"id", "parent", "notused", "detail"
};
int iFirst, mx;
if( sParse.explain==2 ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
iFirst = 8;
mx = 12;
}else{
sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
iFirst = 0;
mx = 8;
}
for(i=iFirst; i<mx; i++){
sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
azColName[i], SQLITE_STATIC);
}
}
#endif
if( db->init.busy==0 ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
}
if( rc!=SQLITE_OK || db->mallocFailed ){
if( sParse.pVdbe ) sqlite3VdbeFinalize(sParse.pVdbe);
assert(!(*ppStmt));
}else{
+12 -19
View File
@@ -414,7 +414,7 @@ static int lookupName(
if( cnt==0
&& cntTab==1
&& pMatch
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& (pNC->ncFlags & NC_IdxExpr)==0
&& sqlite3IsRowid(zCol)
&& VisibleRowid(pMatch->pTab)
){
@@ -625,15 +625,12 @@ static void notValid(
const char *zMsg, /* Type of error */
int validMask /* Set of contexts for which prohibited */
){
assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 );
assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr))==0 );
if( (pNC->ncFlags & validMask)!=0 ){
const char *zIn = "partial index WHERE clauses";
if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
#ifndef SQLITE_OMIT_CHECK
else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
#endif
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
else if( pNC->ncFlags & NC_GenCol ) zIn = "generated columns";
#endif
sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
}
@@ -726,7 +723,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zColumn = pExpr->u.zToken;
}else{
Expr *pLeft = pExpr->pLeft;
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr|NC_GenCol);
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
zDb = 0;
@@ -823,7 +820,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** sqlite_version() that might change over time cannot be used
** in an index. */
notValid(pParse, pNC, "non-deterministic functions",
NC_IdxExpr|NC_PartIdx|NC_GenCol);
NC_IdxExpr|NC_PartIdx);
}
if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
&& pParse->nested==0
@@ -967,8 +964,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_IN );
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
int nRef = pNC->nRef;
notValid(pParse, pNC, "subqueries",
NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol);
notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
@@ -979,8 +975,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
break;
}
case TK_VARIABLE: {
notValid(pParse, pNC, "parameters",
NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol);
notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
break;
}
case TK_IS:
@@ -1793,7 +1788,6 @@ void sqlite3ResolveSelectNames(
** (2) WHERE clauses on partial indices
** (3) Expressions in indexes on expressions
** (4) Expression arguments to VACUUM INTO.
** (5) GENERATED ALWAYS as expressions
**
** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN
** nodes of the expression is set to -1 and the Expr.iColumn value is
@@ -1802,19 +1796,18 @@ void sqlite3ResolveSelectNames(
** Any errors cause an error message to be set in pParse.
*/
int sqlite3ResolveSelfReference(
Parse *pParse, /* Parsing context */
Table *pTab, /* The table being referenced, or NULL */
int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
Expr *pExpr, /* Expression to resolve. May be NULL. */
ExprList *pList /* Expression list to resolve. May be NULL. */
Parse *pParse, /* Parsing context */
Table *pTab, /* The table being referenced, or NULL */
int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr, or 0 */
Expr *pExpr, /* Expression to resolve. May be NULL. */
ExprList *pList /* Expression list to resolve. May be NULL. */
){
SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
NameContext sNC; /* Name context for pParse->pNewTable */
int rc;
assert( type==0 || pTab!=0 );
assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
|| type==NC_GenCol || pTab==0 );
assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr || pTab==0 );
memset(&sNC, 0, sizeof(sNC));
memset(&sSrc, 0, sizeof(sSrc));
if( pTab ){
+4 -12
View File
@@ -100,9 +100,9 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
sqlite3WindowListDelete(db, p->pWinDefn);
}
assert( p->pWin==0 );
#endif
if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
assert( p->pWin==0 );
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
@@ -3503,14 +3503,6 @@ static Expr *substExpr(
}else{
substExprList(pSubst, pExpr->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
Window *pWin = pExpr->y.pWin;
pWin->pFilter = substExpr(pSubst, pWin->pFilter);
substExprList(pSubst, pWin->pPartition);
substExprList(pSubst, pWin->pOrderBy);
}
#endif
}
return pExpr;
}
@@ -4170,14 +4162,14 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
if( pRight->op==TK_COLUMN
&& !ExprHasProperty(pRight, EP_FixedCol)
&& sqlite3ExprIsConstant(pLeft)
&& sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr))
&& sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
){
constInsert(pConst, pRight, pLeft);
}else
if( pLeft->op==TK_COLUMN
&& !ExprHasProperty(pLeft, EP_FixedCol)
&& sqlite3ExprIsConstant(pRight)
&& sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr))
&& sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
){
constInsert(pConst, pLeft, pRight);
}
@@ -5727,7 +5719,7 @@ int sqlite3Select(
goto select_end;
}
#if SELECTTRACE_ENABLED
if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
if( sqlite3SelectTrace & 0x108 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
+10 -33
View File
@@ -7758,19 +7758,10 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zCollist = 0;
sqlite3_stmt *pStmt;
int tnum = 0;
int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
int i;
if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
" .imposter off\n");
/* Also allowed, but not documented:
**
** .imposter TABLE IMPOSTER
**
** where TABLE is a WITHOUT ROWID table. In that case, the
** imposter is another WITHOUT ROWID table with the columns in
** storage order. */
rc = 1;
goto meta_command_exit;
}
@@ -7779,22 +7770,19 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
goto meta_command_exit;
}
zSql = sqlite3_mprintf(
"SELECT rootpage, 0 FROM sqlite_master"
" WHERE name='%q' AND type='index'"
"UNION ALL "
"SELECT rootpage, 1 FROM sqlite_master"
" WHERE name='%q' AND type='table'"
" AND sql LIKE '%%without%%rowid%%'",
azArg[1], azArg[1]
);
zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
" WHERE name='%q' AND type='index'", azArg[1]);
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
tnum = sqlite3_column_int(pStmt, 0);
isWO = sqlite3_column_int(pStmt, 1);
}
sqlite3_finalize(pStmt);
if( tnum==0 ){
utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
rc = 1;
goto meta_command_exit;
}
zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
@@ -7811,9 +7799,6 @@ static int do_meta_command(char *zLine, ShellState *p){
zCol = zLabel;
}
}
if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
lenPK = (int)strlen(zCollist);
}
if( zCollist==0 ){
zCollist = sqlite3_mprintf("\"%w\"", zCol);
}else{
@@ -7821,16 +7806,9 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}
sqlite3_finalize(pStmt);
if( i==0 || tnum==0 ){
utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
rc = 1;
sqlite3_free(zCollist);
goto meta_command_exit;
}
if( lenPK==0 ) lenPK = 100000;
zSql = sqlite3_mprintf(
"CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
azArg[2], zCollist, lenPK, zCollist);
"CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
azArg[2], zCollist, zCollist);
sqlite3_free(zCollist);
rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
if( rc==SQLITE_OK ){
@@ -7841,8 +7819,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
utf8_printf(stdout, "%s;\n", zSql);
raw_printf(stdout,
"WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
azArg[1], isWO ? "table" : "index"
"WARNING: writing to an imposter table will corrupt the index!\n"
);
}
}else{
+34 -93
View File
@@ -1271,17 +1271,10 @@ struct Schema {
** is shared by multiple database connections. Therefore, while parsing
** schema information, the Lookaside.bEnabled flag is cleared so that
** lookaside allocations are not used to construct the schema objects.
**
** New lookaside allocations are only allowed if bDisable==0. When
** bDisable is greater than zero, sz is set to zero which effectively
** disables lookaside without adding a new test for the bDisable flag
** in a performance-critical path. sz should be set by to szTrue whenever
** bDisable changes back to zero.
*/
struct Lookaside {
u32 bDisable; /* Only operate the lookaside when zero */
u16 sz; /* Size of each buffer in bytes */
u16 szTrue; /* True value of sz, even if disabled */
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
u32 nSlot; /* Number of lookaside slots allocated */
u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
@@ -1294,10 +1287,6 @@ struct LookasideSlot {
LookasideSlot *pNext; /* Next buffer in the list of free buffers */
};
#define DisableLookaside db->lookaside.bDisable++;db->lookaside.sz=0
#define EnableLookaside db->lookaside.bDisable--;\
db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue
/*
** A hash table for built-in function definitions. (Application-defined
** functions use a regular table table from hash.h.)
@@ -1818,45 +1807,26 @@ struct Module {
};
/*
** Information about each column of an SQL table is held in an instance
** of the Column structure, in the Table.aCol[] array.
**
** Definitions:
**
** "table column index" This is the index of the column in the
** Table.aCol[] array, and also the index of
** the column in the original CREATE TABLE stmt.
**
** "storage column index" This is the index of the column in the
** record BLOB generated by the OP_MakeRecord
** opcode. The storage column index is less than
** or equal to the table column index. It is
** equal if and only if there are no VIRTUAL
** columns to the left.
** information about each column of an SQL table is held in an instance
** of this structure.
*/
struct Column {
char *zName; /* Name of this column, \000, then the type */
Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */
Expr *pDflt; /* Default value of this column */
char *zColl; /* Collating sequence. If NULL, use the default */
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
char affinity; /* One of the SQLITE_AFF_... values */
u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
/* Allowed values for Column.colFlags:
*/
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
#define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */
#define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
#define COLFLAG_BUSY 0x0080 /* Blocks recursion on GENERATED columns */
#define COLFLAG_NOTAVAIL 0x0100 /* STORED column not yet calculated */
#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
/*
** A "Collating Sequence" is defined by an instance of the following
@@ -1996,7 +1966,6 @@ struct Table {
u32 tabFlags; /* Mask of TF_* values */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */
i16 nNVCol; /* Number of columns that are not VIRTUAL */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
@@ -2023,28 +1992,20 @@ struct Table {
** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
** the TF_OOOHidden attribute would apply in this case. Such tables require
** special handling during INSERT processing. The "OOO" means "Out Of Order".
**
** Constraints:
**
** TF_HasVirtual == COLFLAG_Virtual
** TF_HasStored == COLFLAG_Stored
** special handling during INSERT processing.
*/
#define TF_Readonly 0x0001 /* Read-only system table */
#define TF_Ephemeral 0x0002 /* An ephemeral table */
#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
#define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */
#define TF_HasStored 0x0040 /* Has one or more STORED columns */
#define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */
#define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */
#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */
#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */
#define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */
#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
#define TF_Shadow 0x0400 /* True for a shadow table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -2295,7 +2256,6 @@ struct Index {
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
#ifdef SQLITE_ENABLE_STAT4
int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
@@ -2556,7 +2516,7 @@ struct Expr {
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
#define EP_Commuted 0x000200 /* Comparison operator has been commuted */
/* 0x000200 Available for reuse */
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x001000 /* Operator does not contribute to affinity */
@@ -2625,13 +2585,9 @@ struct Expr {
** True if the expression passed as an argument was a function with
** an OVER() clause (a window function).
*/
#ifdef SQLITE_OMIT_WINDOWFUNC
# define IsWindowFunc(p) 0
#else
# define IsWindowFunc(p) ( \
#define IsWindowFunc(p) ( \
ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \
)
#endif
)
/*
** A list of expressions. Each expression may optionally have a
@@ -2837,22 +2793,21 @@ struct NameContext {
** NC_HasWin == EP_Win
**
*/
#define NC_AllowAgg 0x00001 /* Aggregate functions are allowed here */
#define NC_PartIdx 0x00002 /* True if resolving a partial index WHERE */
#define NC_IsCheck 0x00004 /* True if resolving a CHECK constraint */
#define NC_InAggFunc 0x00008 /* True if analyzing arguments to an agg func */
#define NC_HasAgg 0x00010 /* One or more aggregate functions seen */
#define NC_IdxExpr 0x00020 /* True if resolving columns of CREATE INDEX */
#define NC_VarSelect 0x00040 /* A correlated subquery has been seen */
#define NC_UEList 0x00080 /* True if uNC.pEList is used */
#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
#define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
#define NC_Complex 0x02000 /* True if a function or subquery seen */
#define NC_AllowWin 0x04000 /* Window functions are allowed here */
#define NC_HasWin 0x08000 /* One or more window functions seen */
#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
#define NC_GenCol 0x20000 /* True for a GENERATED ALWAYS AS clause */
#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */
#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */
#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */
#define NC_UEList 0x0080 /* True if uNC.pEList is used */
#define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */
#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
#define NC_Complex 0x2000 /* True if a function or subquery seen */
#define NC_AllowWin 0x4000 /* Window functions are allowed here */
#define NC_HasWin 0x8000 /* One or more window functions seen */
#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -3967,14 +3922,7 @@ void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
void sqlite3OpenMasterTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*);
i16 sqlite3TableColumnToIndex(Index*, i16);
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
#else
i16 sqlite3TableColumnToStorage(Table*, i16);
i16 sqlite3StorageColumnToTable(Table*, i16);
#endif
i16 sqlite3ColumnOfIndex(Index*, i16);
void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
#if SQLITE_ENABLE_HIDDEN_COLUMNS
void sqlite3ColumnPropertiesFromName(Table*, Column*);
@@ -3987,7 +3935,6 @@ void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
void sqlite3AddCheckConstraint(Parse*, Expr*);
void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
void sqlite3AddCollateType(Parse*, Token*);
void sqlite3AddGenerated(Parse*,Expr*,Token*);
void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
@@ -4045,9 +3992,6 @@ void sqlite3FreeIndex(sqlite3*, Index*);
# define sqlite3AutoincrementEnd(X)
#endif
void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
void sqlite3ComputeGeneratedColumns(Parse*, int, Table*);
#endif
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
@@ -4097,14 +4041,12 @@ int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int, int);
void sqlite3ExprCode(Parse*, Expr*, int);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
void sqlite3ExprCodeGeneratedColumn(Parse*, Column*, int);
#endif
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
@@ -4560,7 +4502,6 @@ char *sqlite3Normalize(Vdbe*, const char*);
#endif
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3ExprCompareCollSeq(Parse*,Expr*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
int sqlite3TempInMemory(const sqlite3*);
const char *sqlite3JournalModename(int);
+2 -2
View File
@@ -757,7 +757,7 @@ char *sqlite3Normalize(
int nParen; /* Number of nested levels of parentheses */
int iStartIN; /* Start of RHS of IN operator in z[] */
int nParenAtIN; /* Value of nParent at start of RHS of IN operator */
u32 j; /* Bytes of normalized SQL generated so far */
int j; /* Bytes of normalized SQL generated so far */
sqlite3_str *pStr; /* The normalized SQL string under construction */
db = sqlite3VdbeDb(pVdbe);
@@ -801,7 +801,7 @@ char *sqlite3Normalize(
}
case TK_RP: {
if( iStartIN>0 && nParen==nParenAtIN ){
assert( pStr->nChar>=(u32)iStartIN );
assert( pStr->nChar>=iStartIN );
pStr->nChar = iStartIN+1;
sqlite3_str_append(pStr, "?,?,?", 5);
iStartIN = 0;
+1 -3
View File
@@ -661,9 +661,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
break;
}
case TK_VECTOR: {
char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
sqlite3_free(z);
sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR");
break;
}
case TK_SELECT_COLUMN: {
+17 -80
View File
@@ -147,7 +147,7 @@ void sqlite3Update(
Expr *pLimit, /* LIMIT clause. May be null */
Upsert *pUpsert /* ON CONFLICT clause, or null */
){
int i, j, k; /* Loop counters */
int i, j; /* Loop counters */
Table *pTab; /* The table to be updated */
int addrTop = 0; /* VDBE instruction address of the start of the loop */
WhereInfo *pWInfo; /* Information about the WHERE clause */
@@ -289,10 +289,6 @@ void sqlite3Update(
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto update_cleanup;
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
@@ -312,16 +308,6 @@ void sqlite3Update(
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
chngPk = 1;
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
sqlite3ErrorMsg(pParse,
"cannot UPDATE generated column \"%s\"",
pTab->aCol[j].zName);
goto update_cleanup;
}
#endif
aXRef[j] = i;
break;
}
@@ -356,33 +342,6 @@ void sqlite3Update(
assert( chngPk==0 || chngPk==1 );
chngKey = chngRowid + chngPk;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* Mark generated columns as changing if their generator expressions
** reference any changing column. The actual aXRef[] value for
** generated expressions is not used, other than to check to see that it
** is non-negative, so the value of aXRef[] for generated columns can be
** set to any non-negative number. We use 99999 so that the value is
** obvious when looking at aXRef[] in a symbolic debugger.
*/
if( pTab->tabFlags & TF_HasGenerated ){
int bProgress;
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
do{
bProgress = 0;
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]>=0 ) continue;
if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
if( sqlite3ExprReferencesUpdatedColumn(pTab->aCol[i].pDflt,
aXRef, chngRowid) ){
aXRef[i] = 99999;
bProgress = 1;
}
}
}while( bProgress );
}
#endif
/* The SET expressions are not actually used inside the WHERE loop.
** So reset the colUsed mask. Unless this is a virtual table. In that
** case, set all bits of the colUsed mask (to ensure that the virtual
@@ -427,6 +386,9 @@ void sqlite3Update(
memset(aToOpen, 1, nIdx+1);
}
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto update_cleanup;
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);
@@ -580,8 +542,7 @@ void sqlite3Update(
** is not required) and leave the PK fields in the array of registers. */
for(i=0; i<nPk; i++){
assert( pPk->aiColumn[i]>=0 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,
pPk->aiColumn[i], iPk+i);
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i);
}
if( eOnePass ){
if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
@@ -661,20 +622,15 @@ void sqlite3Update(
oldmask |= sqlite3TriggerColmask(pParse,
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
);
for(i=0, k=regOld; i<pTab->nCol; i++, k++){
u32 colFlags = pTab->aCol[i].colFlags;
if( colFlags & COLFLAG_VIRTUAL ){
k--;
continue;
}
for(i=0; i<pTab->nCol; i++){
if( oldmask==0xffffffff
|| (i<32 && (oldmask & MASKBIT32(i))!=0)
|| (colFlags & COLFLAG_PRIMKEY)!=0
|| (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
){
testcase( oldmask!=0xffffffff && i==31 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, k);
sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
}
}
if( chngRowid==0 && pPk==0 ){
@@ -698,15 +654,13 @@ void sqlite3Update(
newmask = sqlite3TriggerColmask(
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
);
for(i=0, k=regNew; i<pTab->nCol; i++, k++){
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Null, 0, k);
}else if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)!=0 ){
if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
}else{
j = aXRef[i];
if( j>=0 ){
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k);
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
/* This branch loads the value of a column that will not be changed
** into a register. This is done if there are no BEFORE triggers, or
@@ -715,19 +669,12 @@ void sqlite3Update(
*/
testcase( i==31 );
testcase( i==32 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, k);
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
}
}
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( pTab->tabFlags & TF_HasGenerated ){
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
}
#endif
/* Fire any BEFORE UPDATE triggers. This happens before constraints are
** verified. One could argue that this is wrong.
@@ -760,20 +707,11 @@ void sqlite3Update(
** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26)
** for an example.
*/
for(i=0, k=regNew; i<pTab->nCol; i++, k++){
if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
}else if( aXRef[i]<0 && i!=pTab->iPKey ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]<0 && i!=pTab->iPKey ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
}
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
if( pTab->tabFlags & TF_HasGenerated ){
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
}
#endif
}
if( !isView ){
@@ -979,7 +917,6 @@ static void updateVirtualTable(
/* Populate the argument registers. */
for(i=0; i<pTab->nCol; i++){
assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 );
if( aXRef[i]>=0 ){
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
}else{
+1 -1
View File
@@ -226,7 +226,7 @@ void sqlite3UpsertDoUpdate(
for(i=0; i<nPk; i++){
int k;
assert( pPk->aiColumn[i]>=0 );
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
VdbeComment((v, "%s.%s", pIdx->zName,
pTab->aCol[pPk->aiColumn[i]].zName));
-6
View File
@@ -382,9 +382,6 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){
** returns FALSE but it still converts the prefix and writes the result
** into *pResult.
*/
#if defined(_MSC_VER)
#pragma warning(disable : 4756)
#endif
int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
#ifndef SQLITE_OMIT_FLOATING_POINT
int incr;
@@ -572,9 +569,6 @@ do_atof_calc:
return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}
#if defined(_MSC_VER)
#pragma warning(default : 4756)
#endif
/*
** Compare the 19-character string zNum against the text representation
+17 -20
View File
@@ -3143,11 +3143,11 @@ case OP_Count: { /* out2 */
pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
assert( pCrsr );
nEntry = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
rc = sqlite3BtreeCount(pCrsr, &nEntry);
if( rc ) goto abort_due_to_error;
pOut = out2Prerelease(p, pOp);
pOut->u.i = nEntry;
goto check_for_interrupt;
break;
}
#endif
@@ -3375,6 +3375,7 @@ case OP_AutoCommit: {
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
assert( db->nStatement==0 );
sqlite3CloseSavepoints(db);
if( p->rc==SQLITE_OK ){
rc = SQLITE_DONE;
@@ -3455,8 +3456,7 @@ case OP_Transaction: {
goto abort_due_to_error;
}
if( p->usesStmtJournal
&& pOp->p2
if( pOp->p2 && p->usesStmtJournal
&& (db->autoCommit==0 || db->nVdbeRead>1)
){
assert( sqlite3BtreeIsInTrans(pBt) );
@@ -4538,27 +4538,23 @@ case OP_SeekRowid: { /* jump, in3 */
pIn3 = &aMem[pOp->p3];
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_IntReal );
testcase( pIn3->flags & MEM_Real );
testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str );
if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
/* If pIn3->u.i does not contain an integer, compute iKey as the
** integer value of pIn3. Jump to P2 if pIn3 cannot be converted
** into an integer without loss of information. Take care to avoid
** changing the datatype of pIn3, however, as it is used by other
** parts of the prepared statement. */
Mem x = pIn3[0];
applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding);
if( (x.flags & MEM_Int)==0 ) goto jump_to_p2;
iKey = x.u.i;
goto notExistsWithKey;
/* Make sure pIn3->u.i contains a valid integer representation of
** the key value, but do not change the datatype of the register, as
** other parts of the perpared statement might be depending on the
** current datatype. */
u16 origFlags = pIn3->flags;
int isNotInt;
applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding);
isNotInt = (pIn3->flags & MEM_Int)==0;
pIn3->flags = origFlags;
if( isNotInt ) goto jump_to_p2;
}
/* Fall through into OP_NotExists */
case OP_NotExists: /* jump, in3 */
pIn3 = &aMem[pOp->p3];
assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
iKey = pIn3->u.i;
notExistsWithKey:
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
@@ -4569,6 +4565,7 @@ notExistsWithKey:
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
res = 0;
iKey = pIn3->u.i;
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
assert( rc==SQLITE_OK || res==0 );
pC->movetoTarget = iKey; /* Used by OP_Delete */
@@ -6103,7 +6100,7 @@ case OP_IntegrityCk: {
pIn1 = &aMem[pOp->p1];
assert( pOp->p5<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p5) );
z = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
(int)pnErr->u.i+1, &nErr);
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
@@ -6116,7 +6113,7 @@ case OP_IntegrityCk: {
}
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding);
goto check_for_interrupt;
break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+2 -2
View File
@@ -179,7 +179,6 @@ typedef struct VdbeOpList VdbeOpList;
** for a description of what each of these routines does.
*/
Vdbe *sqlite3VdbeCreate(Parse*);
Parse *sqlite3VdbeParser(Vdbe*);
int sqlite3VdbeAddOp0(Vdbe*,int);
int sqlite3VdbeAddOp1(Vdbe*,int,int);
int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
@@ -279,8 +278,9 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
#ifndef SQLITE_OMIT_TRIGGER
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
int sqlite3VdbeHasSubProgram(Vdbe*);
#endif
int sqlite3NotPureFunc(sqlite3_context*);
+1 -2
View File
@@ -286,8 +286,7 @@ struct sqlite3_value {
** True if Mem X is a NULL-nochng type.
*/
#define MemNullNochng(X) \
(((X)->flags&MEM_TypeMask)==(MEM_Null|MEM_Zero) \
&& (X)->n==0 && (X)->u.nZero==0)
((X)->flags==(MEM_Null|MEM_Zero) && (X)->n==0 && (X)->u.nZero==0)
/*
** Return true if a memory cell is not marked as invalid. This macro
+2 -2
View File
@@ -1831,7 +1831,7 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
goto preupdate_old_out;
}
if( p->pPk ){
iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
@@ -1921,7 +1921,7 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
goto preupdate_new_out;
}
if( p->pPk && p->op!=SQLITE_UPDATE ){
iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
+3 -35
View File
@@ -42,13 +42,6 @@ Vdbe *sqlite3VdbeCreate(Parse *pParse){
return p;
}
/*
** Return the Parse object that owns a Vdbe object.
*/
Parse *sqlite3VdbeParser(Vdbe *p){
return p->pParse;
}
/*
** Change the error string stored in Vdbe.zErrMsg
*/
@@ -647,7 +640,7 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
|| (opcode==OP_ParseSchema && pOp->p4.z==0)
|| (opcode==OP_Function0 && pOp->p4.pFunc->funcFlags&SQLITE_FUNC_INTERNAL)
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
@@ -1105,13 +1098,6 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
pVdbe->pProgram = p;
}
/*
** Return true if the given Vdbe has any SubPrograms.
*/
int sqlite3VdbeHasSubProgram(Vdbe *pVdbe){
return pVdbe->pProgram!=0;
}
/*
** Change the opcode at addr into OP_Noop
*/
@@ -2237,26 +2223,8 @@ void sqlite3VdbeMakeReady(
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
if( pParse->explain ){
static const char * const azColName[] = {
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
"id", "parent", "notused", "detail"
};
int iFirst, mx, i;
if( nMem<10 ) nMem = 10;
if( pParse->explain==2 ){
sqlite3VdbeSetNumCols(p, 4);
iFirst = 8;
mx = 12;
}else{
sqlite3VdbeSetNumCols(p, 8);
iFirst = 0;
mx = 8;
}
for(i=iFirst; i<mx; i++){
sqlite3VdbeSetColName(p, i-iFirst, COLNAME_NAME,
azColName[i], SQLITE_STATIC);
}
if( pParse->explain && nMem<10 ){
nMem = 10;
}
p->expired = 0;
+8 -3
View File
@@ -1396,16 +1396,20 @@ static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){
*/
static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
int i;
SorterRecord **aSlot;
SorterRecord *p;
int rc;
SorterRecord *aSlot[64];
rc = vdbeSortAllocUnpacked(pTask);
if( rc!=SQLITE_OK ) return rc;
p = pList->pList;
pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);
memset(aSlot, 0, sizeof(aSlot));
aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
if( !aSlot ){
return SQLITE_NOMEM_BKPT;
}
while( p ){
SorterRecord *pNext;
@@ -1430,12 +1434,13 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
}
p = 0;
for(i=0; i<ArraySize(aSlot); i++){
for(i=0; i<64; i++){
if( aSlot[i]==0 ) continue;
p = p ? vdbeSorterMerge(pTask, p, aSlot[i]) : aSlot[i];
}
pList->pList = p;
sqlite3_free(aSlot);
assert( pTask->pUnpacked->errCode==SQLITE_OK
|| pTask->pUnpacked->errCode==SQLITE_NOMEM
);
+2 -2
View File
@@ -305,12 +305,12 @@ void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
*/
void sqlite3VtabUnlockList(sqlite3 *db){
VTable *p = db->pDisconnect;
db->pDisconnect = 0;
assert( sqlite3BtreeHoldsAllMutexes(db) );
assert( sqlite3_mutex_held(db->mutex) );
if( p ){
db->pDisconnect = 0;
sqlite3ExpirePreparedStatements(db, 0);
do {
VTable *pNext = p->pNext;
@@ -624,7 +624,7 @@ static int vtabCallConstructor(
rc = SQLITE_ERROR;
}else{
int iCol;
u16 oooHidden = 0;
u8 oooHidden = 0;
/* If everything went according to plan, link the new VTable structure
** into the linked list headed by pTab->pVTable. Then loop through the
** columns of the table to see if any of them contain the token "hidden".
+7 -8
View File
@@ -279,7 +279,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
continue;
}
assert(pX->pLeft);
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
pColl = sqlite3BinaryCompareCollSeq(pParse,
pX->pLeft, pX->pRight);
if( pColl==0 ) pColl = pParse->db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
continue;
@@ -800,8 +801,8 @@ static void constructAutomaticIndex(
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
pIdx->aiColumn[n] = pTerm->u.leftColumn;
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : sqlite3StrBINARY;
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
n++;
}
}
@@ -2801,6 +2802,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr;
if( pTerm->wtFlags & TERM_NOPARTIDX ) continue;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
@@ -3263,7 +3265,7 @@ const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
Expr *pX = pHidden->pWC->a[iTerm].pExpr;
if( pX->pLeft ){
pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
}
zRet = (pC ? pC->zName : sqlite3StrBINARY);
}
@@ -5376,11 +5378,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
x = pPk->aiColumn[x];
assert( x>=0 );
}else{
testcase( x!=sqlite3StorageColumnToTable(pTab,x) );
x = sqlite3StorageColumnToTable(pTab,x);
}
x = sqlite3TableColumnToIndex(pIdx, x);
x = sqlite3ColumnOfIndex(pIdx, x);
if( x>=0 ){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
+1
View File
@@ -291,6 +291,7 @@ struct WhereTerm {
#define TERM_LIKE 0x400 /* The original LIKE operator */
#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
#define TERM_NOPARTIDX 0x2000 /* Not for use to enable a partial index */
/*
** An instance of the WhereScan object is used as an iterator for locating
+14 -57
View File
@@ -823,7 +823,7 @@ static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){
assert( pHint->pIdx!=0 );
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pHint->iTabCur
&& sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn)<0
&& sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0
){
pWalker->eCode = 1;
}
@@ -891,7 +891,7 @@ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
pExpr->iTable = reg;
}else if( pHint->pIdx!=0 ){
pExpr->iTable = pHint->iIdxCur;
pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn);
pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn);
assert( pExpr->iColumn>=0 );
}
}else if( pExpr->op==TK_AGG_FUNCTION ){
@@ -1106,7 +1106,6 @@ typedef struct IdxExprTrans {
int iTabCur; /* The cursor of the corresponding table */
int iIdxCur; /* The cursor for the index */
int iIdxCol; /* The column for the index */
int iTabCol; /* The column for the table */
} IdxExprTrans;
/* The walker node callback used to transform matching expressions into
@@ -1129,31 +1128,10 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
}
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* A walker node callback that translates a column reference to a table
** into a corresponding column reference of an index.
*/
static int whereIndexExprTransColumn(Walker *p, Expr *pExpr){
if( pExpr->op==TK_COLUMN ){
IdxExprTrans *pX = p->u.pIdxTrans;
if( pExpr->iTable==pX->iTabCur && pExpr->iColumn==pX->iTabCol ){
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
pExpr->y.pTab = 0;
}
}
return WRC_Continue;
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
/*
** For an indexes on expression X, locate every instance of expression X
** in pExpr and change that subexpression into a reference to the appropriate
** column of the index.
**
** 2019-10-24: Updated to also translate references to a VIRTUAL column in
** the table into references to the corresponding (stored) column of the
** index.
*/
static void whereIndexExprTrans(
Index *pIdx, /* The Index */
@@ -1163,35 +1141,20 @@ static void whereIndexExprTrans(
){
int iIdxCol; /* Column number of the index */
ExprList *aColExpr; /* Expressions that are indexed */
Table *pTab;
Walker w;
IdxExprTrans x;
aColExpr = pIdx->aColExpr;
if( aColExpr==0 && !pIdx->bHasVCol ){
/* The index does not reference any expressions or virtual columns
** so no translations are needed. */
return;
}
pTab = pIdx->pTable;
if( aColExpr==0 ) return; /* Not an index on expressions */
memset(&w, 0, sizeof(w));
w.xExprCallback = whereIndexExprTransNode;
w.u.pIdxTrans = &x;
x.iTabCur = iTabCur;
x.iIdxCur = iIdxCur;
for(iIdxCol=0; iIdxCol<pIdx->nColumn; iIdxCol++){
i16 iRef = pIdx->aiColumn[iIdxCol];
if( iRef==XN_EXPR ){
assert( aColExpr->a[iIdxCol].pExpr!=0 );
x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
w.xExprCallback = whereIndexExprTransNode;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( iRef>=0 && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0 ){
x.iTabCol = iRef;
w.xExprCallback = whereIndexExprTransColumn;
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
}else{
continue;
}
for(iIdxCol=0; iIdxCol<aColExpr->nExpr; iIdxCol++){
if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue;
assert( aColExpr->a[iIdxCol].pExpr!=0 );
x.iIdxCol = iIdxCol;
x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
sqlite3WalkExpr(&w, pWInfo->pWhere);
sqlite3WalkExprList(&w, pWInfo->pOrderBy);
sqlite3WalkExprList(&w, pWInfo->pResultSet);
@@ -1342,12 +1305,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
iIn = pLevel->u.in.nIn;
for(j=nConstraint-1; j>=0; j--){
pTerm = pLoop->aLTerm[j];
if( (pTerm->eOperator & WO_IN)!=0 ) iIn--;
if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
disableTerm(pLevel, pTerm);
}else if( (pTerm->eOperator & WO_IN)!=0
&& sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1
){
}else if( (pTerm->eOperator & WO_IN)!=0 ){
Expr *pCompare; /* The comparison operator */
Expr *pRight; /* RHS of the comparison */
VdbeOp *pOp; /* Opcode to access the value of the IN constraint */
@@ -1358,8 +1318,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** encoding of the value in the register, so it *must* be reloaded. */
assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
if( !db->mallocFailed ){
assert( iIn>=0 && iIn<pLevel->u.in.nIn );
pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop);
assert( iIn>0 );
pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop);
assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 );
assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 );
@@ -1383,7 +1343,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
}
}
assert( iIn==0 || db->mallocFailed );
/* These registers need to be preserved in case there is an IN operator
** loop. So we could deallocate the registers here (and potentially
** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
@@ -1863,7 +1822,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
}
sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
@@ -1872,9 +1831,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
/* If pIdx is an index on one or more expressions, then look through
** all the expressions in pWInfo and try to transform matching expressions
** into reference to index columns. Also attempt to translate references
** to virtual columns in the table into references to (stored) columns
** of the index.
** into reference to index columns.
**
** Do not do this for the RHS of a LEFT JOIN. This is because the
** expression may be evaluated after OP_NullRow has been executed on
@@ -2125,7 +2082,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
r = sqlite3GetTempRange(pParse, nPk);
for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk];
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk);
}
/* Check if the temp table already contains this key. If so,
+33 -8
View File
@@ -109,14 +109,39 @@ static int allowedOp(int op){
/*
** Commute a comparison operator. Expressions of the form "X op Y"
** are converted into "Y op X".
**
** If left/right precedence rules come into play when determining the
** collating sequence, then COLLATE operators are adjusted to ensure
** that the collating sequence does not change. For example:
** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_Collate flag
** is not commuted.
**
** The return value is extra flags that are added to the WhereTerm object
** after it is commuted. The only extra flag ever added is TERM_NOPARTIDX
** which prevents the term from being used to enable a partial index if
** COLLATE changes have been made.
*/
static u16 exprCommute(Parse *pParse, Expr *pExpr){
if( pExpr->pLeft->op==TK_VECTOR
|| pExpr->pRight->op==TK_VECTOR
|| sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight) !=
sqlite3BinaryCompareCollSeq(pParse, pExpr->pRight, pExpr->pLeft)
){
pExpr->flags ^= EP_Commuted;
u16 expRight = (pExpr->pRight->flags & EP_Collate);
u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
u16 wtFlags = 0;
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
if( expRight==expLeft ){
/* Either X and Y both have COLLATE operator or neither do */
if( expRight ){
/* Both X and Y have COLLATE operators. Make sure X is always
** used by clearing the EP_Collate flag from Y. */
pExpr->pRight->flags &= ~EP_Collate;
wtFlags |= TERM_NOPARTIDX;
}else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
/* Neither X nor Y have COLLATE operators, but X has a non-default
** collating sequence. So add the EP_Collate marker on X to cause
** it to be searched first. */
pExpr->pLeft->flags |= EP_Collate;
wtFlags |= TERM_NOPARTIDX;
}
}
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
if( pExpr->op>=TK_GT ){
@@ -127,7 +152,7 @@ static u16 exprCommute(Parse *pParse, Expr *pExpr){
assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
}
return 0;
return wtFlags;
}
/*
@@ -905,7 +930,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){
){
return 0;
}
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
if( sqlite3IsBinary(pColl) ) return 1;
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
}
-19
View File
@@ -417,23 +417,4 @@ do_execsql_test 8.2 {
SELECT * FROM t0 WHERE c1 = 1;
} {{ } 1}
# 2019-10-09
# ALWAYS() macro fails following OOM
# Problem detected by dbsqlfuzz.
#
do_execsql_test 9.0 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
}
do_faultsim_test 9.1 -faults oom* -body {
execsql {
SELECT * FROM (
SELECT b COLLATE nocase IN (SELECT c FROM t2) FROM t1
);
}
} -test {
faultsim_test_result {0 {}}
}
finish_test
-39
View File
@@ -1071,43 +1071,4 @@ do_catchsql_test 11.1 {
DELETE FROM t3 WHERE x IN (SELECT x FROM t4);
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_test 12.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 12288 pagesize 4096 filename crash-e6d070858a3a85.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........
| 96: 00 00 00 00 0d 00 00 00 02 0f 8f 00 0f bf 0f 8f ................
| 3968: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2e ................
| 3984: 02 06 17 15 11 01 45 69 6e 64 65 78 74 31 63 62 ......Eindext1cb
| 4000: 74 31 03 43 52 45 41 54 45 20 49 4e 44 45 58 20 t1.CREATE INDEX
| 4016: 74 31 63 62 20 4f 4e 20 74 31 28 63 2c 62 29 3f t1cb ON t1(c,b)?
| 4032: 01 06 17 11 11 01 6b 74 61 62 6c 65 74 31 74 31 ......ktablet1t1
| 4048: 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 31 .CREATE TABLE t1
| 4064: 28 61 20 49 4e 54 2c 20 62 20 49 4e 54 2c 20 43 (a INT, b INT, C
| 4080: 20 49 4e 54 20 44 45 46 41 55 4c 54 20 31 36 29 INT DEFAULT 16)
| page 2 offset 4096
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4000: 00 00 00 00 00 00 00 00 07 0b 04 01 01 01 63 63 ..............cc
| 4016: 11 05 0a 04 00 00 01 11 05 09 04 08 08 01 0f 05 ................
| 4032: 08 04 00 00 01 01 56 07 04 01 08 01 07 10 07 06 ......V.........
| 4048: 14 01 01 01 06 08 10 06 05 04 f5 00 01 05 10 07 ................
| 4064: 04 04 01 01 01 04 03 10 06 03 04 01 09 01 03 10 ................
| 4080: 06 02 04 01 00 01 02 10 06 01 04 09 01 01 02 10 ................
| page 3 offset 8192
| 0: 0a 00 00 00 0b 0f b0 00 0f f9 0f f2 0f eb 0f e4 ................
| 16: 0f dd 0f d6 0f 9f 0f c7 0f be 00 00 00 00 00 00 ................
| 4016: 07 04 01 01 01 11 e2 0b 06 04 91 00 01 11 0a 07 ................
| 4032: 04 01 01 01 10 08 06 07 04 01 01 01 10 04 04 06 ................
| 4048: 04 01 01 09 10 02 06 04 01 0a 01 10 00 00 00 00 ................
| end crash-e6d070858a3a85.db
}]} {}
do_catchsql_test 12.1 {
SELECT CAST((SELECT b FROM t1 WHERE 16=c) AS int) FROM t1 WHERE 16=c;
} {1 {database disk image is malformed}}
finish_test
-20
View File
@@ -164,25 +164,5 @@ do_execsql_test 4.4 {
SELECT a, avg(c) FILTER (WHERE b!=1) FROM t1 GROUP BY a ORDER BY 2
} {c 2.0 b 5.0 a 10.0}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 5.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(1, 3);
}
do_execsql_test 5.1 {
SELECT count(*) FILTER (WHERE b>2) FROM (SELECT * FROM t1)
} {1}
do_execsql_test 5.2 {
SELECT count(*) FILTER (WHERE b>2) OVER () FROM (SELECT * FROM t1)
} {1 1}
do_execsql_test 5.3 {
SELECT count(*) FILTER (WHERE b>2) OVER (ORDER BY b) FROM (SELECT * FROM t1)
} {0 1}
finish_test
-56
View File
@@ -226,61 +226,5 @@ do_execsql_test 6.1 {
SELECT rowid FROM t6 WHERE t6 MATCH 'b OR "x a"'
} {50001 50002 50003 50004}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.0 {
CREATE VIRTUAL TABLE vt0 USING fts3(c0);
INSERT INTO vt0 VALUES (x'00');
}
do_execsql_test 7.1 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
# Ticket [8a6fa2bb].
#
reset_db
do_execsql_test 7.0.1 {
CREATE VIRTUAL TABLE vt0 USING fts4(c0, order=DESC);
INSERT INTO vt0(c0) VALUES (0), (0);
}
do_execsql_test 7.0.2 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
reset_db
do_execsql_test 7.1.1 {
CREATE VIRTUAL TABLE vt0 USING fts4(c0, order=ASC);
INSERT INTO vt0(c0) VALUES (0), (0);
}
do_execsql_test 7.1.2 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
do_execsql_test 7.2.1 {
CREATE VIRTUAL TABLE ft USING fts4(c0, c1, order=DESC, prefix=1);
INSERT INTO ft VALUES('a b c d', 'hello world');
INSERT INTO ft VALUES('negative', 'positive');
INSERT INTO ft VALUES('hello world', 'a b c d');
}
do_execsql_test 7.2.2 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
# Ticket [745f1abc].
#
reset_db
do_execsql_test 8.1 {
CREATE VIRTUAL TABLE vt0 USING fts4(c0, prefix=1);
}
do_execsql_test 8.2 {
BEGIN;
INSERT INTO vt0 VALUES (0);
INSERT INTO vt0(vt0) VALUES('optimize');
COMMIT;
}
do_execsql_test 8.3 {
INSERT INTO vt0(vt0) VALUES('integrity-check');
}
finish_test
-15
View File
@@ -326,22 +326,7 @@ foreach mod {fts3 fts4} {
execsql { INSERT INTO t1(t1) VALUES('merge=200,10') }
expr { ([db total_changes] - $x)>1 }
} {0}
}
#-------------------------------------------------------------------------
# Test cases 8.* - ticket [bf1aab89].
#
set testprefix fts4merge
reset_db
do_execsql_test 8.0 {
CREATE VIRTUAL TABLE t1 USING fts4(a, order=DESC);
INSERT INTO t1(a) VALUES (0);
INSERT INTO t1(a) VALUES (0);
UPDATE t1 SET a = NULL;
}
do_execsql_test 8.1 {
INSERT INTO t1(t1) VALUES('merge=1,4');
}
finish_test
BIN
View File
Binary file not shown.
+3 -50
View File
@@ -1,4 +1,4 @@
# 2001-09-15
# 2001 September 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
@@ -11,6 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the INSERT statement.
#
# $Id: insert.test,v 1.31 2007/04/05 11:25:59 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -457,7 +458,7 @@ do_execsql_test insert-14.1 {
SELECT x FROM t14;
} {1}
integrity_check insert-14.2
integrity_check insert-99.0
# 2019-08-12.
#
@@ -474,53 +475,5 @@ do_execsql_test insert-15.1 {
SELECT a, length(b) FROM t1;
} {4 33000}
# 2019-10-16
# ticket https://www.sqlite.org/src/info/a8a4847a2d96f5de
# On a REPLACE INTO, if an AFTER trigger adds back the conflicting
# row, you can end up with the wrong number of rows in an index.
#
db close
sqlite3 db :memory:
do_catchsql_test insert-16.1 {
PRAGMA recursive_triggers = true;
CREATE TABLE t0(c0,c1);
CREATE UNIQUE INDEX i0 ON t0(c0);
INSERT INTO t0(c0,c1) VALUES(123,1);
CREATE TRIGGER tr0 AFTER DELETE ON t0
BEGIN
INSERT INTO t0 VALUES(123,2);
END;
REPLACE INTO t0(c0,c1) VALUES(123,3);
} {1 {UNIQUE constraint failed: t0.c0}}
do_execsql_test insert-16.2 {
SELECT * FROM t0;
} {123 1}
integrity_check insert-16.3
do_catchsql_test insert-16.4 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE INDEX t1b ON t1(b);
INSERT INTO t1 VALUES(1, 'one');
CREATE TRIGGER tr3 AFTER DELETE ON t1 BEGIN
INSERT INTO t1 VALUES(1, 'three');
END;
REPLACE INTO t1 VALUES(1, 'two');
} {1 {UNIQUE constraint failed: t1.a}}
integrity_check insert-16.5
do_catchsql_test insert-16.6 {
PRAGMA foreign_keys = 1;
CREATE TABLE p1(a, b UNIQUE);
CREATE TABLE c1(c, d REFERENCES p1(b) ON DELETE CASCADE);
CREATE TRIGGER tr6 AFTER DELETE ON c1 BEGIN
INSERT INTO p1 VALUES(4, 1);
END;
INSERT INTO p1 VALUES(1, 1);
INSERT INTO c1 VALUES(2, 1);
REPLACE INTO p1 VALUES(3, 1);
} {1 {UNIQUE constraint failed: p1.b}}
integrity_check insert-16.7
finish_test
-52
View File
@@ -884,56 +884,4 @@ do_execsql_test join-17.110 {
WHERE NOT(y='a');
} {1 3 1 3}
#-------------------------------------------------------------------------
reset_db
do_execsql_test join-18.1 {
CREATE TABLE t0(a);
CREATE TABLE t1(b);
CREATE VIEW v0 AS SELECT a FROM t1 LEFT JOIN t0;
INSERT INTO t1 VALUES (1);
} {}
do_execsql_test join-18.2 {
SELECT * FROM v0 WHERE NOT(v0.a IS FALSE);
} {{}}
do_execsql_test join-18.3 {
SELECT * FROM t1 LEFT JOIN t0 WHERE NOT(a IS FALSE);
} {1 {}}
do_execsql_test join-18.4 {
SELECT NOT(v0.a IS FALSE) FROM v0
} {1}
#-------------------------------------------------------------------------
reset_db
do_execsql_test join-19.0 {
CREATE TABLE t1(a);
CREATE TABLE t2(b);
INSERT INTO t1(a) VALUES(0);
CREATE VIEW v0(c) AS SELECT t2.b FROM t1 LEFT JOIN t2;
}
do_execsql_test join-19.1 {
SELECT * FROM v0 WHERE v0.c NOTNULL NOTNULL;
} {{}}
do_execsql_test join-19.2 {
SELECT * FROM t1 LEFT JOIN t2
} {0 {}}
do_execsql_test join-19.3 {
SELECT * FROM t1 LEFT JOIN t2 WHERE (b IS NOT NULL) IS NOT NULL;
} {0 {}}
do_execsql_test join-19.4 {
SELECT (b IS NOT NULL) IS NOT NULL FROM t1 LEFT JOIN t2
} {1}
do_execsql_test join-19.5 {
SELECT * FROM t1 LEFT JOIN t2 WHERE
(b IS NOT NULL AND b IS NOT NULL) IS NOT NULL;
} {0 {}}
finish_test
-30
View File
@@ -347,36 +347,6 @@ foreach {tnum sql flags norm} {
{SELECT x FROM t1 WHERE x IN ([x] IS NOT NULL, NULL, 1, 'a', "b", x'00');}
0x2
{0 {SELECT x FROM t1 WHERE x IN(x IS NOT NULL,?,?,?,b,?);}}
800
{ATTACH "normalize800.db" AS somefile;}
0x2
{0 {ATTACH"normalize800.db"AS somefile;}}
810
{ATTACH DATABASE "normalize810.db" AS somefile;}
0x2
{0 {ATTACH DATABASE"normalize810.db"AS somefile;}}
900
{INSERT INTO t1 (x) VALUES("sl1"), (1), ("sl2"), ('i');}
0x2
{0 {INSERT INTO t1(x)VALUES(?),(?),(?),(?);}}
910
{UPDATE t1 SET x = "sl1" WHERE x IN (1, "sl2", 'i');}
0x2
{0 {UPDATE t1 SET x=?WHERE x IN(?,?,?);}}
920
{UPDATE t1 SET x = "y" WHERE x IN (1, "sl1", 'i');}
0x2
{0 {UPDATE t1 SET x=y WHERE x IN(?,?,?);}}
930
{DELETE FROM t1 WHERE x IN (1, "sl1", 'i');}
0x2
{0 {DELETE FROM t1 WHERE x IN(?,?,?);}}
} {
do_test $tnum {
set code [catch {
-47
View File
@@ -570,51 +570,4 @@ do_execsql_test 22.100 {
SELECT (SELECT 5,6 UNION SELECT 3,4 ORDER BY 1 DESC) IN (SELECT 5,6);
} {1 0 1 0 0 1 0 1}
# 2019-10-21 Ticket b47e3627ecaadbde
#
do_execsql_test 23.100 {
DROP TABLE IF EXISTS t0;
CREATE TABLE t0(aa COLLATE NOCASE, bb);
INSERT INTO t0 VALUES('a', 'A');
SELECT (+bb,1) >= (aa, 1), (aa,1)<=(+bb,1) FROM t0;
SELECT 2 FROM t0 WHERE (+bb,1) >= (aa,1);
SELECT 3 FROM t0 WHERE (aa,1) <= (+bb,1);
} {0 1 3}
do_execsql_test 23.110 {
SELECT (SELECT +bb,1) >= (aa, 1), (aa,1)<=(SELECT +bb,1) FROM t0;
SELECT 2 FROM t0 WHERE (SELECT +bb,1) >= (aa,1);
SELECT 3 FROM t0 WHERE (aa,1) <= (SELECT +bb,1);
} {0 1 3}
# 2019-10-22 Ticket 6ef984af8972c2eb
do_execsql_test 24.100 {
DROP TABLE t0;
CREATE TABLE t0(c0 TEXT PRIMARY KEY);
INSERT INTO t0(c0) VALUES ('');
SELECT (t0.c0, TRUE) > (CAST(0 AS REAL), FALSE) FROM t0;
SELECT 2 FROM t0 WHERE (t0.c0, TRUE) > (CAST('' AS REAL), FALSE);
} {1 2}
# 2019-10-23 Ticket 135c9da7513e5a97
do_execsql_test 25.10 {
DROP TABLE t0;
CREATE TABLE t0(c0 UNIQUE);
INSERT INTO t0(c0) VALUES('a');
SELECT (t0.c0, 0) < ('B' COLLATE NOCASE, 0) FROM t0;
SELECT 2 FROM t0 WHERE (t0.c0, 0) < ('B' COLLATE NOCASE, 0);
} {1 2}
do_execsql_test 25.20 {
SELECT ('B' COLLATE NOCASE, 0)> (t0.c0, 0) FROM t0;
SELECT 2 FROM t0 WHERE ('B' COLLATE NOCASE, 0)> (t0.c0, 0);
} {1 2}
do_execsql_test 25.30 {
SELECT ('B', 0)> (t0.c0 COLLATE nocase, 0) FROM t0;
SELECT 2 FROM t0 WHERE ('B', 0)> (t0.c0 COLLATE nocase, 0);
} {1 2}
do_execsql_test 25.40 {
SELECT (t0.c0 COLLATE nocase, 0) < ('B', 0) FROM t0;
SELECT 2 FROM t0 WHERE (t0.c0 COLLATE nocase, 0) < ('B', 0);
} {1 2}
finish_test
-91
View File
@@ -1,91 +0,0 @@
# 2018 October 14
#
# 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 rowvaluevtab
register_echo_module db
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c);
CREATE INDEX t1b ON t1(b);
INSERT INTO t1 VALUES('one', 1, 1);
INSERT INTO t1 VALUES('two', 1, 2);
INSERT INTO t1 VALUES('three', 1, 3);
INSERT INTO t1 VALUES('four', 2, 1);
INSERT INTO t1 VALUES('five', 2, 2);
INSERT INTO t1 VALUES('six', 2, 3);
INSERT INTO t1 VALUES('seven', 3, 1);
INSERT INTO t1 VALUES('eight', 3, 2);
INSERT INTO t1 VALUES('nine', 3, 3);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
) INSERT INTO t1 SELECT NULL, NULL, NULL FROM s;
CREATE VIRTUAL TABLE e1 USING echo(t1);
}
proc do_vfilter4_test {tn sql expected} {
set res [list]
db eval "explain $sql" {
if {$opcode=="VFilter"} {
lappend res $p4
}
}
uplevel [list do_test $tn [list set {} $res] [list {*}$expected]]
}
do_execsql_test 1.1 {
SELECT a FROM e1 WHERE (b, c) = (2, 2)
} {five}
do_vfilter4_test 1.1f {
SELECT a FROM e1 WHERE (b, c) = (?, ?)
} {{SELECT rowid, a, b, c FROM 't1' WHERE b = ?}}
do_execsql_test 1.2 {
SELECT a FROM e1 WHERE (b, c) > (2, 2)
} {six seven eight nine}
do_vfilter4_test 1.2f {
SELECT a FROM e1 WHERE (b, c) > (2, 2)
} {
{SELECT rowid, a, b, c FROM 't1' WHERE b >= ?}
}
do_execsql_test 1.3 {
SELECT a FROM e1 WHERE (b, c) >= (2, 2)
} {five six seven eight nine}
do_vfilter4_test 1.3f {
SELECT a FROM e1 WHERE (b, c) >= (2, 2)
} {
{SELECT rowid, a, b, c FROM 't1' WHERE b >= ?}
}
do_execsql_test 1.3 {
SELECT a FROM e1 WHERE (b, c) BETWEEN (1, 2) AND (2, 3)
} {two three four five six}
do_vfilter4_test 1.3f {
SELECT a FROM e1 WHERE (b, c) BETWEEN (1, 2) AND (2, 3)
} {
{SELECT rowid, a, b, c FROM 't1' WHERE b >= ? AND b <= ?}
}
do_execsql_test 1.4 {
SELECT a FROM e1 WHERE (b, c) IN ( VALUES(2, 2) )
} {five}
do_vfilter4_test 1.4f {
SELECT a FROM e1 WHERE (b, c) IN ( VALUES(2, 2) )
} {{SELECT rowid, a, b, c FROM 't1' WHERE b = ?}}
finish_test
-16
View File
@@ -782,20 +782,4 @@ do_execsql_test trigger1-20.1 {
DROP TRIGGER r20_3;
} {}
# 2019-10-24 ticket 50c09fc2cf0d91ce
#
db close
sqlite3 db :memory:
do_execsql_test trigger1-21.1 {
PRAGMA recursive_triggers = true;
CREATE TABLE t0(a, b, c UNIQUE);
CREATE UNIQUE INDEX i0 ON t0(b) WHERE a;
CREATE TRIGGER tr0 AFTER DELETE ON t0 BEGIN
DELETE FROM t0;
END;
INSERT INTO t0(a,b,c) VALUES(0,0,9),(1,1,1);
REPLACE INTO t0(a,b,c) VALUES(2,0,9);
SELECT * FROM t0;
} {2 0 9}
finish_test
-44
View File
@@ -1190,48 +1190,4 @@ do_execsql_test 30.0 {
win3 AS (win2 RANGE BETWEEN 5.2 PRECEDING AND true PRECEDING );
} {1 1}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 31.1 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE TABLE t3(e, f);
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t2 VALUES(1, 1);
INSERT INTO t3 VALUES(1, 1);
}
do_execsql_test 31.2 {
SELECT d IN (SELECT sum(c) OVER (ORDER BY e+c) FROM t3) FROM (
SELECT * FROM t2
);
} {1}
do_execsql_test 31.3 {
SELECT d IN (SELECT sum(c) OVER (PARTITION BY d ORDER BY e+c) FROM t3) FROM (
SELECT * FROM t2
);
} {1}
do_catchsql_test 31.3 {
SELECT d IN (
SELECT sum(c) OVER ( ROWS BETWEEN d FOLLOWING AND UNBOUNDED FOLLOWING)
FROM t3
)
FROM (
SELECT * FROM t2
);
} {1 {frame starting offset must be a non-negative integer}}
do_catchsql_test 31.3 {
SELECT d IN (
SELECT sum(c) OVER ( ROWS BETWEEN CURRENT ROW AND c FOLLOWING)
FROM t3
)
FROM (
SELECT * FROM t2
);
} {1 {frame ending offset must be a non-negative integer}}
finish_test
+1 -1
View File
@@ -1068,6 +1068,6 @@ int ParseFallback(int iToken){
return yyFallback[iToken];
#else
(void)iToken;
return 0;
#endif
return 0;
}
-2
View File
@@ -164,7 +164,6 @@ static Keyword aKeywordTable[] = {
{ "AFTER", "TK_AFTER", TRIGGER },
{ "ALL", "TK_ALL", ALWAYS },
{ "ALTER", "TK_ALTER", ALTER },
{ "ALWAYS", "TK_ALWAYS", ALWAYS },
{ "ANALYZE", "TK_ANALYZE", ANALYZE },
{ "AND", "TK_AND", ALWAYS },
{ "AS", "TK_AS", ALWAYS },
@@ -217,7 +216,6 @@ static Keyword aKeywordTable[] = {
{ "FOREIGN", "TK_FOREIGN", FKEY },
{ "FROM", "TK_FROM", ALWAYS },
{ "FULL", "TK_JOIN_KW", ALWAYS },
{ "GENERATED", "TK_GENERATED", ALWAYS },
{ "GLOB", "TK_LIKE_KW", ALWAYS },
{ "GROUP", "TK_GROUP", ALWAYS },
{ "GROUPS", "TK_GROUPS", WINDOWFUNC },