Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 31aa6145b7 | |||
| 731dd6ebda | |||
| 04c6747a80 | |||
| b7de827137 | |||
| cfc45b1021 | |||
| f8c2fea195 | |||
| e89feee5c3 | |||
| 8c53b4e7f6 | |||
| de72d2a81a | |||
| 4a5cff73a7 | |||
| fdc75c9f53 | |||
| 04ab586bf3 | |||
| 4f939e86df | |||
| 1ba88c7f1d | |||
| f7c44f9bd2 | |||
| 4d2f81eb73 | |||
| 3a85a298c9 | |||
| 909f78cbd8 | |||
| 26505e5f51 | |||
| 49f6a0d82a | |||
| 1af016b7f4 | |||
| f6e015fab9 | |||
| f6fa95b81d | |||
| 63e50b9ed6 | |||
| fcee090746 | |||
| 746a1515b2 | |||
| 60ce5d3135 | |||
| b8a762827c | |||
| bcdef69482 | |||
| eea8eb6d04 | |||
| 49b269e095 | |||
| 52f0c6205c | |||
| eafb9a0ae5 | |||
| 48ea97e5dd | |||
| 09236755ee | |||
| 8055a3ead4 | |||
| 3c425484a7 |
+17
-3
@@ -32,6 +32,7 @@ CC = @CC@
|
||||
CFLAGS = @CPPFLAGS@ @CFLAGS@
|
||||
TCC = ${CC} ${CFLAGS} -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/icu
|
||||
TCC += -I${TOP}/ext/fts3 -I${TOP}/ext/async -I${TOP}/ext/session
|
||||
TCC += -I${TOP}/ext/userauth
|
||||
|
||||
# Define this for the autoconf-based build, so that the code knows it can
|
||||
# include the generated config.h
|
||||
@@ -187,7 +188,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
||||
random.lo resolve.lo rowset.lo rtree.lo \
|
||||
sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
|
||||
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
|
||||
update.lo upsert.lo util.lo vacuum.lo \
|
||||
update.lo userauth.lo upsert.lo util.lo vacuum.lo \
|
||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
|
||||
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
|
||||
window.lo utf.lo vtab.lo
|
||||
@@ -355,6 +356,9 @@ SRC += \
|
||||
SRC += \
|
||||
$(TOP)/ext/session/sqlite3session.c \
|
||||
$(TOP)/ext/session/sqlite3session.h
|
||||
SRC += \
|
||||
$(TOP)/ext/userauth/userauth.c \
|
||||
$(TOP)/ext/userauth/sqlite3userauth.h
|
||||
SRC += \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.h \
|
||||
$(TOP)/ext/rbu/sqlite3rbu.c
|
||||
@@ -455,7 +459,8 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/totype.c \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
$(TOP)/ext/misc/zipfile.c
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/userauth/userauth.c
|
||||
|
||||
# Source code to the library files needed by the test fixture
|
||||
#
|
||||
@@ -471,6 +476,7 @@ TESTSRC2 = \
|
||||
$(TOP)/src/dbstat.c \
|
||||
$(TOP)/src/expr.c \
|
||||
$(TOP)/src/func.c \
|
||||
$(TOP)/src/global.c \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/wal.c \
|
||||
$(TOP)/src/main.c \
|
||||
@@ -560,6 +566,8 @@ EXTHDR += \
|
||||
$(TOP)/ext/icu/sqliteicu.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/rtree/sqlite3rtree.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/userauth/sqlite3userauth.h
|
||||
|
||||
# executables needed for testing
|
||||
#
|
||||
@@ -1117,7 +1125,10 @@ fts3_write.lo: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
|
||||
rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
|
||||
|
||||
sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
||||
sqlite3session.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
|
||||
|
||||
userauth.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
|
||||
|
||||
json1.lo: $(TOP)/ext/misc/json1.c
|
||||
@@ -1295,6 +1306,9 @@ showwal$(TEXE): $(TOP)/tool/showwal.c sqlite3.lo
|
||||
showshm$(TEXE): $(TOP)/tool/showshm.c
|
||||
$(LTLINK) -o $@ $(TOP)/tool/showshm.c
|
||||
|
||||
index_usage$(TEXE): $(TOP)/tool/index_usage.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/tool/index_usage.c sqlite3.lo $(TLIBS)
|
||||
|
||||
changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
|
||||
|
||||
|
||||
@@ -345,6 +345,7 @@ 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
|
||||
!ENDIF
|
||||
@@ -2443,6 +2444,10 @@ showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
|
||||
showshm.exe: $(TOP)\tool\showshm.c
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
index_usage.exe: $(TOP)\tool\index_usage.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
$(TOP)\tool\index_usage.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
|
||||
|
||||
@@ -283,6 +283,7 @@ 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
|
||||
!ENDIF
|
||||
@@ -937,6 +938,7 @@ LIBRESOBJS =
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
!ENDIF
|
||||
|
||||
|
||||
|
||||
@@ -777,6 +777,9 @@ For example:</p>
|
||||
<p>This might be needed, for example, if some of the C actions in the
|
||||
grammar call functions that are prototyped in unistd.h.</p>
|
||||
|
||||
<p>Use the <tt><a href="#pcode">%code</a></tt> directive to add code to
|
||||
the end of the generated parser.</p>
|
||||
|
||||
<a name='pleft'></a>
|
||||
<h4>The <tt>%left</tt> directive</h4>
|
||||
|
||||
|
||||
@@ -4166,6 +4166,7 @@ static int fts3EvalPhraseLoad(
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
|
||||
/*
|
||||
** This function is called on each phrase after the position lists for
|
||||
** any deferred tokens have been loaded into memory. It updates the phrases
|
||||
@@ -4269,6 +4270,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_DISABLE_FTS4_DEFERRED */
|
||||
|
||||
/*
|
||||
** Maximum number of tokens a phrase may have to be considered for the
|
||||
|
||||
@@ -82,7 +82,7 @@ typedef struct unicode_cursor unicode_cursor;
|
||||
|
||||
struct unicode_tokenizer {
|
||||
sqlite3_tokenizer base;
|
||||
int bRemoveDiacritic;
|
||||
int eRemoveDiacritic;
|
||||
int nException;
|
||||
int *aiException;
|
||||
};
|
||||
@@ -227,17 +227,20 @@ static int unicodeCreate(
|
||||
pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
|
||||
if( pNew==NULL ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(unicode_tokenizer));
|
||||
pNew->bRemoveDiacritic = 1;
|
||||
pNew->eRemoveDiacritic = 1;
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i++){
|
||||
const char *z = azArg[i];
|
||||
int n = (int)strlen(z);
|
||||
|
||||
if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
|
||||
pNew->bRemoveDiacritic = 1;
|
||||
pNew->eRemoveDiacritic = 1;
|
||||
}
|
||||
else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
|
||||
pNew->bRemoveDiacritic = 0;
|
||||
pNew->eRemoveDiacritic = 0;
|
||||
}
|
||||
else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){
|
||||
pNew->eRemoveDiacritic = 2;
|
||||
}
|
||||
else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
|
||||
rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
|
||||
@@ -350,7 +353,7 @@ static int unicodeNext(
|
||||
|
||||
/* Write the folded case of the last character read to the output */
|
||||
zEnd = z;
|
||||
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
|
||||
iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic);
|
||||
if( iOut ){
|
||||
WRITE_UTF8(zOut, iOut);
|
||||
}
|
||||
|
||||
+40
-22
@@ -159,32 +159,47 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
||||
** E"). The resuls of passing a codepoint that corresponds to an
|
||||
** uppercase letter are undefined.
|
||||
*/
|
||||
static int remove_diacritic(int c){
|
||||
static int remove_diacritic(int c, int bComplex){
|
||||
unsigned short aDia[] = {
|
||||
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
|
||||
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
|
||||
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
|
||||
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
|
||||
3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
|
||||
3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
|
||||
4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
|
||||
6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
|
||||
61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
|
||||
61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
|
||||
62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
|
||||
62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
|
||||
62924, 63050, 63082, 63274, 63390,
|
||||
3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
|
||||
3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
|
||||
4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
|
||||
4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
|
||||
6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
|
||||
61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
|
||||
61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
|
||||
61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
|
||||
62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
|
||||
62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
|
||||
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
|
||||
63182, 63242, 63274, 63310, 63368, 63390,
|
||||
};
|
||||
char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
|
||||
'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
|
||||
'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
|
||||
'e', 'i', 'o', 'u', 'y',
|
||||
'\0', 'a'|0x00, 'c'|0x00, 'e'|0x00, 'i'|0x00, 'n'|0x00,
|
||||
'o'|0x00, 'u'|0x00, 'y'|0x00, 'y'|0x00, 'a'|0x00, 'c'|0x00,
|
||||
'd'|0x00, 'e'|0x00, 'e'|0x00, 'g'|0x00, 'h'|0x00, 'i'|0x00,
|
||||
'j'|0x00, 'k'|0x00, 'l'|0x00, 'n'|0x00, 'o'|0x00, 'r'|0x00,
|
||||
's'|0x00, 't'|0x00, 'u'|0x00, 'u'|0x00, 'w'|0x00, 'y'|0x00,
|
||||
'z'|0x00, 'o'|0x00, 'u'|0x00, 'a'|0x00, 'i'|0x00, 'o'|0x00,
|
||||
'u'|0x00, 'u'|0x80, 'a'|0x80, 'g'|0x00, 'k'|0x00, 'o'|0x00,
|
||||
'o'|0x80, 'j'|0x00, 'g'|0x00, 'n'|0x00, 'a'|0x80, 'a'|0x00,
|
||||
'e'|0x00, 'i'|0x00, 'o'|0x00, 'r'|0x00, 'u'|0x00, 's'|0x00,
|
||||
't'|0x00, 'h'|0x00, 'a'|0x00, 'e'|0x00, 'o'|0x80, 'o'|0x00,
|
||||
'o'|0x80, 'y'|0x00, '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a'|0x00, 'b'|0x00,
|
||||
'c'|0x80, 'd'|0x00, 'd'|0x00, 'e'|0x80, 'e'|0x00, 'e'|0x80,
|
||||
'f'|0x00, 'g'|0x00, 'h'|0x00, 'h'|0x00, 'i'|0x00, 'i'|0x80,
|
||||
'k'|0x00, 'l'|0x00, 'l'|0x80, 'l'|0x00, 'm'|0x00, 'n'|0x00,
|
||||
'o'|0x80, 'p'|0x00, 'r'|0x00, 'r'|0x80, 'r'|0x00, 's'|0x00,
|
||||
's'|0x80, 't'|0x00, 'u'|0x00, 'u'|0x80, 'v'|0x00, 'w'|0x00,
|
||||
'w'|0x00, 'x'|0x00, 'y'|0x00, 'z'|0x00, 'h'|0x00, 't'|0x00,
|
||||
'w'|0x00, 'y'|0x00, 'a'|0x00, 'a'|0x80, 'a'|0x80, 'a'|0x80,
|
||||
'e'|0x00, 'e'|0x80, 'e'|0x80, 'i'|0x00, 'o'|0x00, 'o'|0x80,
|
||||
'o'|0x80, 'o'|0x80, 'u'|0x00, 'u'|0x80, 'u'|0x80, 'y'|0x00,
|
||||
};
|
||||
|
||||
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
|
||||
@@ -201,7 +216,8 @@ static int remove_diacritic(int c){
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
|
||||
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
|
||||
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +244,7 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
|
||||
** The results are undefined if the value passed to this function
|
||||
** is less than zero.
|
||||
*/
|
||||
int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
|
||||
/* Each entry in the following array defines a rule for folding a range
|
||||
** of codepoints to lower case. The rule applies to a range of nRange
|
||||
** codepoints starting at codepoint iCode.
|
||||
@@ -351,7 +367,9 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
assert( ret>0 );
|
||||
}
|
||||
|
||||
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
||||
if( eRemoveDiacritic ){
|
||||
ret = remove_diacritic(ret, eRemoveDiacritic==2);
|
||||
}
|
||||
}
|
||||
|
||||
else if( c>=66560 && c<66600 ){
|
||||
|
||||
@@ -9,11 +9,12 @@ proc print_rd {map} {
|
||||
set nRange 1
|
||||
set iFirst [lindex $map 0 0]
|
||||
set cPrev [lindex $map 0 1]
|
||||
set fPrev [lindex $map 0 2]
|
||||
|
||||
foreach m [lrange $map 1 end] {
|
||||
foreach {i c} $m {}
|
||||
foreach {i c f} $m {}
|
||||
|
||||
if {$cPrev == $c} {
|
||||
if {$cPrev == $c && $fPrev==$f} {
|
||||
for {set j [expr $iFirst+$nRange]} {$j<$i} {incr j} {
|
||||
if {[info exists tl_lookup_table($j)]==0} break
|
||||
}
|
||||
@@ -29,13 +30,16 @@ proc print_rd {map} {
|
||||
|
||||
lappend lRange [list $iFirst $nRange]
|
||||
lappend aChar $cPrev
|
||||
lappend aFlag $fPrev
|
||||
|
||||
set iFirst $i
|
||||
set cPrev $c
|
||||
set fPrev $f
|
||||
set nRange 1
|
||||
}
|
||||
lappend lRange [list $iFirst $nRange]
|
||||
lappend aChar $cPrev
|
||||
lappend aFlag $fPrev
|
||||
|
||||
puts "/*"
|
||||
puts "** If the argument is a codepoint corresponding to a lowercase letter"
|
||||
@@ -45,7 +49,7 @@ proc print_rd {map} {
|
||||
puts "** E\"). The resuls of passing a codepoint that corresponds to an"
|
||||
puts "** uppercase letter are undefined."
|
||||
puts "*/"
|
||||
puts "static int ${::remove_diacritic}(int c)\{"
|
||||
puts "static int ${::remove_diacritic}(int c, int bComplex)\{"
|
||||
puts " unsigned short aDia\[\] = \{"
|
||||
puts -nonewline " 0, "
|
||||
set i 1
|
||||
@@ -60,13 +64,17 @@ proc print_rd {map} {
|
||||
puts ""
|
||||
puts " \};"
|
||||
puts " char aChar\[\] = \{"
|
||||
puts -nonewline " '\\0', "
|
||||
puts -nonewline " '\\0', "
|
||||
set i 1
|
||||
foreach c $aChar {
|
||||
set str "'$c', "
|
||||
if {$c == ""} { set str "'\\0', " }
|
||||
foreach c $aChar f $aFlag {
|
||||
if { $f } {
|
||||
set str "'$c'|0x80, "
|
||||
} else {
|
||||
set str "'$c'|0x00, "
|
||||
}
|
||||
if {$c == ""} { set str "'\\0', " }
|
||||
|
||||
if {($i % 12)==0} {puts "" ; puts -nonewline " " }
|
||||
if {($i % 6)==0} {puts "" ; puts -nonewline " " }
|
||||
incr i
|
||||
puts -nonewline "$str"
|
||||
}
|
||||
@@ -87,7 +95,8 @@ proc print_rd {map} {
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);}
|
||||
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
|
||||
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);}
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
@@ -95,7 +104,8 @@ proc print_isdiacritic {zFunc map} {
|
||||
|
||||
set lCode [list]
|
||||
foreach m $map {
|
||||
foreach {code char} $m {}
|
||||
foreach {code char flag} $m {}
|
||||
if {$flag} continue
|
||||
if {$code && $char == ""} { lappend lCode $code }
|
||||
}
|
||||
set lCode [lsort -integer $lCode]
|
||||
@@ -472,7 +482,7 @@ proc print_fold {zFunc} {
|
||||
puts "** The results are undefined if the value passed to this function"
|
||||
puts "** is less than zero."
|
||||
puts "*/"
|
||||
puts "int ${zFunc}\(int c, int bRemoveDiacritic)\{"
|
||||
puts "int ${zFunc}\(int c, int eRemoveDiacritic)\{"
|
||||
|
||||
set liOff [tl_generate_ioff_table $lRecord]
|
||||
tl_print_table_header
|
||||
@@ -516,7 +526,9 @@ proc print_fold {zFunc} {
|
||||
assert( ret>0 );
|
||||
}
|
||||
|
||||
if( bRemoveDiacritic ) ret = ${::remove_diacritic}(ret);
|
||||
if( eRemoveDiacritic ){
|
||||
ret = ${::remove_diacritic}(ret, eRemoveDiacritic==2);
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -605,10 +617,6 @@ proc print_categories {lMap} {
|
||||
|
||||
set nCat [expr [llength [array names C]] + 1]
|
||||
puts [code {
|
||||
int sqlite3Fts5UnicodeNCat(void) {
|
||||
return $nCat;
|
||||
}
|
||||
|
||||
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
|
||||
aArray[0] = 1;
|
||||
switch( zCat[0] ){
|
||||
|
||||
@@ -7,12 +7,24 @@
|
||||
# character that it should be replaced with, or an empty string if the
|
||||
# codepoint should simply be removed from the input. Examples:
|
||||
#
|
||||
# { 224 a } (replace codepoint 224 to "a")
|
||||
# { 769 "" } (remove codepoint 769 from input)
|
||||
# { 224 a 0 } (replace codepoint 224 to "a")
|
||||
# { 769 "" 0 } (remove codepoint 769 from input)
|
||||
#
|
||||
# Mappings are only returned for non-upper case codepoints. It is assumed
|
||||
# that the input has already been folded to lower case.
|
||||
#
|
||||
# The third value in the list is always either 0 or 1. 0 if the
|
||||
# UnicodeData.txt file maps the codepoint to a single ASCII character and
|
||||
# a diacritic, or 1 if the mapping is indirect. For example, consider the
|
||||
# two entries:
|
||||
#
|
||||
# 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC
|
||||
# 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8
|
||||
#
|
||||
# The first codepoint is a direct mapping (as 006F is ASCII and 0323 is a
|
||||
# diacritic). The second is an indirect mapping, as it maps to the
|
||||
# first codepoint plus 0302 (a diacritic).
|
||||
#
|
||||
proc rd_load_unicodedata_text {zName} {
|
||||
global tl_lookup_table
|
||||
|
||||
@@ -53,18 +65,29 @@ proc rd_load_unicodedata_text {zName} {
|
||||
set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"]
|
||||
set iDia [expr "0x[lindex $character_decomposition_mapping 1]"]
|
||||
|
||||
# Filter out upper-case characters, as they will be mapped to their
|
||||
# lower-case equivalents before this data is used.
|
||||
if {[info exists tl_lookup_table($iCode)]} continue
|
||||
|
||||
# Check if this is an indirect mapping. If so, set bIndirect to true
|
||||
# and change $iAscii to the indirectly mappped ASCII character.
|
||||
set bIndirect 0
|
||||
if {[info exists dia($iDia)] && [info exists mapping($iAscii)]} {
|
||||
set iAscii $mapping($iAscii)
|
||||
set bIndirect 1
|
||||
}
|
||||
|
||||
if { ($iAscii >= 97 && $iAscii <= 122)
|
||||
|| ($iAscii >= 65 && $iAscii <= 90)
|
||||
} {
|
||||
lappend lRet [list $iCode [string tolower [format %c $iAscii]]]
|
||||
lappend lRet [list $iCode [string tolower [format %c $iAscii]] $bIndirect]
|
||||
set mapping($iCode) $iAscii
|
||||
set dia($iDia) 1
|
||||
}
|
||||
}
|
||||
|
||||
foreach d [array names dia] {
|
||||
lappend lRet [list $d ""]
|
||||
lappend lRet [list $d "" 0]
|
||||
}
|
||||
set lRet [lsort -integer -index 0 $lRet]
|
||||
|
||||
|
||||
@@ -234,13 +234,18 @@ struct Unicode61Tokenizer {
|
||||
unsigned char aTokenChar[128]; /* ASCII range token characters */
|
||||
char *aFold; /* Buffer to fold text into */
|
||||
int nFold; /* Size of aFold[] in bytes */
|
||||
int bRemoveDiacritic; /* True if remove_diacritics=1 is set */
|
||||
int eRemoveDiacritic; /* True if remove_diacritics=1 is set */
|
||||
int nException;
|
||||
int *aiException;
|
||||
|
||||
unsigned char aCategory[32]; /* True for token char categories */
|
||||
};
|
||||
|
||||
/* Values for eRemoveDiacritic (must match internals of fts5_unicode2.c) */
|
||||
#define FTS5_REMOVE_DIACRITICS_NONE 0
|
||||
#define FTS5_REMOVE_DIACRITICS_SIMPLE 1
|
||||
#define FTS5_REMOVE_DIACRITICS_COMPLEX 2
|
||||
|
||||
static int fts5UnicodeAddExceptions(
|
||||
Unicode61Tokenizer *p, /* Tokenizer object */
|
||||
const char *z, /* Characters to treat as exceptions */
|
||||
@@ -361,7 +366,7 @@ static int fts5UnicodeCreate(
|
||||
int i;
|
||||
memset(p, 0, sizeof(Unicode61Tokenizer));
|
||||
|
||||
p->bRemoveDiacritic = 1;
|
||||
p->eRemoveDiacritic = FTS5_REMOVE_DIACRITICS_SIMPLE;
|
||||
p->nFold = 64;
|
||||
p->aFold = sqlite3_malloc(p->nFold * sizeof(char));
|
||||
if( p->aFold==0 ){
|
||||
@@ -382,10 +387,15 @@ static int fts5UnicodeCreate(
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
p->eRemoveDiacritic = (zArg[0] - '0');
|
||||
assert( p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_NONE
|
||||
|| p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_SIMPLE
|
||||
|| p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_COMPLEX
|
||||
);
|
||||
}
|
||||
p->bRemoveDiacritic = (zArg[0]=='1');
|
||||
}else
|
||||
if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
|
||||
rc = fts5UnicodeAddExceptions(p, zArg, 1);
|
||||
@@ -499,7 +509,7 @@ static int fts5UnicodeTokenize(
|
||||
READ_UTF8(zCsr, zTerm, iCode);
|
||||
if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){
|
||||
non_ascii_tokenchar:
|
||||
iCode = sqlite3Fts5UnicodeFold(iCode, p->bRemoveDiacritic);
|
||||
iCode = sqlite3Fts5UnicodeFold(iCode, p->eRemoveDiacritic);
|
||||
if( iCode ) WRITE_UTF8(zOut, iCode);
|
||||
}else{
|
||||
break;
|
||||
|
||||
+41
-31
@@ -28,32 +28,47 @@
|
||||
** E"). The resuls of passing a codepoint that corresponds to an
|
||||
** uppercase letter are undefined.
|
||||
*/
|
||||
static int fts5_remove_diacritic(int c){
|
||||
static int fts5_remove_diacritic(int c, int bComplex){
|
||||
unsigned short aDia[] = {
|
||||
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
|
||||
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
|
||||
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
|
||||
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
|
||||
3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
|
||||
3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
|
||||
4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
|
||||
6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
|
||||
61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
|
||||
61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
|
||||
62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
|
||||
62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
|
||||
62924, 63050, 63082, 63274, 63390,
|
||||
3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
|
||||
3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
|
||||
4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
|
||||
4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
|
||||
6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
|
||||
61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
|
||||
61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
|
||||
61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
|
||||
62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
|
||||
62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
|
||||
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
|
||||
63182, 63242, 63274, 63310, 63368, 63390,
|
||||
};
|
||||
char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
|
||||
'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
|
||||
'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
|
||||
'e', 'i', 'o', 'u', 'y',
|
||||
'\0', 'a'|0x00, 'c'|0x00, 'e'|0x00, 'i'|0x00, 'n'|0x00,
|
||||
'o'|0x00, 'u'|0x00, 'y'|0x00, 'y'|0x00, 'a'|0x00, 'c'|0x00,
|
||||
'd'|0x00, 'e'|0x00, 'e'|0x00, 'g'|0x00, 'h'|0x00, 'i'|0x00,
|
||||
'j'|0x00, 'k'|0x00, 'l'|0x00, 'n'|0x00, 'o'|0x00, 'r'|0x00,
|
||||
's'|0x00, 't'|0x00, 'u'|0x00, 'u'|0x00, 'w'|0x00, 'y'|0x00,
|
||||
'z'|0x00, 'o'|0x00, 'u'|0x00, 'a'|0x00, 'i'|0x00, 'o'|0x00,
|
||||
'u'|0x00, 'u'|0x80, 'a'|0x80, 'g'|0x00, 'k'|0x00, 'o'|0x00,
|
||||
'o'|0x80, 'j'|0x00, 'g'|0x00, 'n'|0x00, 'a'|0x80, 'a'|0x00,
|
||||
'e'|0x00, 'i'|0x00, 'o'|0x00, 'r'|0x00, 'u'|0x00, 's'|0x00,
|
||||
't'|0x00, 'h'|0x00, 'a'|0x00, 'e'|0x00, 'o'|0x80, 'o'|0x00,
|
||||
'o'|0x80, 'y'|0x00, '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a'|0x00, 'b'|0x00,
|
||||
'c'|0x80, 'd'|0x00, 'd'|0x00, 'e'|0x80, 'e'|0x00, 'e'|0x80,
|
||||
'f'|0x00, 'g'|0x00, 'h'|0x00, 'h'|0x00, 'i'|0x00, 'i'|0x80,
|
||||
'k'|0x00, 'l'|0x00, 'l'|0x80, 'l'|0x00, 'm'|0x00, 'n'|0x00,
|
||||
'o'|0x80, 'p'|0x00, 'r'|0x00, 'r'|0x80, 'r'|0x00, 's'|0x00,
|
||||
's'|0x80, 't'|0x00, 'u'|0x00, 'u'|0x80, 'v'|0x00, 'w'|0x00,
|
||||
'w'|0x00, 'x'|0x00, 'y'|0x00, 'z'|0x00, 'h'|0x00, 't'|0x00,
|
||||
'w'|0x00, 'y'|0x00, 'a'|0x00, 'a'|0x80, 'a'|0x80, 'a'|0x80,
|
||||
'e'|0x00, 'e'|0x80, 'e'|0x80, 'i'|0x00, 'o'|0x00, 'o'|0x80,
|
||||
'o'|0x80, 'o'|0x80, 'u'|0x00, 'u'|0x80, 'u'|0x80, 'y'|0x00,
|
||||
};
|
||||
|
||||
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
|
||||
@@ -70,7 +85,8 @@ static int fts5_remove_diacritic(int c){
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
|
||||
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
|
||||
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +113,7 @@ int sqlite3Fts5UnicodeIsdiacritic(int c){
|
||||
** The results are undefined if the value passed to this function
|
||||
** is less than zero.
|
||||
*/
|
||||
int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
|
||||
int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){
|
||||
/* Each entry in the following array defines a rule for folding a range
|
||||
** of codepoints to lower case. The rule applies to a range of nRange
|
||||
** codepoints starting at codepoint iCode.
|
||||
@@ -220,7 +236,9 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
|
||||
assert( ret>0 );
|
||||
}
|
||||
|
||||
if( bRemoveDiacritic ) ret = fts5_remove_diacritic(ret);
|
||||
if( eRemoveDiacritic ){
|
||||
ret = fts5_remove_diacritic(ret, eRemoveDiacritic==2);
|
||||
}
|
||||
}
|
||||
|
||||
else if( c>=66560 && c<66600 ){
|
||||
@@ -230,13 +248,6 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int sqlite3Fts5UnicodeNCat(void) {
|
||||
return 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
|
||||
aArray[0] = 1;
|
||||
switch( zCat[0] ){
|
||||
@@ -756,9 +767,8 @@ void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
|
||||
int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
|
||||
int n = (aFts5UnicodeData[iTbl] >> 5) + i;
|
||||
for(; i<128 && i<n; i++){
|
||||
aAscii[i] = (u8)bToken;
|
||||
aAscii[i] = bToken;
|
||||
}
|
||||
iTbl++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ do_catchsql_test 6.2 {
|
||||
} {1 {error in tokenizer constructor}}
|
||||
do_catchsql_test 6.3 {
|
||||
CREATE VIRTUAL TABLE a3 USING fts5(
|
||||
x, y, tokenize = 'unicode61 remove_diacritics 2'
|
||||
x, y, tokenize = 'unicode61 remove_diacritics 3'
|
||||
);
|
||||
} {1 {error in tokenizer constructor}}
|
||||
do_catchsql_test 6.4 {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# 2014 June 17
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5umlaut
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(
|
||||
x,
|
||||
tokenize="unicode61 remove_diacritics 2"
|
||||
);
|
||||
}
|
||||
|
||||
foreach {tn q res1 res2} {
|
||||
1 "Hà Nội" 0 1
|
||||
2 "Hà Noi" 1 1
|
||||
3 "Ha Noi" 1 1
|
||||
4 "Ha N\u1ed9i" 0 1
|
||||
5 "Ha N\u006fi" 1 1
|
||||
6 "Ha N\u006f\u0302i" 1 1
|
||||
7 "Ha N\u006f\u0323\u0302i" 1 1
|
||||
} {
|
||||
do_execsql_test 1.$tn.1 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(rowid, x) VALUES (1, 'Ha Noi');
|
||||
SELECT count(*) FROM t1($q)
|
||||
} $res1
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(rowid, x) VALUES (1, $q);
|
||||
SELECT count(*) FROM t1('Ha Noi')
|
||||
} $res1
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2(rowid, x) VALUES (1, 'Ha Noi');
|
||||
SELECT count(*) FROM t2($q)
|
||||
} $res2
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2(rowid, x) VALUES (1, $q);
|
||||
SELECT count(*) FROM t2('Ha Noi')
|
||||
} $res2
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -36,24 +36,26 @@ foreach x [an_load_unicodedata_text $UD] {
|
||||
}
|
||||
|
||||
foreach {y} [rd_load_unicodedata_text $UD] {
|
||||
foreach {code ascii} $y {}
|
||||
foreach {code ascii f} $y {}
|
||||
if {$ascii==""} {
|
||||
set int 0
|
||||
} else {
|
||||
binary scan $ascii c int
|
||||
}
|
||||
set aDiacritic($code) $int
|
||||
set aDiacritic($code,$f) $int
|
||||
if {$f==0} { set aDiacritic($code,1) $int }
|
||||
}
|
||||
|
||||
proc tcl_fold {i {bRemoveDiacritic 0}} {
|
||||
global tl_lookup_table
|
||||
global aDiacritic
|
||||
set f [expr $bRemoveDiacritic==2]
|
||||
|
||||
if {[info exists tl_lookup_table($i)]} {
|
||||
set i $tl_lookup_table($i)
|
||||
}
|
||||
if {$bRemoveDiacritic && [info exists aDiacritic($i)]} {
|
||||
set i $aDiacritic($i)
|
||||
if {$bRemoveDiacritic && [info exists aDiacritic($i,$f)]} {
|
||||
set i $aDiacritic($i,$f)
|
||||
}
|
||||
expr $i
|
||||
}
|
||||
@@ -85,7 +87,7 @@ do_execsql_test 1.1 {
|
||||
SELECT count(*), min(i) FROM ii WHERE fts5_fold(i)!=CAST(tcl_fold(i) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
do_execsql_test 1.2.1 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
UNION ALL
|
||||
@@ -95,6 +97,16 @@ do_execsql_test 1.2 {
|
||||
WHERE fts5_fold(i,1)!=CAST(tcl_fold(i,1) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.2.2 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
UNION ALL
|
||||
SELECT i+1 FROM ii WHERE i<100000
|
||||
)
|
||||
SELECT count(*), min(i) FROM ii
|
||||
WHERE fts5_fold(i,2)!=CAST(tcl_fold(i,2) AS int);
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
WITH ii(i) AS (
|
||||
SELECT -1
|
||||
|
||||
+6
-6
@@ -527,7 +527,7 @@ static void geopolyCcwFunc(
|
||||
if( p ){
|
||||
if( geopolyArea(p)<0.0 ){
|
||||
int ii, jj;
|
||||
for(ii=2, jj=p->nVertex*2 - 4; ii<jj; ii+=2, jj-=2){
|
||||
for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){
|
||||
GeoCoord t = p->a[ii];
|
||||
p->a[ii] = p->a[jj];
|
||||
p->a[jj] = t;
|
||||
@@ -544,15 +544,15 @@ static void geopolyCcwFunc(
|
||||
|
||||
#define GEOPOLY_PI 3.1415926535897932385
|
||||
|
||||
/* Fast approximation for cosine(X) for X between -0.5*pi and 2*pi
|
||||
/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi
|
||||
*/
|
||||
static double geopolyCosine(double r){
|
||||
static double geopolySine(double r){
|
||||
assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI );
|
||||
if( r>=1.5*GEOPOLY_PI ){
|
||||
r -= 2.0*GEOPOLY_PI;
|
||||
}
|
||||
if( r>=0.5*GEOPOLY_PI ){
|
||||
return -geopolyCosine(r-GEOPOLY_PI);
|
||||
return -geopolySine(r-GEOPOLY_PI);
|
||||
}else{
|
||||
double r2 = r*r;
|
||||
double r3 = r2*r;
|
||||
@@ -593,8 +593,8 @@ static void geopolyRegularFunc(
|
||||
p->hdr[3] = n&0xff;
|
||||
for(i=0; i<n; i++){
|
||||
double rAngle = 2.0*GEOPOLY_PI*i/n;
|
||||
p->a[i*2] = x - r*geopolyCosine(rAngle-0.5*GEOPOLY_PI);
|
||||
p->a[i*2+1] = y + r*geopolyCosine(rAngle);
|
||||
p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
|
||||
p->a[i*2+1] = y + r*geopolySine(rAngle);
|
||||
}
|
||||
sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
|
||||
sqlite3_free(p);
|
||||
|
||||
@@ -96,7 +96,7 @@ struct sqlite3_rtree_query_info {
|
||||
sqlite3_int64 iRowid; /* Rowid for current entry */
|
||||
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
|
||||
int eParentWithin; /* Visibility of parent node */
|
||||
int eWithin; /* OUT: Visiblity */
|
||||
int eWithin; /* OUT: Visibility */
|
||||
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
|
||||
/* The following fields are only available in 3.8.11 and later */
|
||||
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
|
||||
|
||||
@@ -396,6 +396,7 @@ TESTSRC2 = \
|
||||
$(TOP)/src/dbstat.c \
|
||||
$(TOP)/src/expr.c \
|
||||
$(TOP)/src/func.c \
|
||||
$(TOP)/src/global.c \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/wal.c \
|
||||
$(TOP)/src/main.c \
|
||||
@@ -994,6 +995,10 @@ showwal$(EXE): $(TOP)/tool/showwal.c sqlite3.o
|
||||
showshm$(EXE): $(TOP)/tool/showshm.c
|
||||
$(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c
|
||||
|
||||
index_usage$(EXE): $(TOP)/tool/index_usage.c sqlite3.o
|
||||
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_DEPRECATED -o index_usage$(EXE) \
|
||||
$(TOP)/tool/index_usage.c sqlite3.o $(THREADLIB)
|
||||
|
||||
changeset$(EXE): $(TOP)/ext/session/changeset.c sqlite3.o
|
||||
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \
|
||||
$(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
C Consolidate\sthe\stwo\ssqlite3SchemaToIndex()\sroutines.
|
||||
D 2018-11-20T16:02:52.908
|
||||
C When\scompiled\swith\sSQLITE_ENABLE_NORMALIZE,\salways\shave\ssqlite3_exec()\senable\sthe\sSQLITE_PREPARE_NORMALIZE\sflag.
|
||||
D 2018-12-04T21:16:34.044
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in b730006b54c990461d864c5387f2e6f13aadb0236804555fb010ed6865a5f058
|
||||
F Makefile.in 68d0ba0f0b533d5bc84c78c13a6ce84ee81183a67014caa47a969e67f028fa1c
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 071853dfc2148aadaeb7a153b9986cc9d71b7f256874f79b119f97a4c89453f5
|
||||
F Makefile.msc b7d4a710fa3f0b8cfc532ff195b85dc1ba2a8ad34343cb3d67639f28f0a24306
|
||||
F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee
|
||||
F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -14,7 +14,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am e14b629addaa1ce372b72043f28f40de2e32b7e211b6e0fc18dbb87989197e40
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.msc 9e73d9abaadb7a4951ddd0e947c5c791770f23bb1e04bfa50b43c01bee0575f2
|
||||
F autoconf/Makefile.msc ee8ab2b6b5d712f68acc4c186e3fad7b831b87a2b118e0a123043ea8a2c8b016
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192
|
||||
@@ -37,7 +37,7 @@ F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x
|
||||
F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
F doc/lemon.html ac63db056bce24b7368e29319cd1a7eb5f1798cc85922d96a80b6c3a4ff9f51b
|
||||
F doc/lemon.html 24956ab2995e55fe171e55bdd04f22b553957dc8bb43501dbb9311e30187e0d3
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
@@ -80,7 +80,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c eddaba472f7ceee0240252e21875547bd137d4383fcd9e6c99b9e59078356171
|
||||
F ext/fts3/fts3.c 65b8489e35da23b127992c6dd6cfd382a486f8c87bf26dfa72876efe46e551bb
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5
|
||||
F ext/fts3/fts3_aux.c e9b465f8469acc2cd700a90c0242912a3202e4e4e15df72d7db7f1e3a2222c85
|
||||
@@ -96,8 +96,8 @@ F ext/fts3/fts3_tokenize_vtab.c a47c2a33de6db00816704315ac0a9afdfa1c71fa5b99f791
|
||||
F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c 525a3bd9a7564603c5c061b7de55403a565307758a94600e8a2f6b00d1c40d9d
|
||||
F ext/fts3/fts3_unicode2.c cc04fc672bfd42b1e650398cb0bf71f64f9aae032cfe75bbcfe75b9cf966029c
|
||||
F ext/fts3/fts3_unicode.c b1902e9ad47a6569fbb8ecb5ce52f20fe59b590d5c5e3bbdd56b10b03bdf632b
|
||||
F ext/fts3/fts3_unicode2.c 90e65f4291c8ecceee284ecc8d5d48734e95ecd4b008e06f36f14e77f93d655f
|
||||
F ext/fts3/fts3_write.c a85bc4885fde7f1b44c9de013b62f7cd3332dc59e208053d878729b1d04745bc
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
@@ -105,8 +105,8 @@ F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87
|
||||
F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 0069320b64db6ee269c5e95f1f150d070fbf0a863fc7b3549d7e52bd068fb118
|
||||
F ext/fts3/unicode/parseunicode.tcl 024ae0bdd96309d7b8fc479148191e9b3001dc74017a3f65f9a27de3b3ff968b
|
||||
F ext/fts3/unicode/mkunicode.tcl 2ea30d8122ccf1e33142c9cc8913d8cad9eb6668db359a228f10aeb37e2ab863
|
||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||
F ext/fts5/fts5.h 5edc74ca603d71284d475886e6e91b5c5cf2e8e93e9ba3a36ba2f2440ee97948
|
||||
F ext/fts5/fts5Int.h 39f12034b598df4e0f59bbe6cf03af03a905a534b04f182d155641a04e1eb797
|
||||
@@ -121,8 +121,8 @@ F ext/fts5/fts5_storage.c 4bec8a1b3905978b22a67bca5f4a3cfdb94af234cf51efb36f4f2d
|
||||
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
|
||||
F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
|
||||
F ext/fts5/fts5_test_tok.c 80de1a4b1a3caa216c3be8862440f0117a8357dd9b7cfc5a2a2ce11fe6eb64ae
|
||||
F ext/fts5/fts5_tokenize.c ebd13d034f3dc7c841e1c32c364a4fca5cc2e05a0b91682a93fa1e6defcd4292
|
||||
F ext/fts5/fts5_unicode2.c 543cf0987c27ad59e5a7a6222480b917b5431009b7b139027c9581a63e39e37e
|
||||
F ext/fts5/fts5_tokenize.c ca2b6a033794945ac505241a86b0aa978709c23aa2e6121984d3e3ede96003c8
|
||||
F ext/fts5/fts5_unicode2.c 26519f47d567c5a9b08c376edd38f1b8a773b45ff29f1ffd81d9edfe20f96e18
|
||||
F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
|
||||
F ext/fts5/fts5_vocab.c fbe38044889b2d2d99babeeef239c620fb0332bb928a84506ac748d81500b354
|
||||
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
|
||||
@@ -206,10 +206,11 @@ F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074
|
||||
F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947ec60b6fadbc4b3fb17a
|
||||
F ext/fts5/test/fts5tok1.test ce6551e41ff56f30b69963577324624733bed0d1753589f06120d664d9cd45c9
|
||||
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
|
||||
F ext/fts5/test/fts5tokenizer.test 6aeb5e8061ffc0ff9a5299f27beaee3b2b4b8b336d4f107262bca338bea8f8e9
|
||||
F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
|
||||
F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
|
||||
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
|
||||
F ext/fts5/test/fts5unicode2.test 9b3df486de05fb4bde4aa7ee8de2e6dae1df6eb90e3f2e242c9383b95d314e3e
|
||||
F ext/fts5/test/fts5unicode3.test c3caecbe8264629ffe653b43ca5790b9793eba4422f92203e5247558e5a534e7
|
||||
F ext/fts5/test/fts5unicode3.test 9cbc82e2b02e2e3b7504103580c90f095e07fe8230b1951a9ed7558717b5feb7
|
||||
F ext/fts5/test/fts5unicode4.test 6463301d669f963c83988017aa354108be0b947d325aef58d3abddf27147b687
|
||||
F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d
|
||||
F ext/fts5/test/fts5update.test 0737876e20e97a6a6abf45de19fc99315727bcee6a83fadcada1cc080b9aa8f0
|
||||
@@ -361,7 +362,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
|
||||
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/geopoly.c 38ad90cab8dbd3dfba246d642f47366e40418e47fa55fe89f1078483d51b52c0
|
||||
F ext/rtree/geopoly.c d56ff997f2646b03be742eb85e8206f779d777f3a282fe0da576780ca0e11f20
|
||||
F ext/rtree/rtree.c 7125183bf6c37b8b8ee1a04d2b0fe258531fd31650fdd050ed041817f1943d17
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
|
||||
@@ -385,7 +386,7 @@ F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
|
||||
F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35
|
||||
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
|
||||
F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
|
||||
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
|
||||
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
||||
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
@@ -428,7 +429,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk ddb6616776c53dfc06bb3f8396df8721c8b699294271fd0c3d110dd278d9c723
|
||||
F main.mk 55f94164ecc194b067d9c55e106f37fd3c9b39f9668e8b568c98f008b6f9ec90
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -440,37 +441,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c f4ba663ee11eaf3a17c0b21a8e377a9e8991627b0afe994fcce8f44faf566669
|
||||
F src/analyze.c 09c9684253a328735c63f714e1c50360e977b4020b7b1325d11dd46f2f192123
|
||||
F src/alter.c f886160da189e4e99093cd5a2aca625652cc9b027d5100b87f81c175d1056387
|
||||
F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
|
||||
F src/attach.c 92b51739a885da8bd84bc9a05485f1e48148bce5c15432f059b45af98fff75cd
|
||||
F src/auth.c 6ea0bfef8f2d972358f40c349a7ae431649adb3ca2aac73dc2f3b4e8fb4c33b8
|
||||
F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
|
||||
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 786ad5319e5a889711043db3136c8b7f58bcdd53327410dd2330d02be1eab69d
|
||||
F src/btree.c 3ef104ecae8b1b5f0458be1f5fa7c1ecf25fdc322a9d63bb8151f89eb32d381e
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c ba7c7eef4461790f37c309936bfc5d0d6ba9b194b02d3c8ff1fd53b420ea6d3b
|
||||
F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
|
||||
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
|
||||
F src/build.c d31ac32f9fe0e35f3953bd4f287c8d025ad89af6a78697e054ea8d59f07a4577
|
||||
F src/callback.c e5031c28f6e8eb2f290298e262eb1eb5f201ef2ae25db54b396882ae2059e944
|
||||
F src/build.c fce47a9789704e65c63299b01be8153745faee7919f5137d3f29b7c3c0b549bd
|
||||
F src/callback.c 789bd33d188146f66c0dd8306472a72d1c05f71924b24a91caf6bd45cf9aba73
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
|
||||
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
|
||||
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
|
||||
F src/dbstat.c 3c8bd4e77f0244fd2bd7cc90acf116ad2f8e82d70e536637f35ac2bc99b726f9
|
||||
F src/delete.c 65e16dc1cf64eab1b6761aefbacefc4b983d2f9ed7265f050b88689a271c1741
|
||||
F src/expr.c 38c50318213e42b579189a7438a53c19833486ecbe97da9bfac3bd39242a0c56
|
||||
F src/delete.c f7938125847e8ef485448db5fbad29acb2991381a02887dd854c1617315ab9fb
|
||||
F src/expr.c 9aacc0b72348ba90010b672dcbbbe2fa56e1182043bc917a3a147b2bc57a5497
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 2c112c00667b3c4668023a000489261d5b72441c67f969b526a1af831d297d96
|
||||
F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
|
||||
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
|
||||
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
|
||||
F src/global.c 8291eee0782b83124de14ec0389ec9fd6ae1873358a6b0d9469fe17a46ad803b
|
||||
F src/hash.c 931ec82d7e070654a8facb42549bbb3a25720171d73ba94c3d3160580d01ef1f
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 037e39bd36cef876e376663e3c1fb74b19267b0f13036c304fbb2b01c4aaff05
|
||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||
F src/loadext.c 448eab53ecdb566a1259ee2d45ebff9c0bc4a2cf393774488775c33e4fbe89bf
|
||||
F src/main.c 63ec9559c244c7e10eafc0efe0f66387fc40b8683ba20aeb0422e334f4eb0a52
|
||||
F src/insert.c f12f27eb606d601825be9a229a7390a8d64d40226697883f96de8e088d620055
|
||||
F src/legacy.c f2965b726364fee8ed57fb1a363b85cfe9f418b261cf41b0790339b33e905477
|
||||
F src/loadext.c 9050dd153b5583804184be9c9dee9ebb554178d6db1f8ac280899e8aad9060e6
|
||||
F src/main.c 5a94791735ddd51804b75b7ef4645c25cbe6fe1d0e8f25851b2ed1211ad3d076
|
||||
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@@ -491,32 +492,32 @@ F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c f6e91b8fd82af7afbfd073c4974ad6cdb8e62d9f65ceddb45167835a0567fdc0
|
||||
F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
|
||||
F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c f803ffcd8440b5249549ea103158a1c659bf060961b2389f9fede66a3a352d0b
|
||||
F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963
|
||||
F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179
|
||||
F src/pcache.c 4196eb6ed3bbf00b80596c8e0b4f50e57eb7d890c19fb27a7354306abb7f983d
|
||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||
F src/pragma.c f9b6a7f8136a1df3830d3e91e526a43c75a2b1db24795813871fbc86dd683db7
|
||||
F src/pager.c 75e0f3cfa3962c714f519f8a3d1e67ecca1c91de0e010a036b988e40ce9e4c73
|
||||
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
|
||||
F src/parse.y 5cf85c2b9dfac38ac4e2bf2776484705186ce2eda8631e65cc0b04bf566c1173
|
||||
F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
|
||||
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c ad0ffc5b35b0280d045ac569d34d4b842e3e6a4a118f6396b320987a0957afcc
|
||||
F src/pragma.c 4e056f042683b99c4ea0db395f68d051b1a95833ab40951c40d3ef7e1fee1354
|
||||
F src/pragma.h fdd03d78a7497f74a3f652909f945328480089189526841ae829ce7313d98d13
|
||||
F src/prepare.c fc8c448c4df0c23d5087e8069a2e03598ed1be9a567c9bc70f49b829e76b61ad
|
||||
F src/prepare.c f81f8d707e583192c28fea0b2e19385415b7d188123b23f49b038076408d7a69
|
||||
F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 23c3d8c311b71da12b57be43b27e84a97b500dabda4eabb74d2bbc750a5ab7c1
|
||||
F src/resolve.c 976e7879286a1eecdc71ceff64f6d1b3f58c8f8096537ba668b3dc0887f410c1
|
||||
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
|
||||
F src/select.c 88f6aab4f5f0d1c13fef55d07ff6dcfb8d44aec8b65ca8e7038ef3f889f9e324
|
||||
F src/shell.c.in 91ccfc85bcd28015c5db01449275e7fba3e9f97aa2533b53b73e81906eebaac0
|
||||
F src/sqlite.h.in 3baffc1c299e0c10dc63f31ce4b322d14548dae6ac73b0719ba505b37966bac3
|
||||
F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f
|
||||
F src/shell.c.in 482e23a370cbe5b0d4c73a0f0f5fce34f7caa08a14a8d75e12f0225c4e14915c
|
||||
F src/sqlite.h.in cce9feede1c1c03923c091b4bbbd081dd77aaf92024cc2cdbf65f712c2f668c3
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
|
||||
F src/sqliteInt.h a499dea6afe4123faf1ef1461b9b23738b6578009a648bbab0fab1e7c2e696ad
|
||||
F src/sqliteInt.h f54ee1ef1e0f99d27af20561df72aac9158ed420cfc3a2e330fdee40672daf37
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c b651e68af3cb859e4083c79e0e7177e2aeb35ed23e3892d7bbe5b732d38bf2b9
|
||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c b15e46bdc1b14e994a358d51ce0bf8b7d7d4615cda96634ca0498ee39bc83b9c
|
||||
F src/test1.c b95363b0bc9e1ecc61964ca5a22c137422af4808a54a7bbb1a4f7d6d6257f704
|
||||
F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6
|
||||
F src/test1.c 5390e5afb31fed61f72d0be0cb1b322d198a6e03fc13ff245ae76d17b4dcf2e9
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||
@@ -571,30 +572,30 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 9e781e1ca80eefe7b5d6a9e2cd5c678c847da55fd6f093781fad7950934d4c83
|
||||
F src/treeview.c 7b12ac059de54c939b6eb0dbffc9410c29c80d2470cee5cbe07d5ff9ea2d9253
|
||||
F src/trigger.c e143e102daa1791d990a447ef4bfb0fb5f6a502bebf98fee7f868e66f6664c38
|
||||
F src/update.c 792c3c1ccef5794a63a9b2cb0fc183b9357dd64b3614c7aa1460dd3becd177c5
|
||||
F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
|
||||
F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274
|
||||
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
||||
F src/vacuum.c 87907c331ea9acdd887504869a91449d90df6a7debbabb9e52e6e71aa42178ff
|
||||
F src/vdbe.c 103913320325dc5848449a8f9a8470b1b67d74dc47d67ade1c7d6024b50517a5
|
||||
F src/vdbe.h fda06d544a79e684797e7d433e5c410e563f8d3897098826e4c23cdb3be4193e
|
||||
F src/vdbeInt.h edfb25fc654f9d6d31ba47b161326f984f897e4b6e49cb8e9ee8708215023e0b
|
||||
F src/vdbeapi.c ecccfce6f614c33a95952efeec969d163e8349eac314ee2b7b163eda921b5eb0
|
||||
F src/vdbeaux.c 5e83d8a9e6513d14f17810c70a87d4876bf9f2b55eb78bec8571fe37a37ade1a
|
||||
F src/vdbeblob.c bef4668e92c33b47933aa24ffa9a982617f59a5330d927fd5d33ab42bc3e01c6
|
||||
F src/vacuum.c 836cadc922de866c849e23a75f93d344cdc143d388339305d09a3fed27e8798d
|
||||
F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b
|
||||
F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
|
||||
F src/vdbeInt.h 437e6c6af679fdf157867eb83a8adc6cf5145d6774453c2214cfd0bd01d92980
|
||||
F src/vdbeapi.c dc825a6ec99a5066c1aa0d9824509057c0510f03cc8c72f81ba074553f8a5ae8
|
||||
F src/vdbeaux.c f547901b1aa9e2d81c63f06893f633648e434180666a827aacb547d7d6c8a601
|
||||
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
|
||||
F src/vdbemem.c 7b3305bc4a5139f4536ac9b5f61da0f915e49d2e3fdfa87dfdfa9d7aba8bc1e9
|
||||
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
|
||||
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
|
||||
F src/vtab.c 9b380532e2e9fa5c559e2f59b702c4e87b32a6146a9e273e299315547fbd705c
|
||||
F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
|
||||
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
|
||||
F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
|
||||
F src/where.c fded04f3d811ced6281f7d24cc2d03d9fc4d5ce403d616cfef7dbcccbdbaf4c3
|
||||
F src/where.c 3818e8a736a05d2cb194e64399af707e367fbcc5c251d785804d02eaf121288e
|
||||
F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
|
||||
F src/wherecode.c c45f03aefc2266b990df0fc4d7acc4e27f56f881f4fc0fc355b7cbc4d7189da5
|
||||
F src/whereexpr.c 833b58f9d34fa8118bf671b695a9929028707e13bf7e16e932d80c9c64d5f0a3
|
||||
F src/whereexpr.c 491f0894ad9903750cdecb7894437a0cabdffdd88f574d2b1c9ac85d14fe4b9c
|
||||
F src/window.c 6550e2850ebced51100ef83d49b00a1cf03f81a482dafedafb0320df647ed8fc
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
@@ -603,17 +604,17 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
|
||||
F test/alter.test 99e72759d48d6531ac2a9f346b4a9b5fe8f89c67a0fa5e916a3990d3b1fe9d09
|
||||
F test/alter.test 93dee7c0ff9106fbd53a8bbf519107904b884050a99c4565412c58c37d68c802
|
||||
F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687
|
||||
F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
|
||||
F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433
|
||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||
F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499
|
||||
F test/altercol.test 50095d59d07a178a2a6330ec2440b2f1a0b59918364c32d29b8a692f29a97a1a
|
||||
F test/altercol.test 313ed080ed61691c52cd87053129889f71582d6d0efebdd5f3edad2a98c66874
|
||||
F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
|
||||
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
|
||||
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
|
||||
F test/altertab.test ebb159e81589919852b2c3af8efbc25e6568bd758892fdc49cdaf1d73d26072f
|
||||
F test/altertab.test 17e46baa6b2234048c91891a303141afceca4da95a36ee1a0a9fec6ccef1f4da
|
||||
F test/altertab2.test 0d64de5632ca5de13b023839cfe5b8952d029e4622befcea1433adaa93883220
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 7168c8bffa5d5cbc53c05b7e9c7fcdd24b365a1bc5046ce80c45efa3c02e6b7c
|
||||
@@ -640,7 +641,7 @@ F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd
|
||||
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
|
||||
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
|
||||
F test/atrc.c ec92d56d8fbed9eb3e11aaf1ab98cf7dd59e69dae31f128013f1d97e54e7dfed
|
||||
F test/attach.test fb03859ee33e23588b8c73102374de7231987760a986fe3a912e75563931c9f8
|
||||
F test/attach.test 21bce8681f780a8d631a5ec7ecd0d849bfe84611257b038ae4ffeccc609d8a4e
|
||||
F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
|
||||
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
|
||||
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
|
||||
@@ -834,7 +835,7 @@ F test/fallocate.test 07416bd593a116d5893cb244f45a94d5c6fe030561df3bd972e6135f81
|
||||
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
|
||||
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
|
||||
F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768
|
||||
F test/fkey2.test 6206484a0eba570902a1a4d86489df24d0265f6994daebf851861d8f0cf4a27b
|
||||
F test/fkey2.test d35d1c81e7569bdd2b872e91750f7098117d2e8291369f70b7e3d50a0e523dc2
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a
|
||||
@@ -956,6 +957,7 @@ F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
|
||||
F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
|
||||
F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a
|
||||
F test/fts4umlaut.test 1d28e2a2dffa794e15babadebdece091431b09d740be79c08eb6aba1173a8c84
|
||||
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test 09dda479bcfc568f99f3070413e9672a8eeedc1be9c5d819bf55d4788c2583b7
|
||||
@@ -970,7 +972,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c 8074a35ed4ec3735a5e144b7e0e9123d9821a92281756c1a40d43e302dd79243
|
||||
F test/fuzzcheck.c fda41c0e4e667fae96b002410bb19cece7a33314264ed6bbc6d012909ee9fd58
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -1004,7 +1006,7 @@ F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
|
||||
F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9
|
||||
F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758
|
||||
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
|
||||
F test/incrvacuum.test b729aab1d4983037da57e66c20dfd7458561a85626dcf824f60175e35f4ce152
|
||||
F test/incrvacuum.test 2aaee202b1f230e55779f70d155f6ba67bbdff8481d650214d256ab0f97d4a2b
|
||||
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
|
||||
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
|
||||
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
|
||||
@@ -1019,7 +1021,7 @@ F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
|
||||
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
|
||||
F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
|
||||
F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
|
||||
F test/indexexpr2.test d8f56b6cf4e5663486129bc18c6bde4cef9f8876942b001bfdd692a2b1a42668
|
||||
F test/indexexpr2.test fc994dcd4b3da932d4add8e65ed7ca08166d541e00a46874cfacd98dfb93a31b
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a
|
||||
@@ -1053,7 +1055,7 @@ F test/journal3.test c9c29883f5bf535ae82ae21c472df6263806a22e467b6db7cd0d6d54530
|
||||
F test/jrnlmode.test a6693f2bed4541a21e703aaa37bb3e10de154130645952933b82b2dec0a8b539
|
||||
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test b40a9f5395d8e669b0bc3eb550ad2ae9e5ada01fbce23c446c2a30a305a6d575
|
||||
F test/json101.test 8f8977b00ba02f9a26c1d1f52f29f540f6d5eb162cbd5eb78bb805366d4ab26d
|
||||
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
|
||||
F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b
|
||||
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
|
||||
@@ -1061,6 +1063,7 @@ F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c 94da54bb66aae7a54e47cf7e4ea4acecc0f217560f79ad3abfcc0361d6d557ba
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
|
||||
F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/like3.test 430691e6057e11a59e934be74c06b85605b80061d45af5714d52886a811efeb7
|
||||
@@ -1162,7 +1165,7 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
|
||||
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
|
||||
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
|
||||
F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace
|
||||
F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03
|
||||
F test/ossfuzz.c 273eaea2d65b70d77ea4f01404114b9e0244488943f768dc39458c72bd722e0e
|
||||
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
|
||||
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
|
||||
F test/pager1.test 1e9ee778bdeaf4f7f09997d029cdaca6a42dfc2092edafe4f5e590acbf1eab13
|
||||
@@ -1183,7 +1186,7 @@ F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb0696
|
||||
F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9
|
||||
F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c
|
||||
F test/pragma4.test 52d8186f9e8d09b87189432cdd401dfa66d0b32445e837fa19046c8ae7621b0e
|
||||
F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd
|
||||
@@ -1204,10 +1207,9 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl c5b474f9880073fc3b69729ee05d5284653a9ee101af572204917d9dcb1d9015 x
|
||||
F test/releasetest.tcl b290d538ffcb2ff711f09eadc7396c1a42580f3fb078605471dc8875ca0b4d1e x
|
||||
F test/resetdb.test 373a9eb8fcbd58bf87affec6a88c6353038f98a5d25be5ab75a0b9636c462a36
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/reuse1.test 85c107d2c45a99e148f639d28e7b839b9981a5aa6856c4ec969072ce5b64eaf4
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
|
||||
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
|
||||
@@ -1343,13 +1345,13 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
|
||||
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
|
||||
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test 54300134f76db817685194d2f0e63e3fbf7380b45e0d426e00a9aee752497cfb
|
||||
F test/tabfunc01.test 20e98ffe55f35d8d33fd834ca8bf9d4b637e560af8fcd00464b4154d90a4db45
|
||||
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
|
||||
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 049da602775bebfadfa2fae0710e1099a38ef2fc9f76c7546be3ba8fdbb02263
|
||||
F test/tclsqlite.test dca8aa30d84175e7d8c8fc43d3ffa11fa56e23fbdac2679d03833a0f326edf34
|
||||
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
|
||||
F test/tempdb2.test 4749545409c6d7438b435c3f05cdd139cf4145a954a6908d19e3443ffd8724b3
|
||||
F test/tempdb2.test 2479226e4cb96f4c663eccd2d12c077cf6bda29ca5cc69a8a58a06127105dd62
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
|
||||
@@ -1588,7 +1590,7 @@ F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be4
|
||||
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
|
||||
F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f
|
||||
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
|
||||
F test/vtab_err.test 1c476cac24c9c730f83cd7c8bf66482a30151be08d36a2283f87fc38a2dacbb1
|
||||
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
|
||||
F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918
|
||||
@@ -1670,7 +1672,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982
|
||||
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
|
||||
F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
F test/without_rowid3.test e1bb85362d9b7b63ea2b93c433bb2923fff8badb98e463474365531c1cd5f880
|
||||
F test/without_rowid3.test ea4b59dd1b0d7f5f5e4b7cca978cdb905752a9d7c57dc4344a591dba765a3691
|
||||
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
||||
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
|
||||
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
|
||||
@@ -1697,9 +1699,10 @@ F tool/fuzzershell.c e1d90a03ca790d7c331c2aae08ca46ff435f1ae1faa6cb9cc48f4687c18
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c 8fd515b97522ae4b1aa6ca9847439f005d4cbaf6eb0eb416b694dba77c0263f0
|
||||
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
||||
F tool/lemon.c 60d1e1eb0f7ebae709f68f1472d77fbf291c5345cd98ff417219da7e74fd09e9
|
||||
F tool/lempar.c 6020ce61dd7a536a3866952eb1e616c7e8b14b8f623368ed5a98f0639cedf048
|
||||
F tool/lemon.c c9ba01f6729c892ae3e0f55c8a2d694a7e6ec3dd3aa280b411a008ef69b410cd
|
||||
F tool/lempar.c 61af95b8fac2bfd59c09d55330e78f3f5e352d7aa80bf37404b96ef795be3fdc
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
|
||||
@@ -1779,7 +1782,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 84be9220db4adaf4873cf38d7259a321900608d63be4d08603e74f8b7ae120ac
|
||||
R 6da38ba0540b642f9b1cc73aec9a5fb5
|
||||
U dan
|
||||
Z 47b1db7061e0aabc455eabfcd73eae34
|
||||
P df95455213c9d1db7229e94217e78edc05cbf9e40f39528105494ea6ac52be94
|
||||
R 73d39f6c8ad10375d91c1bf80b5506d5
|
||||
T *branch * execWithNormalize
|
||||
T *sym-execWithNormalize *
|
||||
T -sym-trunk *
|
||||
U mistachkin
|
||||
Z 74e4003db4dff8d15e39466a0b866842
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
dfab7170edf23de33013ea2af2f512ee978a689a6d218f6f490d46e48b9213b3
|
||||
28643d837d057879b3067a18bb4c628d10ffc8c69b8f1870154566cb0b09cba5
|
||||
+53
-58
@@ -74,8 +74,8 @@ static void renameReloadSchema(Parse *pParse, int iDb){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
if( v ){
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb, 0);
|
||||
if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse, 1, 0);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0);
|
||||
if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ void sqlite3AlterRenameTable(
|
||||
|
||||
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
|
||||
if( !pTab ) goto exit_rename_table;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
db->mDbFlags |= DBFLAG_PreferBuiltin;
|
||||
|
||||
@@ -148,11 +148,11 @@ void sqlite3AlterRenameTable(
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){
|
||||
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
|
||||
goto exit_rename_table;
|
||||
}
|
||||
if( IsVirtual(pTab) ){
|
||||
pVTab = sqlite3GetVTable(db, -1, pTab);
|
||||
pVTab = sqlite3GetVTable(db, pTab);
|
||||
if( pVTab->pVtab->pModule->xRename==0 ){
|
||||
pVTab = 0;
|
||||
}
|
||||
@@ -276,7 +276,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
||||
assert( pNew );
|
||||
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
iDb = sqlite3SchemaToIndex(db, pNew->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
|
||||
pCol = &pNew->aCol[pNew->nCol-1];
|
||||
@@ -429,7 +429,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
||||
}
|
||||
|
||||
assert( pTab->addColOffset>0 );
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
|
||||
/* Put a copy of the Table struct in Parse.pNewTable for the
|
||||
** sqlite3AddColumn() function and friends to modify. But modify
|
||||
@@ -530,7 +530,7 @@ void sqlite3AlterRenameColumn(
|
||||
if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
|
||||
|
||||
/* Which schema holds the table to be altered */
|
||||
iSchema = sqlite3SchemaToIndex(db, pTab->pSchema, 0);
|
||||
iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iSchema>=0 );
|
||||
zDb = db->aDb[iSchema].zDbSName;
|
||||
|
||||
@@ -667,10 +667,16 @@ static void renameTokenCheckAll(Parse *pParse, void *pPtr){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Add a new RenameToken object mapping parse tree element pPtr into
|
||||
** token *pToken to the Parse object currently under construction.
|
||||
** Remember that the parser tree element pPtr was created using
|
||||
** the token pToken.
|
||||
**
|
||||
** Return a copy of pPtr.
|
||||
** In other words, construct a new RenameToken object and add it
|
||||
** to the list of RenameToken objects currently being built up
|
||||
** in pParse->pRename.
|
||||
**
|
||||
** The pPtr argument is returned so that this routine can be used
|
||||
** with tail recursion in tokenExpr() routine, for a small performance
|
||||
** improvement.
|
||||
*/
|
||||
void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
|
||||
RenameToken *pNew;
|
||||
@@ -1058,14 +1064,13 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
|
||||
sNC.pParse = pParse;
|
||||
assert( pNew->pTabSchema );
|
||||
pParse->pTriggerTab = sqlite3FindTable(db, pNew->table,
|
||||
db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema, 0)].zDbSName
|
||||
db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName
|
||||
);
|
||||
pParse->eTriggerOp = pNew->op;
|
||||
/* ALWAYS() because if the table of the trigger does not exist, the
|
||||
** error would have been hit before this point */
|
||||
if( ALWAYS(pParse->pTriggerTab) ){
|
||||
int iDb = sqlite3SchemaToIndex(db, pParse->pTriggerTab->pSchema, 0);
|
||||
rc = sqlite3ViewGetColumnNames(pParse, iDb, pParse->pTriggerTab);
|
||||
rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
|
||||
}
|
||||
|
||||
/* Resolve symbols in WHEN clause */
|
||||
@@ -1082,41 +1087,38 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
|
||||
Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb);
|
||||
if( pTarget==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
int iDb = sqlite3SchemaToIndex(db, pTarget->pSchema, 0);
|
||||
if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, iDb, pTarget)) ){
|
||||
SrcList sSrc;
|
||||
memset(&sSrc, 0, sizeof(sSrc));
|
||||
sSrc.nSrc = 1;
|
||||
sSrc.a[0].zName = pStep->zTarget;
|
||||
sSrc.a[0].pTab = pTarget;
|
||||
sNC.pSrcList = &sSrc;
|
||||
if( pStep->pWhere ){
|
||||
rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
|
||||
}else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){
|
||||
SrcList sSrc;
|
||||
memset(&sSrc, 0, sizeof(sSrc));
|
||||
sSrc.nSrc = 1;
|
||||
sSrc.a[0].zName = pStep->zTarget;
|
||||
sSrc.a[0].pTab = pTarget;
|
||||
sNC.pSrcList = &sSrc;
|
||||
if( pStep->pWhere ){
|
||||
rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
|
||||
}
|
||||
assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) );
|
||||
if( pStep->pUpsert ){
|
||||
Upsert *pUpsert = pStep->pUpsert;
|
||||
assert( rc==SQLITE_OK );
|
||||
pUpsert->pUpsertSrc = &sSrc;
|
||||
sNC.uNC.pUpsert = pUpsert;
|
||||
sNC.ncFlags = NC_UUpsert;
|
||||
rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
|
||||
if( rc==SQLITE_OK ){
|
||||
ExprList *pUpsertSet = pUpsert->pUpsertSet;
|
||||
rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
|
||||
rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere);
|
||||
}
|
||||
assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) );
|
||||
if( pStep->pUpsert ){
|
||||
Upsert *pUpsert = pStep->pUpsert;
|
||||
assert( rc==SQLITE_OK );
|
||||
pUpsert->pUpsertSrc = &sSrc;
|
||||
sNC.uNC.pUpsert = pUpsert;
|
||||
sNC.ncFlags = NC_UUpsert;
|
||||
rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
|
||||
if( rc==SQLITE_OK ){
|
||||
ExprList *pUpsertSet = pUpsert->pUpsertSet;
|
||||
rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
|
||||
}
|
||||
sNC.ncFlags = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
|
||||
}
|
||||
sNC.ncFlags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1186,15 +1188,8 @@ static void renameParseCleanup(Parse *pParse){
|
||||
** into zNew. The name should be quoted if bQuote is true.
|
||||
**
|
||||
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
|
||||
** Though accessible to application code, it is not intended for use by
|
||||
** applications. The existance of this function, and the way it works,
|
||||
** is subject to change without notice.
|
||||
**
|
||||
** If any of the parameters are out-of-bounds, then simply return NULL.
|
||||
** An out-of-bounds parameter can only occur when the application calls
|
||||
** this function directly. The parameters will always be well-formed when
|
||||
** this routine is invoked by the bytecode for a legitimate ALTER TABLE
|
||||
** statement.
|
||||
** It is only accessible to SQL created using sqlite3NestedParse(). It is
|
||||
** not reachable from ordinary SQL passed into sqlite3_prepare().
|
||||
*/
|
||||
static void renameColumnFunc(
|
||||
sqlite3_context *context,
|
||||
@@ -1579,7 +1574,7 @@ static void renameTableTest(
|
||||
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema, 0);
|
||||
int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
|
||||
int i2 = sqlite3FindDbName(db, zDb);
|
||||
if( i1==i2 ) sqlite3_result_int(context, 1);
|
||||
}
|
||||
@@ -1602,9 +1597,9 @@ static void renameTableTest(
|
||||
*/
|
||||
void sqlite3AlterFunctions(void){
|
||||
static FuncDef aAlterTableFuncs[] = {
|
||||
FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc),
|
||||
FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc),
|
||||
FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest),
|
||||
INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
|
||||
INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
|
||||
INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
|
||||
};
|
||||
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
|
||||
}
|
||||
|
||||
+10
-9
@@ -979,7 +979,6 @@ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
|
||||
*/
|
||||
static void analyzeOneTable(
|
||||
Parse *pParse, /* Parser context */
|
||||
int iDb, /* Database that contains table pTab */
|
||||
Table *pTab, /* Table whose indices are to be analyzed */
|
||||
Index *pOnlyIdx, /* If not NULL, only analyze this one index */
|
||||
int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */
|
||||
@@ -993,6 +992,7 @@ static void analyzeOneTable(
|
||||
Vdbe *v; /* The virtual machine being built up */
|
||||
int i; /* Loop counter */
|
||||
int jZeroRows = -1; /* Jump from here if number of rows is zero */
|
||||
int iDb; /* Index of database containing pTab */
|
||||
u8 needTableCnt = 1; /* True to count the table */
|
||||
int regNewRowid = iMem++; /* Rowid for the inserted record */
|
||||
int regStat4 = iMem++; /* Register to hold Stat4Accum object */
|
||||
@@ -1023,6 +1023,7 @@ static void analyzeOneTable(
|
||||
return;
|
||||
}
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb>=0 );
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
@@ -1117,7 +1118,7 @@ static void analyzeOneTable(
|
||||
pParse->nMem = MAX(pParse->nMem, regPrev+nColTest);
|
||||
|
||||
/* Open a read-only cursor on the index being analyzed. */
|
||||
assert( db->aDb[iDb].pSchema==pIdx->pSchema );
|
||||
assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
|
||||
sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
@@ -1347,7 +1348,7 @@ static void analyzeDatabase(Parse *pParse, int iDb){
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||
Table *pTab = (Table*)sqliteHashData(k);
|
||||
analyzeOneTable(pParse, iDb, pTab, 0, iStatCur, iMem, iTab);
|
||||
analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab);
|
||||
}
|
||||
loadAnalysis(pParse, iDb);
|
||||
}
|
||||
@@ -1357,11 +1358,13 @@ static void analyzeDatabase(Parse *pParse, int iDb){
|
||||
** a database. If pOnlyIdx is not NULL then it is a single index
|
||||
** in pTab that should be analyzed.
|
||||
*/
|
||||
static void analyzeTable(Parse *pParse, int iDb, Table *pTab, Index *pOnlyIdx){
|
||||
static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){
|
||||
int iDb;
|
||||
int iStatCur;
|
||||
|
||||
assert( pTab!=0 );
|
||||
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
iStatCur = pParse->nTab;
|
||||
pParse->nTab += 3;
|
||||
@@ -1370,9 +1373,7 @@ static void analyzeTable(Parse *pParse, int iDb, Table *pTab, Index *pOnlyIdx){
|
||||
}else{
|
||||
openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl");
|
||||
}
|
||||
analyzeOneTable(pParse, iDb, pTab,
|
||||
pOnlyIdx, iStatCur, pParse->nMem+1, pParse->nTab
|
||||
);
|
||||
analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur,pParse->nMem+1,pParse->nTab);
|
||||
loadAnalysis(pParse, iDb);
|
||||
}
|
||||
|
||||
@@ -1423,9 +1424,9 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
|
||||
z = sqlite3NameFromToken(db, pTableName);
|
||||
if( z ){
|
||||
if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
|
||||
analyzeTable(pParse, iDb, pIdx->pTable, pIdx);
|
||||
analyzeTable(pParse, pIdx->pTable, pIdx);
|
||||
}else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){
|
||||
analyzeTable(pParse, iDb, pTab, 0);
|
||||
analyzeTable(pParse, pTab, 0);
|
||||
}
|
||||
sqlite3DbFree(db, z);
|
||||
}
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@ void sqlite3AuthRead(
|
||||
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
|
||||
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
|
||||
if( db->xAuth==0 ) return;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pSchema, 0); /* TODO! */
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
|
||||
if( iDb<0 ){
|
||||
/* An attempt to read a column out of a subquery or other
|
||||
** temporary table. */
|
||||
|
||||
+1
-2
@@ -252,8 +252,7 @@ int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
|
||||
int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
|
||||
Btree *p;
|
||||
assert( db!=0 );
|
||||
if( pSchema && (db->openFlags & SQLITE_OPEN_REUSE_SCHEMA) ) return 1;
|
||||
if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema, 0);
|
||||
if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
if( !sqlite3_mutex_held(db->mutex) ) return 0;
|
||||
if( iDb==1 ) return 1;
|
||||
|
||||
+3
-7
@@ -4758,9 +4758,6 @@ static int accessPayload(
|
||||
/* Need to read this page properly. It contains some of the
|
||||
** range of data that is being read (eOp==0) or written (eOp!=0).
|
||||
*/
|
||||
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
||||
sqlite3_file *fd; /* File from which to do direct overflow read */
|
||||
#endif
|
||||
int a = amt;
|
||||
if( a + offset > ovflSize ){
|
||||
a = ovflSize - offset;
|
||||
@@ -4771,7 +4768,7 @@ static int accessPayload(
|
||||
**
|
||||
** 1) this is a read operation, and
|
||||
** 2) data is required from the start of this overflow page, and
|
||||
** 3) there is no open write-transaction, and
|
||||
** 3) there are no dirty pages in the page-cache
|
||||
** 4) the database is file-backed, and
|
||||
** 5) the page is not in the WAL file
|
||||
** 6) at least 4 bytes have already been read into the output buffer
|
||||
@@ -4782,11 +4779,10 @@ static int accessPayload(
|
||||
*/
|
||||
if( eOp==0 /* (1) */
|
||||
&& offset==0 /* (2) */
|
||||
&& pBt->inTransaction==TRANS_READ /* (3) */
|
||||
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
|
||||
&& 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
|
||||
&& sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */
|
||||
&& &pBuf[-4]>=pBufStart /* (6) */
|
||||
){
|
||||
sqlite3_file *fd = sqlite3PagerFile(pBt->pPager);
|
||||
u8 aSave[4];
|
||||
u8 *aWrite = &pBuf[-4];
|
||||
assert( aWrite>=pBufStart ); /* due to (6) */
|
||||
|
||||
+53
-57
@@ -191,7 +191,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
for(i=0; i<pParse->nVtabLock; i++){
|
||||
char *vtab = (char *)pParse->apVtabLock[i];
|
||||
char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
|
||||
sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
|
||||
}
|
||||
pParse->nVtabLock = 0;
|
||||
@@ -227,7 +227,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
if( v && pParse->nErr==0 && !db->mallocFailed ){
|
||||
/* A minimum of one cursor is required if autoincrement is used
|
||||
* See ticket [a696379c1f08866] */
|
||||
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
|
||||
assert( pParse->pAinc==0 || pParse->nTab>0 );
|
||||
sqlite3VdbeMakeReady(v, pParse);
|
||||
pParse->rc = SQLITE_DONE;
|
||||
}else{
|
||||
@@ -266,9 +266,7 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
|
||||
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
|
||||
sqlite3RunParser(pParse, zSql, &zErrMsg);
|
||||
if( zErrMsg ){
|
||||
sqlite3ErrorMsg(pParse, "%z", zErrMsg);
|
||||
}
|
||||
sqlite3DbFree(db, zErrMsg);
|
||||
sqlite3DbFree(db, zSql);
|
||||
memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
|
||||
pParse->nested--;
|
||||
@@ -397,14 +395,9 @@ Table *sqlite3LocateTableItem(
|
||||
struct SrcList_item *p
|
||||
){
|
||||
const char *zDb;
|
||||
if( pParse->iFixDb && pParse->iFixDb!=2 ){
|
||||
zDb = pParse->db->aDb[pParse->iFixDb-1].zDbSName;
|
||||
assert( p->zDatabase==0 || sqlite3StrICmp(p->zDatabase, zDb)==0 );
|
||||
if( p->zDatabase==0 ){
|
||||
p->zDatabase = sqlite3DbStrDup(pParse->db, zDb);
|
||||
}
|
||||
}else if( p->pSchema ){
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema, 0);
|
||||
assert( p->pSchema==0 || p->zDatabase==0 );
|
||||
if( p->pSchema ){
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
|
||||
zDb = pParse->db->aDb[iDb].zDbSName;
|
||||
}else{
|
||||
zDb = p->zDatabase;
|
||||
@@ -534,14 +527,11 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
|
||||
DbSetProperty(db, 1, DB_ResetWanted);
|
||||
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
|
||||
}
|
||||
|
||||
if( db->nSchemaLock==0 ){
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( DbHasProperty(db, i, DB_ResetWanted) ){
|
||||
if( i==1 ){
|
||||
sqlite3SchemaClear(db->aDb[1].pSchema);
|
||||
}else{
|
||||
sqlite3SchemaUnuse(db, i);
|
||||
}
|
||||
sqlite3SchemaClear(db->aDb[i].pSchema);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -554,15 +544,22 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
|
||||
void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
|
||||
int i;
|
||||
sqlite3BtreeEnterAll(db);
|
||||
assert( db->nSchemaLock==0 );
|
||||
for(i=0; i<db->nDb; i=(i?i+1:2)){
|
||||
sqlite3SchemaUnuse(db, i);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Db *pDb = &db->aDb[i];
|
||||
if( pDb->pSchema ){
|
||||
if( db->nSchemaLock==0 ){
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
}else{
|
||||
DbSetProperty(db, i, DB_ResetWanted);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3SchemaClear(db->aDb[1].pSchema);
|
||||
db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk);
|
||||
sqlite3VtabUnlockList(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3CollapseDatabaseArray(db);
|
||||
if( db->nSchemaLock==0 ){
|
||||
sqlite3CollapseDatabaseArray(db);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1902,6 +1899,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
recomputeColumnsNotIndexed(pPk);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
** Return true if zName is a shadow table name in the current database
|
||||
** connection.
|
||||
@@ -1927,6 +1925,9 @@ static int isShadowTableName(sqlite3 *db, char *zName){
|
||||
if( pMod->pModule->xShadowName==0 ) return 0;
|
||||
return pMod->pModule->xShadowName(zTail+1);
|
||||
}
|
||||
#else
|
||||
# define isShadowTableName(x,y) 0
|
||||
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
/*
|
||||
** This routine is called to report the final ")" that terminates
|
||||
@@ -2004,7 +2005,7 @@ void sqlite3EndTable(
|
||||
}
|
||||
}
|
||||
|
||||
iDb = sqlite3SchemaToIndex(db, p->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(db, p->pSchema);
|
||||
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
/* Resolve names in all CHECK constraint expressions.
|
||||
@@ -2158,7 +2159,7 @@ void sqlite3EndTable(
|
||||
#endif
|
||||
|
||||
/* Reparse everything to update our internal data structures */
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
|
||||
sqlite3VdbeAddParseSchemaOp(v, iDb,
|
||||
sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
|
||||
}
|
||||
|
||||
@@ -2224,7 +2225,7 @@ void sqlite3CreateView(
|
||||
p = pParse->pNewTable;
|
||||
if( p==0 || pParse->nErr ) goto create_view_fail;
|
||||
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
|
||||
iDb = sqlite3SchemaToIndex(db, p->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(db, p->pSchema);
|
||||
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
|
||||
if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
|
||||
|
||||
@@ -2277,7 +2278,7 @@ create_view_fail:
|
||||
** the columns of the view in the pTable structure. Return the number
|
||||
** of errors. If an error is seen leave an error message in pParse->zErrMsg.
|
||||
*/
|
||||
int sqlite3ViewGetColumnNames(Parse *pParse, int iDb, Table *pTable){
|
||||
int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
Table *pSelTab; /* A fake table from which we get the result set */
|
||||
Select *pSel; /* Copy of the SELECT that implements the view */
|
||||
int nErr = 0; /* Number of errors encountered */
|
||||
@@ -2294,7 +2295,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, int iDb, Table *pTable){
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
db->nSchemaLock++;
|
||||
rc = sqlite3VtabCallConnect(pParse, iDb, pTable);
|
||||
rc = sqlite3VtabCallConnect(pParse, pTable);
|
||||
db->nSchemaLock--;
|
||||
if( rc ){
|
||||
return 1;
|
||||
@@ -2541,7 +2542,7 @@ static void destroyTable(Parse *pParse, Table *pTab){
|
||||
if( iLargest==0 ){
|
||||
return;
|
||||
}else{
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema, 0);
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
assert( iDb>=0 && iDb<pParse->db->nDb );
|
||||
destroyRootPage(pParse, iLargest, iDb);
|
||||
iDestroyed = iLargest;
|
||||
@@ -2668,14 +2669,13 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
||||
if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
|
||||
goto exit_drop_table;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
|
||||
/* If pTab is a virtual table, call ViewGetColumnNames() to ensure
|
||||
** it is initialized.
|
||||
*/
|
||||
if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){
|
||||
if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){
|
||||
goto exit_drop_table;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
@@ -2696,7 +2696,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
}else if( IsVirtual(pTab) ){
|
||||
code = SQLITE_DROP_VTABLE;
|
||||
zArg2 = sqlite3GetVTable(db, -1, pTab)->pMod->zName;
|
||||
zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName;
|
||||
#endif
|
||||
}else{
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
@@ -2917,12 +2917,7 @@ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
|
||||
** the index already exists and must be cleared before being refilled and
|
||||
** the root page number of the index is taken from pIndex->tnum.
|
||||
*/
|
||||
static void sqlite3RefillIndex(
|
||||
Parse *pParse,
|
||||
int iDb,
|
||||
Index *pIndex,
|
||||
int memRootPage
|
||||
){
|
||||
static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
Table *pTab = pIndex->pTable; /* The table that is indexed */
|
||||
int iTab = pParse->nTab++; /* Btree cursor used for pTab */
|
||||
int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
|
||||
@@ -2935,6 +2930,7 @@ static void sqlite3RefillIndex(
|
||||
KeyInfo *pKey; /* KeyInfo for index */
|
||||
int regRecord; /* Register holding assembled index record */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
|
||||
@@ -3068,6 +3064,7 @@ void sqlite3CreateIndex(
|
||||
char *zName = 0; /* Name of the index */
|
||||
int nName; /* Number of characters in zName */
|
||||
int i, j;
|
||||
DbFixer sFix; /* For assigning database names to pTable */
|
||||
int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */
|
||||
sqlite3 *db = pParse->db;
|
||||
Db *pDb; /* The specific table containing the indexed database */
|
||||
@@ -3116,9 +3113,13 @@ void sqlite3CreateIndex(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( iDb!=1 ) pTblName->a[0].zDatabase = db->aDb[iDb].zDbSName;
|
||||
sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
|
||||
if( sqlite3FixSrcList(&sFix, pTblName) ){
|
||||
/* Because the parser constructs pTblName from a single identifier,
|
||||
** sqlite3FixSrcList can never fail. */
|
||||
assert(0);
|
||||
}
|
||||
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
|
||||
pTblName->a[0].zDatabase = 0;
|
||||
assert( db->mallocFailed==0 || pTab==0 );
|
||||
if( pTab==0 ) goto exit_create_index;
|
||||
if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){
|
||||
@@ -3133,7 +3134,7 @@ void sqlite3CreateIndex(
|
||||
assert( pStart==0 );
|
||||
pTab = pParse->pNewTable;
|
||||
if( !pTab ) goto exit_create_index;
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
}
|
||||
pDb = &db->aDb[iDb];
|
||||
|
||||
@@ -3556,9 +3557,9 @@ void sqlite3CreateIndex(
|
||||
** to invalidate all pre-compiled statements.
|
||||
*/
|
||||
if( pTblName ){
|
||||
sqlite3RefillIndex(pParse, iDb, pIndex, iMem);
|
||||
sqlite3RefillIndex(pParse, pIndex, iMem);
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
|
||||
sqlite3VdbeAddParseSchemaOp(v, iDb,
|
||||
sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
|
||||
sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
|
||||
}
|
||||
@@ -3571,7 +3572,7 @@ void sqlite3CreateIndex(
|
||||
** sure all indices labeled OE_Replace come after all those labeled
|
||||
** OE_Ignore. This is necessary for the correct constraint check
|
||||
** processing (in sqlite3GenerateConstraintChecks()) as part of
|
||||
** UPDATE and INSERT statements.
|
||||
** UPDATE and INSERT statements.
|
||||
*/
|
||||
if( db->init.busy || pTblName==0 ){
|
||||
if( onError!=OE_Replace || pTab->pIndex==0
|
||||
@@ -3682,8 +3683,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
|
||||
"or PRIMARY KEY constraint cannot be dropped", 0);
|
||||
goto exit_drop_index;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema, 0);
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int code = SQLITE_DROP_INDEX;
|
||||
@@ -4416,18 +4416,14 @@ static int collationMatch(const char *zColl, Index *pIndex){
|
||||
** If pColl==0 then recompute all indices of pTab.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_REINDEX
|
||||
static void reindexTable(
|
||||
Parse *pParse,
|
||||
int iDb,
|
||||
Table *pTab,
|
||||
char const *zColl
|
||||
){
|
||||
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
|
||||
Index *pIndex; /* An index associated with pTab */
|
||||
|
||||
for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
|
||||
if( zColl==0 || collationMatch(zColl, pIndex) ){
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3RefillIndex(pParse, iDb, pIndex, -1);
|
||||
sqlite3RefillIndex(pParse, pIndex, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4451,7 +4447,7 @@ static void reindexDatabases(Parse *pParse, char const *zColl){
|
||||
assert( pDb!=0 );
|
||||
for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||
pTab = (Table*)sqliteHashData(k);
|
||||
reindexTable(pParse, iDb, pTab, zColl);
|
||||
reindexTable(pParse, pTab, zColl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4510,7 +4506,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
pTab = sqlite3FindTable(db, z, zDb);
|
||||
if( pTab ){
|
||||
reindexTable(pParse, iDb, pTab, 0);
|
||||
reindexTable(pParse, pTab, 0);
|
||||
sqlite3DbFree(db, z);
|
||||
return;
|
||||
}
|
||||
@@ -4518,7 +4514,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
|
||||
sqlite3DbFree(db, z);
|
||||
if( pIndex ){
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3RefillIndex(pParse, iDb, pIndex, -1);
|
||||
sqlite3RefillIndex(pParse, pIndex, -1);
|
||||
return;
|
||||
}
|
||||
sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
|
||||
|
||||
+1
-106
@@ -479,117 +479,13 @@ void sqlite3SchemaClear(void *p){
|
||||
pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted);
|
||||
}
|
||||
|
||||
/*
|
||||
** Global linked list of sharable Schema objects. Read and write access must
|
||||
** be protected by the SQLITE_MUTEX_STATIC_MASTER mutex.
|
||||
*/
|
||||
static Schema *SQLITE_WSD sharedSchemaList = 0;
|
||||
|
||||
/*
|
||||
** Check that the schema of db iDb is writable (either because it is the temp
|
||||
** db schema or because the db handle was opened without
|
||||
** SQLITE_OPEN_REUSE_SCHEMA). If so, do nothing. Otherwise, leave an
|
||||
** error in the Parse object.
|
||||
*/
|
||||
void sqlite3SchemaWritable(Parse *pParse, int iDb){
|
||||
if( iDb!=1 && (pParse->db->openFlags & SQLITE_OPEN_REUSE_SCHEMA)
|
||||
&& IN_DECLARE_VTAB==0
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "attempt to modify read-only schema");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Replace the Schema object currently associated with database iDb with
|
||||
** an empty schema object, ready to be populated. If there are multiple
|
||||
** users of the Schema, this means decrementing the current objects ref
|
||||
** count and replacing it with a pointer to a new, empty, object. Or, if
|
||||
** the database handle passed as the first argument of the schema object
|
||||
** is the only user, remove it from the shared list (if applicable) and
|
||||
** clear it in place.
|
||||
*/
|
||||
void sqlite3SchemaUnuse(sqlite3 *db, int iDb){
|
||||
Db *pDb = &db->aDb[iDb];
|
||||
Schema *pSchema;
|
||||
assert( iDb!=1 );
|
||||
if( (pSchema = pDb->pSchema) ){
|
||||
|
||||
if( (db->openFlags & SQLITE_OPEN_REUSE_SCHEMA) ){
|
||||
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
assert( pSchema->nRef>=1 );
|
||||
if( pSchema->nRef==1 ){
|
||||
Schema **pp;
|
||||
for(pp=&sharedSchemaList; (*pp); pp=&(*pp)->pNext){
|
||||
if( *pp==pSchema ){
|
||||
*pp = pSchema->pNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pSchema->pNext = 0;
|
||||
}else{
|
||||
assert( db->openFlags & SQLITE_OPEN_REUSE_SCHEMA );
|
||||
pSchema->nRef--;
|
||||
pDb->pSchema = pSchema = 0;
|
||||
}
|
||||
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
|
||||
}
|
||||
|
||||
if( pSchema==0 ){
|
||||
db->aDb[iDb].pSchema = sqlite3SchemaGet(db, 0);
|
||||
}else{
|
||||
sqlite3SchemaClear(pSchema);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The schema for database iDb of database handle db, which was opened
|
||||
** with SQLITE_OPEN_REUSE_SCHEMA, has just been parsed. This function
|
||||
** checks the global list (sharedSchemaList) for a matching schema and,
|
||||
** if one is found, frees the newly parsed Schema object and adds a pointer
|
||||
** to the existing shared schema in its place. Or, if there is no matching
|
||||
** schema in the list, then the new schema is added to it.
|
||||
*/
|
||||
void sqlite3SchemaReuse(sqlite3 *db, int iDb){
|
||||
Schema *pSchema = db->aDb[iDb].pSchema;
|
||||
Schema *p;
|
||||
assert( pSchema && iDb!=1 );
|
||||
|
||||
sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_SCHEMA_REUSE) );
|
||||
for(p=sharedSchemaList; p; p=p->pNext){
|
||||
if( p->cksum==pSchema->cksum
|
||||
&& p->schema_cookie==pSchema->schema_cookie
|
||||
){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !p ){
|
||||
/* No matching schema was found. */
|
||||
pSchema->pNext = sharedSchemaList;
|
||||
sharedSchemaList = pSchema;
|
||||
}else{
|
||||
/* Found a matching schema. Increase its ref count. */
|
||||
p->nRef++;
|
||||
}
|
||||
sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_SCHEMA_REUSE) );
|
||||
|
||||
/* If a matching schema was found in the shared schema list, free the
|
||||
** schema object just parsed, and add a pointer to the matching schema
|
||||
** to the db handle. */
|
||||
if( p ){
|
||||
sqlite3SchemaClear(pSchema);
|
||||
sqlite3DbFree(0, pSchema);
|
||||
db->aDb[iDb].pSchema = p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Find and return the schema associated with a BTree. Create
|
||||
** a new one if necessary.
|
||||
*/
|
||||
Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
|
||||
Schema * p;
|
||||
if( pBt && (db->openFlags & SQLITE_OPEN_REUSE_SCHEMA)==0 ){
|
||||
if( pBt ){
|
||||
p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
|
||||
}else{
|
||||
p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));
|
||||
@@ -602,7 +498,6 @@ Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
|
||||
sqlite3HashInit(&p->trigHash);
|
||||
sqlite3HashInit(&p->fkeyHash);
|
||||
p->enc = SQLITE_UTF8;
|
||||
p->nRef = 1;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
+24
-21
@@ -62,7 +62,7 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
|
||||
static int tabIsReadOnly(Parse *pParse, Table *pTab){
|
||||
sqlite3 *db;
|
||||
if( IsVirtual(pTab) ){
|
||||
return sqlite3GetVTable(pParse->db, -1, pTab)->pMod->pModule->xUpdate==0;
|
||||
return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0;
|
||||
}
|
||||
if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0;
|
||||
db = pParse->db;
|
||||
@@ -70,9 +70,11 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){
|
||||
return sqlite3WritableSchema(db)==0 && pParse->nested==0;
|
||||
}
|
||||
assert( pTab->tabFlags & TF_Shadow );
|
||||
return (db->flags & SQLITE_Defensive)!=0
|
||||
&& db->nVdbeExec==0
|
||||
&& db->pVtabCtx==0;
|
||||
return (db->flags & SQLITE_Defensive)!=0
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
&& db->pVtabCtx==0
|
||||
#endif
|
||||
&& db->nVdbeExec==0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -103,7 +105,6 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
|
||||
*/
|
||||
void sqlite3MaterializeView(
|
||||
Parse *pParse, /* Parsing context */
|
||||
int iDb, /* Database in which view resides */
|
||||
Table *pView, /* View definition */
|
||||
Expr *pWhere, /* Optional WHERE clause to be added */
|
||||
ExprList *pOrderBy, /* Optional ORDER BY clause */
|
||||
@@ -114,6 +115,7 @@ void sqlite3MaterializeView(
|
||||
Select *pSel;
|
||||
SrcList *pFrom;
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
|
||||
pWhere = sqlite3ExprDup(db, pWhere, 0);
|
||||
pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
|
||||
if( pFrom ){
|
||||
@@ -318,17 +320,17 @@ void sqlite3DeleteFrom(
|
||||
}
|
||||
#endif
|
||||
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pTabList->a[0].zDatabase);
|
||||
assert( iDb<db->nDb );
|
||||
|
||||
/* If pTab is really a view, make sure it has been initialized.
|
||||
*/
|
||||
if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){
|
||||
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
|
||||
if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb<db->nDb );
|
||||
rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0,
|
||||
db->aDb[iDb].zDbSName);
|
||||
assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
|
||||
@@ -365,7 +367,9 @@ void sqlite3DeleteFrom(
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
if( isView ){
|
||||
sqlite3MaterializeView(pParse, iDb, pTab, pWhere, pOrderBy, pLimit,iTabCur);
|
||||
sqlite3MaterializeView(pParse, pTab,
|
||||
pWhere, pOrderBy, pLimit, iTabCur
|
||||
);
|
||||
iDataCur = iIdxCur = iTabCur;
|
||||
pOrderBy = 0;
|
||||
pLimit = 0;
|
||||
@@ -529,8 +533,8 @@ void sqlite3DeleteFrom(
|
||||
iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
}
|
||||
testcase( IsVirtual(pTab) );
|
||||
sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite,
|
||||
OPFLAG_FORDELETE, iTabCur, aToOpen, &iDataCur, &iIdxCur);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE,
|
||||
iTabCur, aToOpen, &iDataCur, &iIdxCur);
|
||||
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
|
||||
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
|
||||
if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
|
||||
@@ -563,8 +567,8 @@ void sqlite3DeleteFrom(
|
||||
/* Delete the row */
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( IsVirtual(pTab) ){
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, iDb, pTab);
|
||||
sqlite3VtabMakeWritable(pParse, iDb, pTab);
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
|
||||
sqlite3MayAbort(pParse);
|
||||
if( eOnePass==ONEPASS_SINGLE ){
|
||||
@@ -579,7 +583,7 @@ void sqlite3DeleteFrom(
|
||||
#endif
|
||||
{
|
||||
int count = (pParse->nested==0); /* True to count changes */
|
||||
sqlite3GenerateRowDelete(pParse, iDb, pTab, pTrigger, iDataCur, iIdxCur,
|
||||
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
||||
iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]);
|
||||
}
|
||||
|
||||
@@ -678,7 +682,6 @@ delete_from_cleanup:
|
||||
*/
|
||||
void sqlite3GenerateRowDelete(
|
||||
Parse *pParse, /* Parsing context */
|
||||
int iDb, /* Database containing pTab */
|
||||
Table *pTab, /* Table containing the row to be deleted */
|
||||
Trigger *pTrigger, /* List of triggers to (potentially) fire */
|
||||
int iDataCur, /* Cursor from which column data is extracted */
|
||||
@@ -721,7 +724,7 @@ void sqlite3GenerateRowDelete(
|
||||
/* TODO: Could use temporary registers here. Also could attempt to
|
||||
** avoid copying the contents of the rowid register. */
|
||||
mask = sqlite3TriggerColmask(
|
||||
pParse, iDb, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
|
||||
pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
|
||||
);
|
||||
mask |= sqlite3FkOldmask(pParse, pTab);
|
||||
iOld = pParse->nMem+1;
|
||||
@@ -740,7 +743,7 @@ void sqlite3GenerateRowDelete(
|
||||
|
||||
/* Invoke BEFORE DELETE trigger programs. */
|
||||
addrStart = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3CodeRowTrigger(pParse, iDb, pTrigger,
|
||||
sqlite3CodeRowTrigger(pParse, pTrigger,
|
||||
TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
|
||||
);
|
||||
|
||||
@@ -763,7 +766,7 @@ void sqlite3GenerateRowDelete(
|
||||
/* Do FK processing. This call checks that any FK constraints that
|
||||
** refer to this table (i.e. constraints attached to other tables)
|
||||
** are not violated by deleting this row. */
|
||||
sqlite3FkCheck(pParse, iDb, pTab, iOld, 0, 0, 0);
|
||||
sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Delete the index and table entries. Skip this step if pTab is really
|
||||
@@ -796,10 +799,10 @@ void sqlite3GenerateRowDelete(
|
||||
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
|
||||
** handle rows (possibly in other tables) that refer via a foreign key
|
||||
** to the row just deleted. */
|
||||
sqlite3FkActions(pParse, iDb, pTab, 0, iOld, 0, 0);
|
||||
sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0);
|
||||
|
||||
/* Invoke AFTER DELETE trigger programs. */
|
||||
sqlite3CodeRowTrigger(pParse, iDb, pTrigger,
|
||||
sqlite3CodeRowTrigger(pParse, pTrigger,
|
||||
TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
|
||||
);
|
||||
|
||||
|
||||
+1
-1
@@ -2369,7 +2369,7 @@ int sqlite3FindInIndex(
|
||||
pTab = p->pSrc->a[0].pTab;
|
||||
|
||||
/* Code an OP_Transaction and OP_TableLock for <table>. */
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, p->pSrc->a[0].zDatabase);
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
||||
|
||||
|
||||
+4
-3
@@ -862,7 +862,6 @@ static int isSetNullAction(Parse *pParse, FKey *pFKey){
|
||||
*/
|
||||
void sqlite3FkCheck(
|
||||
Parse *pParse, /* Parse context */
|
||||
int iDb, /* Database containing pTab */
|
||||
Table *pTab, /* Row is being deleted from this table */
|
||||
int regOld, /* Previous row data is stored here */
|
||||
int regNew, /* New row data is stored here */
|
||||
@@ -871,6 +870,7 @@ void sqlite3FkCheck(
|
||||
){
|
||||
sqlite3 *db = pParse->db; /* Database handle */
|
||||
FKey *pFKey; /* Used to iterate through FKs */
|
||||
int iDb; /* Index of database containing pTab */
|
||||
const char *zDb; /* Name of database containing pTab */
|
||||
int isIgnoreErrors = pParse->disableTriggers;
|
||||
|
||||
@@ -879,6 +879,8 @@ void sqlite3FkCheck(
|
||||
|
||||
/* If foreign-keys are disabled, this function is a no-op. */
|
||||
if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
|
||||
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
|
||||
/* Loop through all the foreign key constraints for which pTab is the
|
||||
@@ -1357,7 +1359,6 @@ static Trigger *fkActionTrigger(
|
||||
*/
|
||||
void sqlite3FkActions(
|
||||
Parse *pParse, /* Parse context */
|
||||
int iDb, /* Database in which pTab resides */
|
||||
Table *pTab, /* Table being updated or deleted from */
|
||||
ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */
|
||||
int regOld, /* Address of array containing old row */
|
||||
@@ -1374,7 +1375,7 @@ void sqlite3FkActions(
|
||||
if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){
|
||||
Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges);
|
||||
if( pAct ){
|
||||
sqlite3CodeRowTriggerDirect(pParse, iDb, pAct,pTab,regOld,OE_Abort,0);
|
||||
sqlite3CodeRowTriggerDirect(pParse, pAct, pTab, regOld, OE_Abort, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
0, /* xTestCallback */
|
||||
#endif
|
||||
0, /* bLocaltimeFault */
|
||||
0, /* bInternalFunctions */
|
||||
0x7ffffffe, /* iOnceResetThreshold */
|
||||
SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */
|
||||
};
|
||||
|
||||
+18
-18
@@ -168,7 +168,7 @@ static int readsTable(Parse *p, int iDb, Table *pTab){
|
||||
int i;
|
||||
int iEnd = sqlite3VdbeCurrentAddr(v);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, iDb, pTab) : 0;
|
||||
VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0;
|
||||
#endif
|
||||
|
||||
for(i=1; i<iEnd; i++){
|
||||
@@ -319,6 +319,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){
|
||||
aOp[7].p2 = memId+2;
|
||||
aOp[7].p1 = memId;
|
||||
aOp[10].p2 = memId;
|
||||
if( pParse->nTab==0 ) pParse->nTab = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,7 +569,7 @@ void sqlite3Insert(
|
||||
if( pTab==0 ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pTabList->a[0].zDatabase);
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb<db->nDb );
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0,
|
||||
db->aDb[iDb].zDbSName) ){
|
||||
@@ -596,7 +597,7 @@ void sqlite3Insert(
|
||||
/* If pTab is really a view, make sure it has been initialized.
|
||||
** ViewGetColumnNames() is a no-op if pTab is not a view.
|
||||
*/
|
||||
if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){
|
||||
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
|
||||
@@ -811,7 +812,7 @@ void sqlite3Insert(
|
||||
/* If this is not a view, open the table and and all indices */
|
||||
if( !isView ){
|
||||
int nIdx;
|
||||
nIdx = sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite, 0, -1, 0,
|
||||
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
|
||||
&iDataCur, &iIdxCur);
|
||||
aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1));
|
||||
if( aRegIdx==0 ){
|
||||
@@ -927,7 +928,7 @@ void sqlite3Insert(
|
||||
}
|
||||
|
||||
/* Fire BEFORE or INSTEAD OF triggers */
|
||||
sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
|
||||
sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
|
||||
pTab, regCols-pTab->nCol-1, onError, endOfLoop);
|
||||
|
||||
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
|
||||
@@ -1027,8 +1028,8 @@ void sqlite3Insert(
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( IsVirtual(pTab) ){
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, iDb, pTab);
|
||||
sqlite3VtabMakeWritable(pParse, iDb, pTab);
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
|
||||
sqlite3MayAbort(pParse);
|
||||
@@ -1037,11 +1038,10 @@ void sqlite3Insert(
|
||||
{
|
||||
int isReplace; /* Set to true if constraints may cause a replace */
|
||||
int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
|
||||
sqlite3GenerateConstraintChecks(pParse, iDb, pTab, aRegIdx, iDataCur,
|
||||
iIdxCur, regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace,
|
||||
0, pUpsert
|
||||
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
|
||||
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
|
||||
);
|
||||
sqlite3FkCheck(pParse, iDb, pTab, 0, regIns, 0, 0);
|
||||
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
|
||||
|
||||
/* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
|
||||
** constraints or (b) there are no triggers and this table is not a
|
||||
@@ -1068,7 +1068,7 @@ void sqlite3Insert(
|
||||
|
||||
if( pTrigger ){
|
||||
/* Code AFTER triggers */
|
||||
sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
|
||||
sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
|
||||
pTab, regData-2-pTab->nCol, onError, endOfLoop);
|
||||
}
|
||||
|
||||
@@ -1275,7 +1275,6 @@ int sqlite3ExprReferencesUpdatedColumn(
|
||||
*/
|
||||
void sqlite3GenerateConstraintChecks(
|
||||
Parse *pParse, /* The parser context */
|
||||
int iDb, /* Databse that contains pTab */
|
||||
Table *pTab, /* The table being inserted or updated */
|
||||
int *aRegIdx, /* Use register aRegIdx[i] for index i. 0 for unused */
|
||||
int iDataCur, /* Canonical data cursor (main table or PK index) */
|
||||
@@ -1559,8 +1558,8 @@ void sqlite3GenerateConstraintChecks(
|
||||
}
|
||||
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
|
||||
sqlite3MultiWrite(pParse);
|
||||
sqlite3GenerateRowDelete(pParse, iDb, pTab, pTrigger, iDataCur,
|
||||
iIdxCur, regNewData, 1, 0, OE_Replace, 1, -1);
|
||||
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
||||
regNewData, 1, 0, OE_Replace, 1, -1);
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
assert( HasRowid(pTab) );
|
||||
@@ -1808,7 +1807,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
|
||||
sqlite3MultiWrite(pParse);
|
||||
}
|
||||
sqlite3GenerateRowDelete(pParse, iDb, pTab, pTrigger, iDataCur, iIdxCur,
|
||||
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
||||
regR, nPkField, 0, OE_Replace,
|
||||
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
|
||||
seenReplace = 1;
|
||||
@@ -1969,7 +1968,6 @@ void sqlite3CompleteInsertion(
|
||||
*/
|
||||
int sqlite3OpenTableAndIndices(
|
||||
Parse *pParse, /* Parsing context */
|
||||
int iDb, /* Database to open pTab in */
|
||||
Table *pTab, /* Table to be opened */
|
||||
int op, /* OP_OpenRead or OP_OpenWrite */
|
||||
u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */
|
||||
@@ -1979,6 +1977,7 @@ int sqlite3OpenTableAndIndices(
|
||||
int *piIdxCur /* Write the first index cursor number here */
|
||||
){
|
||||
int i;
|
||||
int iDb;
|
||||
int iDataCur;
|
||||
Index *pIdx;
|
||||
Vdbe *v;
|
||||
@@ -1991,6 +1990,7 @@ int sqlite3OpenTableAndIndices(
|
||||
** can detect if they are used by mistake in the caller. */
|
||||
return 0;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
assert( v!=0 );
|
||||
if( iBase<0 ) iBase = pParse->nTab;
|
||||
@@ -2285,7 +2285,7 @@ static int xferOptimization(
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_xferopt_count++;
|
||||
#endif
|
||||
iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema, pItem->zDatabase);
|
||||
iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema);
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
sqlite3CodeVerifySchema(pParse, iDbSrc);
|
||||
iSrc = pParse->nTab++;
|
||||
|
||||
@@ -50,7 +50,13 @@ int sqlite3_exec(
|
||||
char **azVals = 0;
|
||||
|
||||
pStmt = 0;
|
||||
#ifdef SQLITE_ENABLE_NORMALIZE
|
||||
rc = sqlite3_prepare_v3(
|
||||
db, zSql, -1, SQLITE_PREPARE_NORMALIZE, &pStmt, &zLeftover
|
||||
);
|
||||
#else
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
|
||||
#endif
|
||||
assert( rc==SQLITE_OK || pStmt==0 );
|
||||
if( rc!=SQLITE_OK ){
|
||||
continue;
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
# define sqlite3_declare_vtab 0
|
||||
# define sqlite3_vtab_config 0
|
||||
# define sqlite3_vtab_on_conflict 0
|
||||
# define sqlite3_vtab_collation 0
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
|
||||
+20
-7
@@ -1185,10 +1185,6 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
||||
sqlite3BtreeClose(pDb->pBt);
|
||||
pDb->pBt = 0;
|
||||
if( j!=1 ){
|
||||
if( db->openFlags & SQLITE_OPEN_REUSE_SCHEMA ){
|
||||
sqlite3SchemaUnuse(db, j);
|
||||
sqlite3DbFree(0, pDb->pSchema);
|
||||
}
|
||||
pDb->pSchema = 0;
|
||||
}
|
||||
}
|
||||
@@ -2000,6 +1996,7 @@ void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pOld = db->pTraceArg;
|
||||
db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0;
|
||||
if( db->xProfile ) db->mTrace |= SQLITE_TRACE_XPROFILE;
|
||||
db->xTrace = (int(*)(u32,void*,void*,void*))xTrace;
|
||||
db->pTraceArg = pArg;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
@@ -2024,6 +2021,9 @@ int sqlite3_trace_v2(
|
||||
if( mTrace==0 ) xTrace = 0;
|
||||
if( xTrace==0 ) mTrace = 0;
|
||||
db->mTrace = mTrace;
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
if( db->xProfile ) db->mTrace |= SQLITE_TRACE_XPROFILE;
|
||||
#endif
|
||||
db->xTrace = xTrace;
|
||||
db->pTraceArg = pArg;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
@@ -2056,6 +2056,8 @@ void *sqlite3_profile(
|
||||
pOld = db->pProfileArg;
|
||||
db->xProfile = xProfile;
|
||||
db->pProfileArg = pArg;
|
||||
db->mTrace &= SQLITE_TRACE_NONLEGACY_MASK;
|
||||
if( db->xProfile ) db->mTrace |= SQLITE_TRACE_XPROFILE;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return pOld;
|
||||
}
|
||||
@@ -3957,15 +3959,26 @@ int sqlite3_test_control(int op, ...){
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
|
||||
**
|
||||
** If parameter onoff is non-zero, configure the wrappers so that all
|
||||
** subsequent calls to localtime() and variants fail. If onoff is zero,
|
||||
** undo this setting.
|
||||
** If parameter onoff is non-zero, subsequent calls to localtime()
|
||||
** and its variants fail. If onoff is zero, undo this setting.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
|
||||
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff);
|
||||
**
|
||||
** If parameter onoff is non-zero, internal-use-only SQL functions
|
||||
** are visible to ordinary SQL. This is useful for testing but is
|
||||
** unsafe because invalid parameters to those internal-use-only functions
|
||||
** can result in crashes or segfaults.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
|
||||
sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
|
||||
**
|
||||
** Set or clear a flag that indicates that the database file is always well-
|
||||
|
||||
+23
-7
@@ -284,8 +284,7 @@ struct winFile {
|
||||
int nFetchOut; /* Number of outstanding xFetch references */
|
||||
HANDLE hMap; /* Handle for accessing memory mapping */
|
||||
void *pMapRegion; /* Area memory mapped */
|
||||
sqlite3_int64 mmapSize; /* Usable size of mapped region */
|
||||
sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
|
||||
sqlite3_int64 mmapSize; /* Size of mapped region */
|
||||
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
|
||||
#endif
|
||||
};
|
||||
@@ -2906,6 +2905,26 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
|
||||
DWORD lastErrno;
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
sqlite3_int64 oldMmapSize;
|
||||
if( pFile->nFetchOut>0 ){
|
||||
/* File truncation is a no-op if there are outstanding memory mapped
|
||||
** pages. This is because truncating the file means temporarily unmapping
|
||||
** the file, and that might delete memory out from under existing cursors.
|
||||
**
|
||||
** This can result in incremental vacuum not truncating the file,
|
||||
** if there is an active read cursor when the incremental vacuum occurs.
|
||||
** No real harm comes of this - the database file is not corrupted,
|
||||
** though some folks might complain that the file is bigger than it
|
||||
** needs to be.
|
||||
**
|
||||
** The only feasible work-around is to defer the truncation until after
|
||||
** all references to memory-mapped content are closed. That is doable,
|
||||
** but involves adding a few branches in the common write code path which
|
||||
** could slow down normal operations slightly. Hence, we have decided for
|
||||
** now to simply make trancations a no-op if there are pending reads. We
|
||||
** can maybe revisit this decision in the future.
|
||||
*/
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
assert( pFile );
|
||||
@@ -4334,9 +4353,9 @@ shmpage_out:
|
||||
static int winUnmapfile(winFile *pFile){
|
||||
assert( pFile!=0 );
|
||||
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
|
||||
"mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
|
||||
"mmapSize=%lld, mmapSizeMax=%lld\n",
|
||||
osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
|
||||
pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
|
||||
pFile->mmapSize, pFile->mmapSizeMax));
|
||||
if( pFile->pMapRegion ){
|
||||
if( !osUnmapViewOfFile(pFile->pMapRegion) ){
|
||||
pFile->lastErrno = osGetLastError();
|
||||
@@ -4348,7 +4367,6 @@ static int winUnmapfile(winFile *pFile){
|
||||
}
|
||||
pFile->pMapRegion = 0;
|
||||
pFile->mmapSize = 0;
|
||||
pFile->mmapSizeActual = 0;
|
||||
}
|
||||
if( pFile->hMap!=NULL ){
|
||||
if( !osCloseHandle(pFile->hMap) ){
|
||||
@@ -4459,7 +4477,6 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
|
||||
}
|
||||
pFd->pMapRegion = pNew;
|
||||
pFd->mmapSize = nMap;
|
||||
pFd->mmapSizeActual = nMap;
|
||||
}
|
||||
|
||||
OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
|
||||
@@ -5261,7 +5278,6 @@ static int winOpen(
|
||||
pFile->hMap = NULL;
|
||||
pFile->pMapRegion = 0;
|
||||
pFile->mmapSize = 0;
|
||||
pFile->mmapSizeActual = 0;
|
||||
pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
|
||||
#endif
|
||||
|
||||
|
||||
+25
-11
@@ -825,19 +825,30 @@ static const unsigned char aJournalMagic[] = {
|
||||
*/
|
||||
#define isOpen(pFd) ((pFd)->pMethods!=0)
|
||||
|
||||
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
||||
/*
|
||||
** Return true if this pager uses a write-ahead log to read page pgno.
|
||||
** Return false if the pager reads pgno directly from the database.
|
||||
** Return true if page pgno can be read directly from the database file
|
||||
** by the b-tree layer. This is the case if:
|
||||
**
|
||||
** * the database file is open,
|
||||
** * there are no dirty pages in the cache, and
|
||||
** * the desired page is not currently in the wal file.
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
|
||||
int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
|
||||
u32 iRead = 0;
|
||||
int rc;
|
||||
if( pPager->pWal==0 ) return 0;
|
||||
rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
|
||||
return rc || iRead;
|
||||
int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
|
||||
if( pPager->fd->pMethods==0 ) return 0;
|
||||
if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
if( pPager->pWal ){
|
||||
u32 iRead = 0;
|
||||
int rc;
|
||||
rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
|
||||
return (rc==SQLITE_OK && iRead==0);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
# define pagerUseWal(x) ((x)->pWal!=0)
|
||||
#else
|
||||
@@ -7021,8 +7032,11 @@ void sqlite3PagerSetCodec(
|
||||
void (*xCodecFree)(void*),
|
||||
void *pCodec
|
||||
){
|
||||
pager_reset(pPager);
|
||||
if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
|
||||
if( pPager->xCodecFree ){
|
||||
pPager->xCodecFree(pPager->pCodec);
|
||||
}else{
|
||||
pager_reset(pPager);
|
||||
}
|
||||
pPager->xCodec = pPager->memDb ? 0 : xCodec;
|
||||
pPager->xCodecSizeChng = xCodecSizeChng;
|
||||
pPager->xCodecFree = xCodecFree;
|
||||
|
||||
+4
-5
@@ -179,9 +179,6 @@ int sqlite3PagerSharedLock(Pager *pPager);
|
||||
int sqlite3PagerWalCallback(Pager *pPager);
|
||||
int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
|
||||
int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
|
||||
# ifdef SQLITE_DIRECT_OVERFLOW_READ
|
||||
int sqlite3PagerUseWal(Pager *pPager, Pgno);
|
||||
# endif
|
||||
# ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
|
||||
int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
|
||||
@@ -189,8 +186,10 @@ int sqlite3PagerSharedLock(Pager *pPager);
|
||||
int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
|
||||
void sqlite3PagerSnapshotUnlock(Pager *pPager);
|
||||
# endif
|
||||
#else
|
||||
# define sqlite3PagerUseWal(x,y) 0
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
||||
int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
|
||||
@@ -664,6 +664,12 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
|
||||
pNew->zName = pOld->zName;
|
||||
pNew->zDatabase = pOld->zDatabase;
|
||||
pNew->pSelect = pOld->pSelect;
|
||||
if( pOld->fg.isTabFunc ){
|
||||
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
|
||||
pOld->u1.pFuncArg = 0;
|
||||
pOld->fg.isTabFunc = 0;
|
||||
pNew->fg.isTabFunc = 1;
|
||||
}
|
||||
pOld->zName = pOld->zDatabase = 0;
|
||||
pOld->pSelect = 0;
|
||||
}
|
||||
|
||||
@@ -856,6 +856,15 @@ int sqlite3PCachePercentDirty(PCache *pCache){
|
||||
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
||||
/*
|
||||
** Return true if there are one or more dirty pages in the cache. Else false.
|
||||
*/
|
||||
int sqlite3PCacheIsDirty(PCache *pCache){
|
||||
return (pCache->pDirty!=0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** For all dirty pages currently in the cache, invoke the specified
|
||||
|
||||
@@ -183,4 +183,8 @@ int sqlite3HeaderSizePcache1(void);
|
||||
/* Number of dirty pages as a percentage of the configured cache size */
|
||||
int sqlite3PCachePercentDirty(PCache*);
|
||||
|
||||
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
||||
int sqlite3PCacheIsDirty(PCache *pCache);
|
||||
#endif
|
||||
|
||||
#endif /* _PCACHE_H_ */
|
||||
|
||||
+8
-4
@@ -102,10 +102,12 @@ struct PgHdr1 {
|
||||
PCache1 *pCache; /* Cache that currently owns this page */
|
||||
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
|
||||
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
|
||||
/* NB: pLruPrev is only valid if pLruNext!=0 */
|
||||
};
|
||||
|
||||
/*
|
||||
** A page is pinned if it is no on the LRU list
|
||||
** A page is pinned if it is not on the LRU list. To be "pinned" means
|
||||
** that the page is in active use and must not be deallocated.
|
||||
*/
|
||||
#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
|
||||
#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
|
||||
@@ -569,7 +571,8 @@ static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
|
||||
pPage->pLruPrev->pLruNext = pPage->pLruNext;
|
||||
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
|
||||
pPage->pLruNext = 0;
|
||||
pPage->pLruPrev = 0;
|
||||
/* pPage->pLruPrev = 0;
|
||||
** No need to clear pLruPrev as it is never accessed if pLruNext is 0 */
|
||||
assert( pPage->isAnchor==0 );
|
||||
assert( pPage->pCache->pGroup->lru.isAnchor==1 );
|
||||
pPage->pCache->nRecyclable--;
|
||||
@@ -907,8 +910,9 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||
pPage->iKey = iKey;
|
||||
pPage->pNext = pCache->apHash[h];
|
||||
pPage->pCache = pCache;
|
||||
pPage->pLruPrev = 0;
|
||||
pPage->pLruNext = 0;
|
||||
/* pPage->pLruPrev = 0;
|
||||
** No need to clear pLruPrev since it is not accessed when pLruNext==0 */
|
||||
*(void **)pPage->page.pExtra = 0;
|
||||
pCache->apHash[h] = pPage;
|
||||
if( iKey>pCache->iMaxKey ){
|
||||
@@ -1068,7 +1072,7 @@ static void pcache1Unpin(
|
||||
/* It is an error to call this function if the page is already
|
||||
** part of the PGroup LRU list.
|
||||
*/
|
||||
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
|
||||
assert( pPage->pLruNext==0 );
|
||||
assert( PAGE_IS_PINNED(pPage) );
|
||||
|
||||
if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
|
||||
|
||||
+18
-12
@@ -1086,14 +1086,14 @@ void sqlite3Pragma(
|
||||
Table *pTab;
|
||||
pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
|
||||
if( pTab ){
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
int i, k;
|
||||
int nHidden = 0;
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema, zDb);
|
||||
Column *pCol;
|
||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
pParse->nMem = 7;
|
||||
sqlite3CodeVerifySchema(pParse, iTabDb);
|
||||
sqlite3ViewGetColumnNames(pParse, iTabDb, pTab);
|
||||
sqlite3ViewGetColumnNames(pParse, pTab);
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
int isHidden = IsHiddenColumn(pCol);
|
||||
if( isHidden && pPragma->iArg==0 ){
|
||||
@@ -1153,6 +1153,7 @@ void sqlite3Pragma(
|
||||
Table *pTab;
|
||||
pIdx = sqlite3FindIndex(db, zRight, zDb);
|
||||
if( pIdx ){
|
||||
int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
|
||||
int i;
|
||||
int mx;
|
||||
if( pPragma->iArg ){
|
||||
@@ -1165,7 +1166,7 @@ void sqlite3Pragma(
|
||||
pParse->nMem = 3;
|
||||
}
|
||||
pTab = pIdx->pTable;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3CodeVerifySchema(pParse, iIdxDb);
|
||||
assert( pParse->nMem<=pPragma->nPragCName );
|
||||
for(i=0; i<mx; i++){
|
||||
i16 cnum = pIdx->aiColumn[i];
|
||||
@@ -1189,8 +1190,9 @@ void sqlite3Pragma(
|
||||
int i;
|
||||
pTab = sqlite3FindTable(db, zRight, zDb);
|
||||
if( pTab ){
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
pParse->nMem = 5;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3CodeVerifySchema(pParse, iTabDb);
|
||||
for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
|
||||
const char *azOrigin[] = { "c", "u", "pk" };
|
||||
sqlite3VdbeMultiLoad(v, 1, "isisi",
|
||||
@@ -1237,6 +1239,7 @@ void sqlite3Pragma(
|
||||
pParse->nMem = 2;
|
||||
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
|
||||
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
|
||||
if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue;
|
||||
sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
|
||||
}
|
||||
}
|
||||
@@ -1278,9 +1281,10 @@ void sqlite3Pragma(
|
||||
if( pTab ){
|
||||
pFK = pTab->pFKey;
|
||||
if( pFK ){
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
int i = 0;
|
||||
pParse->nMem = 8;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3CodeVerifySchema(pParse, iTabDb);
|
||||
while(pFK){
|
||||
int j;
|
||||
for(j=0; j<pFK->nCol; j++){
|
||||
@@ -1325,9 +1329,9 @@ void sqlite3Pragma(
|
||||
pParse->nMem += 4;
|
||||
regKey = ++pParse->nMem;
|
||||
regRow = ++pParse->nMem;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
|
||||
while( k ){
|
||||
int iTabDb;
|
||||
if( zRight ){
|
||||
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
|
||||
k = 0;
|
||||
@@ -1336,21 +1340,23 @@ void sqlite3Pragma(
|
||||
k = sqliteHashNext(k);
|
||||
}
|
||||
if( pTab==0 || pTab->pFKey==0 ) continue;
|
||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
||||
iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
sqlite3CodeVerifySchema(pParse, iTabDb);
|
||||
sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName);
|
||||
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
|
||||
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
|
||||
sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead);
|
||||
sqlite3VdbeLoadString(v, regResult, pTab->zName);
|
||||
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
|
||||
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
|
||||
if( pParent==0 ) continue;
|
||||
pIdx = 0;
|
||||
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
|
||||
sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName);
|
||||
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
|
||||
if( x==0 ){
|
||||
if( pIdx==0 ){
|
||||
sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
|
||||
sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead);
|
||||
}else{
|
||||
sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
}
|
||||
}else{
|
||||
@@ -1553,7 +1559,7 @@ void sqlite3Pragma(
|
||||
|
||||
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
sqlite3OpenTableAndIndices(pParse, i, pTab, OP_OpenRead, 0,
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
|
||||
1, 0, &iDataCur, &iIdxCur);
|
||||
/* reg[7] counts the number of entries in the table.
|
||||
** reg[8+i] counts the number of entries in the i-th index
|
||||
|
||||
+3
-48
@@ -44,26 +44,6 @@ static void corruptSchema(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Update the Schema.cksum checksum to account for the database object
|
||||
** specified by the three arguments following the first.
|
||||
*/
|
||||
void schemaUpdateChecksum(
|
||||
Schema *pSchema, /* Schema object being parsed */
|
||||
const char *zName, /* Name of new database object */
|
||||
const char *zRoot, /* Root page of new database object */
|
||||
const char *zSql /* SQL used to create new database object */
|
||||
){
|
||||
int i;
|
||||
u64 cksum = pSchema->cksum;
|
||||
if( zName ){
|
||||
for(i=0; zName[i]; i++) cksum += (cksum<<3) + zName[i];
|
||||
}
|
||||
if( zRoot ) for(i=0; zRoot[i]; i++) cksum += (cksum<<3) + zRoot[i];
|
||||
if( zSql ) for(i=0; zSql[i]; i++) cksum += (cksum<<3) + zSql[i];
|
||||
pSchema->cksum = cksum;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the callback routine for the code that initializes the
|
||||
** database. See sqlite3Init() below for additional information.
|
||||
@@ -149,16 +129,6 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
||||
corruptSchema(pData, argv[0], "invalid rootpage");
|
||||
}
|
||||
}
|
||||
|
||||
if( iDb!=1 && (db->openFlags & SQLITE_OPEN_REUSE_SCHEMA) ){
|
||||
/* If this schema might be used by multiple connections, ensure that
|
||||
** the affinity string is allocated here. Otherwise, there might be
|
||||
** a race condition where two threads attempt to allocate it
|
||||
** simultaneously. */
|
||||
Index *pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
|
||||
if( pIndex ) sqlite3IndexAffinityStr(db, pIndex);
|
||||
schemaUpdateChecksum(db->aDb[iDb].pSchema, argv[0], argv[1], argv[2]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -370,10 +340,6 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
if( iDb!=1 && (db->openFlags & SQLITE_OPEN_REUSE_SCHEMA) ){
|
||||
sqlite3SchemaReuse(db, iDb);
|
||||
}
|
||||
|
||||
/* Jump here for an error that occurs after successfully allocating
|
||||
** curMain and calling sqlite3BtreeEnter(). For an error that occurs
|
||||
** before that point, jump to error_out.
|
||||
@@ -508,18 +474,8 @@ static void schemaIsValid(Parse *pParse){
|
||||
** If the same database is attached more than once, the first
|
||||
** attached database is returned.
|
||||
*/
|
||||
int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema, const char *zDb){
|
||||
int i;
|
||||
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( zDb ){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( i==1 ) continue;
|
||||
if( sqlite3StrICmp(zDb, db->aDb[i].zDbSName)==0 ) return i;
|
||||
}
|
||||
assert( sqlite3StrICmp(zDb, "temp")==0 );
|
||||
}
|
||||
int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
|
||||
int i = -1000000;
|
||||
|
||||
/* If pSchema is NULL, then return -1000000. This happens when code in
|
||||
** expr.c is trying to resolve a reference to a transient table (i.e. one
|
||||
@@ -531,6 +487,7 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema, const char *zDb){
|
||||
** more likely to cause a segfault than -1 (of course there are assert()
|
||||
** statements too, but it never hurts to play the odds).
|
||||
*/
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( pSchema ){
|
||||
for(i=0; 1; i++){
|
||||
assert( i<db->nDb );
|
||||
@@ -539,8 +496,6 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema, const char *zDb){
|
||||
}
|
||||
}
|
||||
assert( i>=0 && i<db->nDb );
|
||||
}else{
|
||||
i = -1000000;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
+12
-6
@@ -80,7 +80,7 @@ static void resolveAlias(
|
||||
if( pExpr->op==TK_COLLATE ){
|
||||
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
|
||||
}
|
||||
ExprSetProperty(pDup, EP_Alias);
|
||||
// ExprSetProperty(pDup, EP_Alias);
|
||||
|
||||
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
|
||||
** prevents ExprDelete() from deleting the Expr structure itself,
|
||||
@@ -196,7 +196,6 @@ static int lookupName(
|
||||
int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
|
||||
Table *pTab = 0; /* Table hold the row */
|
||||
Column *pCol; /* A column of pTab */
|
||||
int iDb = -1;
|
||||
|
||||
assert( pNC ); /* the name context cannot be NULL. */
|
||||
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
|
||||
@@ -224,7 +223,6 @@ static int lookupName(
|
||||
assert( db->aDb[i].zDbSName );
|
||||
if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){
|
||||
pSchema = db->aDb[i].pSchema;
|
||||
iDb = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -256,9 +254,8 @@ static int lookupName(
|
||||
}
|
||||
if( hit || zTab==0 ) continue;
|
||||
}
|
||||
if( zDb && (pTab->pSchema || pSchema) ){
|
||||
int ii = sqlite3SchemaToIndex(db, pTab->pSchema, pItem->zDatabase);
|
||||
if( ii!=iDb ) continue;
|
||||
if( zDb && pTab->pSchema!=pSchema ){
|
||||
continue;
|
||||
}
|
||||
if( zTab ){
|
||||
const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
|
||||
@@ -774,6 +771,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
notValid(pParse, pNC, "non-deterministic functions",
|
||||
NC_IdxExpr|NC_PartIdx);
|
||||
}
|
||||
if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
|
||||
&& pParse->nested==0
|
||||
&& sqlite3Config.bInternalFunctions==0
|
||||
){
|
||||
/* Internal-use-only functions are disallowed unless the
|
||||
** SQL is being compiled using sqlite3NestedParse() */
|
||||
no_such_func = 1;
|
||||
pDef = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( 0==IN_RENAME_OBJECT ){
|
||||
|
||||
+5
-15
@@ -1445,7 +1445,7 @@ static void generateSortTail(
|
||||
/* Open any cursors needed for sorter-reference expressions */
|
||||
for(i=0; i<pSort->nDefer; i++){
|
||||
Table *pTab = pSort->aDefer[i].pTab;
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema, 0); /* TODO */
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead);
|
||||
nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey);
|
||||
}
|
||||
@@ -1713,8 +1713,7 @@ static const char *columnTypeImpl(
|
||||
}
|
||||
zOrigTab = pTab->zName;
|
||||
if( pNC->pParse && pTab->pSchema ){
|
||||
/* TODO: Fix the following for REUSE schemas */
|
||||
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema, 0);
|
||||
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
|
||||
zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName;
|
||||
}
|
||||
#else
|
||||
@@ -4887,20 +4886,13 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
}
|
||||
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
|
||||
if( IsVirtual(pTab) || pTab->pSelect ){
|
||||
int iSave = pParse->iFixDb;
|
||||
i16 nCol;
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pFrom->zDatabase);
|
||||
pParse->iFixDb = 1 + iDb;
|
||||
if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){
|
||||
pParse->iFixDb = iSave;
|
||||
return WRC_Abort;
|
||||
}
|
||||
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
|
||||
assert( pFrom->pSelect==0 );
|
||||
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
|
||||
nCol = pTab->nCol;
|
||||
pTab->nCol = -1;
|
||||
sqlite3WalkSelect(pWalker, pFrom->pSelect);
|
||||
pParse->iFixDb = iSave;
|
||||
pTab->nCol = nCol;
|
||||
}
|
||||
#endif
|
||||
@@ -4992,7 +4984,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
|
||||
continue;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pFrom->zDatabase);
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
|
||||
}
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
@@ -6483,9 +6475,7 @@ int sqlite3Select(
|
||||
** is better to execute the op on an index, as indexes are almost
|
||||
** always spread across less pages than their corresponding tables.
|
||||
*/
|
||||
const int iDb = sqlite3SchemaToIndex(
|
||||
pParse->db, pTab->pSchema, pTabList->a[0].zDatabase
|
||||
);
|
||||
const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */
|
||||
Index *pIdx; /* Iterator variable */
|
||||
KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */
|
||||
|
||||
+2
-13
@@ -1065,7 +1065,6 @@ struct ShellState {
|
||||
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
|
||||
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
|
||||
#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
|
||||
#define SHELL_OPEN_REUSESCHEMA 6 /* Open for schema reuse */
|
||||
|
||||
/*
|
||||
** These are the allowed shellFlgs values
|
||||
@@ -3746,11 +3745,6 @@ static void open_db(ShellState *p, int openFlags){
|
||||
sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
|
||||
break;
|
||||
}
|
||||
case SHELL_OPEN_REUSESCHEMA: {
|
||||
sqlite3_open_v2(p->zDbFilename, &p->db,
|
||||
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_REUSE_SCHEMA, 0);
|
||||
break;
|
||||
}
|
||||
case SHELL_OPEN_UNSPEC:
|
||||
case SHELL_OPEN_NORMAL: {
|
||||
sqlite3_open(p->zDbFilename, &p->db);
|
||||
@@ -6685,9 +6679,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
p->openMode = SHELL_OPEN_APPENDVFS;
|
||||
}else if( optionMatch(z, "readonly") ){
|
||||
p->openMode = SHELL_OPEN_READONLY;
|
||||
}else if( optionMatch(z, "reuseschema") ){
|
||||
p->openMode = SHELL_OPEN_REUSESCHEMA;
|
||||
}else if( z[0]=='-' ){
|
||||
#ifdef SQLITE_ENABLE_DESERIALIZE
|
||||
}else if( optionMatch(z, "deserialize") ){
|
||||
p->openMode = SHELL_OPEN_DESERIALIZE;
|
||||
@@ -7686,6 +7677,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
|
||||
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */
|
||||
{ "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
|
||||
{ "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
|
||||
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
|
||||
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
|
||||
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
|
||||
@@ -7780,6 +7772,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
/* sqlite3_test_control(int, int) */
|
||||
case SQLITE_TESTCTRL_ASSERT:
|
||||
case SQLITE_TESTCTRL_ALWAYS:
|
||||
case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
|
||||
if( nArg==3 ){
|
||||
int opt = booleanValue(azArg[2]);
|
||||
rc2 = sqlite3_test_control(testctrl, opt);
|
||||
@@ -8666,8 +8659,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
#endif
|
||||
}else if( strcmp(z,"-readonly")==0 ){
|
||||
data.openMode = SHELL_OPEN_READONLY;
|
||||
}else if( strcmp(z,"-reuseschema")==0 ){
|
||||
data.openMode = SHELL_OPEN_REUSESCHEMA;
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
|
||||
}else if( strncmp(z, "-A",2)==0 ){
|
||||
/* All remaining command-line arguments are passed to the ".archive"
|
||||
@@ -8767,8 +8758,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
#endif
|
||||
}else if( strcmp(z,"-readonly")==0 ){
|
||||
data.openMode = SHELL_OPEN_READONLY;
|
||||
}else if( strcmp(z,"-reuseschema")==0 ){
|
||||
data.openMode = SHELL_OPEN_REUSESCHEMA;
|
||||
}else if( strcmp(z,"-ascii")==0 ){
|
||||
data.mode = MODE_Ascii;
|
||||
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
|
||||
|
||||
+2
-3
@@ -567,8 +567,6 @@ int sqlite3_exec(
|
||||
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
|
||||
|
||||
/* Reserved: 0x00F00000 */
|
||||
#define SQLITE_OPEN_REUSE_SCHEMA 0x01000000 /* Ok for sqlite3_open_v2() */
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Device Characteristics
|
||||
@@ -3635,7 +3633,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
|
||||
** representation of the SQL statement should be calculated and then
|
||||
** associated with the prepared statement, which can be obtained via
|
||||
** the [sqlite3_normalized_sql()] interface. The semantics used to
|
||||
** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
|
||||
** normalize a SQL statement are unspecified and subject to change.
|
||||
** At a minimum, literal values will be replaced with suitable
|
||||
** placeholders.
|
||||
@@ -7244,6 +7242,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
|
||||
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
||||
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
|
||||
|
||||
+39
-44
@@ -1059,11 +1059,6 @@ struct BusyHandler {
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
|
||||
|
||||
/*
|
||||
** The static mutex with which to protect reusable schemas.
|
||||
*/
|
||||
#define SQLITE_MUTEX_SCHEMA_REUSE SQLITE_MUTEX_STATIC_APP1
|
||||
|
||||
/*
|
||||
** Forward references to structures
|
||||
*/
|
||||
@@ -1238,10 +1233,6 @@ struct Schema {
|
||||
u8 enc; /* Text encoding used by this database */
|
||||
u16 schemaFlags; /* Flags associated with this schema */
|
||||
int cache_size; /* Number of pages to use in the cache */
|
||||
|
||||
int nRef; /* Number of connections using this schema */
|
||||
u64 cksum; /* Checksum for this database schema */
|
||||
Schema *pNext; /* Next schema in shared schema list */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1365,10 +1356,13 @@ void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
|
||||
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
|
||||
** in the style of sqlite3_trace()
|
||||
*/
|
||||
#define SQLITE_TRACE_LEGACY 0x80
|
||||
#define SQLITE_TRACE_LEGACY 0x40 /* Use the legacy xTrace */
|
||||
#define SQLITE_TRACE_XPROFILE 0x80 /* Use the legacy xProfile */
|
||||
#else
|
||||
#define SQLITE_TRACE_LEGACY 0
|
||||
#define SQLITE_TRACE_LEGACY 0
|
||||
#define SQLITE_TRACE_XPROFILE 0
|
||||
#endif /* SQLITE_OMIT_DEPRECATED */
|
||||
#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
|
||||
|
||||
|
||||
/*
|
||||
@@ -1427,8 +1421,10 @@ struct sqlite3 {
|
||||
void **aExtension; /* Array of shared library handles */
|
||||
int (*xTrace)(u32,void*,void*,void*); /* Trace function */
|
||||
void *pTraceArg; /* Argument to the trace function */
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
void (*xProfile)(void*,const char*,u64); /* Profiling function */
|
||||
void *pProfileArg; /* Argument to profile function */
|
||||
#endif
|
||||
void *pCommitArg; /* Argument to xCommitCallback() */
|
||||
int (*xCommitCallback)(void*); /* Invoked at every commit. */
|
||||
void *pRollbackArg; /* Argument to xRollbackCallback() */
|
||||
@@ -1692,8 +1688,9 @@ struct FuncDestructor {
|
||||
** single query - might change over time */
|
||||
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
|
||||
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
|
||||
#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */
|
||||
#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
|
||||
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
|
||||
#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
|
||||
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
|
||||
|
||||
/*
|
||||
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
|
||||
@@ -1769,10 +1766,13 @@ struct FuncDestructor {
|
||||
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
|
||||
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
|
||||
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
|
||||
|
||||
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
|
||||
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
|
||||
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
|
||||
#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
|
||||
{nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
|
||||
0, 0, xFunc, 0, 0, 0, #zName, {0} }
|
||||
|
||||
|
||||
/*
|
||||
** All current savepoints are stored in a linked list starting at
|
||||
@@ -1941,8 +1941,7 @@ struct CollSeq {
|
||||
** the first argument.
|
||||
*/
|
||||
struct VTable {
|
||||
sqlite3 *db; /* Database that owns this virtual table */
|
||||
Btree *pBt; /* Btree backend associated with this table */
|
||||
sqlite3 *db; /* Database connection associated with this table */
|
||||
Module *pMod; /* Pointer to module implementation */
|
||||
sqlite3_vtab *pVtab; /* Pointer to vtab instance */
|
||||
int nRef; /* Number of pointers to this structure */
|
||||
@@ -3009,7 +3008,6 @@ struct AutoincInfo {
|
||||
struct TriggerPrg {
|
||||
Trigger *pTrigger; /* Trigger this program was coded from */
|
||||
TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */
|
||||
int iFixDb; /* Value of Parse.iFixDb when this was coded */
|
||||
SubProgram *pProgram; /* Program implementing pTrigger/orconf */
|
||||
int orconf; /* Default ON CONFLICT policy */
|
||||
u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */
|
||||
@@ -3138,7 +3136,7 @@ struct Parse {
|
||||
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
Token sArg; /* Complete text of a module argument */
|
||||
VTable **apVtabLock; /* Pointer to virtual tables needing locking */
|
||||
Table **apVtabLock; /* Pointer to virtual tables needing locking */
|
||||
#endif
|
||||
Table *pZombieTab; /* List of Table objects to delete after code gen */
|
||||
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
|
||||
@@ -3147,7 +3145,6 @@ struct Parse {
|
||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
|
||||
#endif
|
||||
int iFixDb;
|
||||
};
|
||||
|
||||
#define PARSE_MODE_NORMAL 0
|
||||
@@ -3426,6 +3423,7 @@ struct Sqlite3Config {
|
||||
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
||||
#endif
|
||||
int bLocaltimeFault; /* True to fail localtime() calls */
|
||||
int bInternalFunctions; /* Internal SQL functions are visible */
|
||||
int iOnceResetThreshold; /* When to reset OP_Once counters */
|
||||
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
|
||||
};
|
||||
@@ -3899,9 +3897,9 @@ int sqlite3RowSetNext(RowSet*, i64*);
|
||||
void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
int sqlite3ViewGetColumnNames(Parse*,int,Table*);
|
||||
int sqlite3ViewGetColumnNames(Parse*,Table*);
|
||||
#else
|
||||
# define sqlite3ViewGetColumnNames(A,B,C) 0
|
||||
# define sqlite3ViewGetColumnNames(A,B) 0
|
||||
#endif
|
||||
|
||||
#if SQLITE_MAX_ATTACHED>30
|
||||
@@ -4033,12 +4031,12 @@ int sqlite3IsRowid(const char*);
|
||||
int sqlite3IsRowidN(const char*, int);
|
||||
#endif
|
||||
void sqlite3GenerateRowDelete(
|
||||
Parse*,int,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
|
||||
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
|
||||
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
|
||||
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
|
||||
void sqlite3ResolvePartIdxLabel(Parse*,int);
|
||||
int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
|
||||
void sqlite3GenerateConstraintChecks(Parse*,int,Table*,int*,int,int,int,int,
|
||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
||||
u8,u8,int,int*,int*,Upsert*);
|
||||
#ifdef SQLITE_ENABLE_NULL_TRIM
|
||||
void sqlite3SetMakeRecordP5(Vdbe*,Table*);
|
||||
@@ -4046,7 +4044,7 @@ void sqlite3GenerateConstraintChecks(Parse*,int,Table*,int*,int,int,int,int,
|
||||
# define sqlite3SetMakeRecordP5(A,B)
|
||||
#endif
|
||||
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
|
||||
int sqlite3OpenTableAndIndices(Parse*, int, Table*, int, u8, int,u8*,int*,int*);
|
||||
int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
|
||||
void sqlite3BeginWriteOperation(Parse*, int, int);
|
||||
void sqlite3MultiWrite(Parse*);
|
||||
void sqlite3MayAbort(Parse*);
|
||||
@@ -4071,7 +4069,7 @@ int sqlite3SafetyCheckSickOrOk(sqlite3*);
|
||||
void sqlite3ChangeCookie(Parse*, int);
|
||||
|
||||
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
void sqlite3MaterializeView(Parse*, int, Table*, Expr*, ExprList*,Expr*,int);
|
||||
void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
@@ -4082,9 +4080,9 @@ void sqlite3MaterializeView(Parse*, int, Table*, Expr*, ExprList*,Expr*,int);
|
||||
void sqlite3DropTriggerPtr(Parse*, Trigger*);
|
||||
Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask);
|
||||
Trigger *sqlite3TriggerList(Parse *, Table *);
|
||||
void sqlite3CodeRowTrigger(Parse*, int, Trigger *, int, ExprList*, int,
|
||||
Table *, int, int, int);
|
||||
void sqlite3CodeRowTriggerDirect(Parse*, int, Trigger*, Table*, int, int,int);
|
||||
void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
|
||||
int, int, int);
|
||||
void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
|
||||
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
|
||||
void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
|
||||
TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
|
||||
@@ -4098,7 +4096,7 @@ void sqlite3MaterializeView(Parse*, int, Table*, Expr*, ExprList*,Expr*,int);
|
||||
const char*,const char*);
|
||||
void sqlite3DeleteTrigger(sqlite3*, Trigger*);
|
||||
void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
|
||||
u32 sqlite3TriggerColmask(Parse*,int,Trigger*,ExprList*,int,int,Table*,int);
|
||||
u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
|
||||
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
|
||||
# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
|
||||
#else
|
||||
@@ -4106,12 +4104,12 @@ void sqlite3MaterializeView(Parse*, int, Table*, Expr*, ExprList*,Expr*,int);
|
||||
# define sqlite3DeleteTrigger(A,B)
|
||||
# define sqlite3DropTriggerPtr(A,B)
|
||||
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
|
||||
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J)
|
||||
# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F,G)
|
||||
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I)
|
||||
# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
|
||||
# define sqlite3TriggerList(X, Y) 0
|
||||
# define sqlite3ParseToplevel(p) p
|
||||
# define sqlite3IsToplevel(p) 1
|
||||
# define sqlite3TriggerColmask(A,B,C,D,E,F,G,H) 0
|
||||
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
|
||||
#endif
|
||||
|
||||
int sqlite3JoinType(Parse*, Token*, Token*, Token*);
|
||||
@@ -4298,11 +4296,8 @@ void sqlite3DefaultRowEst(Index*);
|
||||
void sqlite3RegisterLikeFunctions(sqlite3*, int);
|
||||
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
|
||||
void sqlite3SchemaClear(void *);
|
||||
void sqlite3SchemaUnuse(sqlite3*, int);
|
||||
void sqlite3SchemaReuse(sqlite3*, int);
|
||||
void sqlite3SchemaWritable(Parse*, int);
|
||||
Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
|
||||
int sqlite3SchemaToIndex(sqlite3 *db, Schema *, const char*);
|
||||
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
|
||||
KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
|
||||
void sqlite3KeyInfoUnref(KeyInfo*);
|
||||
KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
|
||||
@@ -4390,7 +4385,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
|
||||
# define sqlite3VtabUnlock(X)
|
||||
# define sqlite3VtabUnlockList(X)
|
||||
# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
|
||||
# define sqlite3GetVTable(X,Y,Z) ((VTable*)0)
|
||||
# define sqlite3GetVTable(X,Y) ((VTable*)0)
|
||||
#else
|
||||
void sqlite3VtabClear(sqlite3 *db, Table*);
|
||||
void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
|
||||
@@ -4402,7 +4397,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
|
||||
void sqlite3VtabUnlockList(sqlite3*);
|
||||
int sqlite3VtabSavepoint(sqlite3 *, int, int);
|
||||
void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
|
||||
VTable *sqlite3GetVTable(sqlite3*, int, Table*);
|
||||
VTable *sqlite3GetVTable(sqlite3*, Table*);
|
||||
Module *sqlite3VtabCreateModule(
|
||||
sqlite3*,
|
||||
const char*,
|
||||
@@ -4414,13 +4409,13 @@ void sqlite3AutoLoadExtensions(sqlite3*);
|
||||
#endif
|
||||
int sqlite3VtabEponymousTableInit(Parse*,Module*);
|
||||
void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
|
||||
void sqlite3VtabMakeWritable(Parse*,int,Table*);
|
||||
void sqlite3VtabMakeWritable(Parse*,Table*);
|
||||
void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
|
||||
void sqlite3VtabFinishParse(Parse*, Token*);
|
||||
void sqlite3VtabArgInit(Parse*);
|
||||
void sqlite3VtabArgExtend(Parse*, Token*);
|
||||
int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
|
||||
int sqlite3VtabCallConnect(Parse*, int, Table*);
|
||||
int sqlite3VtabCallConnect(Parse*, Table*);
|
||||
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
||||
int sqlite3VtabBegin(sqlite3 *, VTable *);
|
||||
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
|
||||
@@ -4469,15 +4464,15 @@ const char *sqlite3JournalModename(int);
|
||||
** provided (enforcement of FK constraints requires the triggers sub-system).
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
void sqlite3FkCheck(Parse*, int, Table*, int, int, int*, int);
|
||||
void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
|
||||
void sqlite3FkDropTable(Parse*, SrcList *, Table*);
|
||||
void sqlite3FkActions(Parse*, int, Table*, ExprList*, int, int*, int);
|
||||
void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
|
||||
int sqlite3FkRequired(Parse*, Table*, int*, int);
|
||||
u32 sqlite3FkOldmask(Parse*, Table*);
|
||||
FKey *sqlite3FkReferences(Table *);
|
||||
#else
|
||||
#define sqlite3FkActions(a,b,c,d,e,f,g)
|
||||
#define sqlite3FkCheck(a,b,c,d,e,f,g)
|
||||
#define sqlite3FkActions(a,b,c,d,e,f)
|
||||
#define sqlite3FkCheck(a,b,c,d,e,f)
|
||||
#define sqlite3FkDropTable(a,b,c)
|
||||
#define sqlite3FkOldmask(a,b) 0
|
||||
#define sqlite3FkRequired(a,b,c,d) 0
|
||||
|
||||
@@ -282,7 +282,6 @@ int sqlite3_db_status(
|
||||
Schema *pSchema = db->aDb[i].pSchema;
|
||||
if( ALWAYS(pSchema!=0) ){
|
||||
HashElem *p;
|
||||
int nStart = nByte;
|
||||
|
||||
nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
|
||||
pSchema->tblHash.count
|
||||
@@ -301,9 +300,6 @@ int sqlite3_db_status(
|
||||
for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
|
||||
sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
|
||||
}
|
||||
if( pSchema->nRef>1 ){
|
||||
nByte -= (nByte - nStart)*(pSchema->nRef-1)/pSchema->nRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
db->pnBytesFreed = 0;
|
||||
|
||||
@@ -3443,7 +3443,6 @@ static int sqliteCmdUsage(
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
|
||||
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
||||
" ?-reuse-schema BOOLEAN?"
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
||||
" ?-key CODECKEY?"
|
||||
#endif
|
||||
@@ -3578,14 +3577,6 @@ static int SQLITE_TCLAPI DbMain(
|
||||
}else{
|
||||
flags &= ~SQLITE_OPEN_URI;
|
||||
}
|
||||
}else if( strcmp(zArg, "-reuse-schema")==0 ){
|
||||
int b;
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
||||
if( b ){
|
||||
flags |= SQLITE_OPEN_REUSE_SCHEMA;
|
||||
}else{
|
||||
flags &= ~SQLITE_OPEN_REUSE_SCHEMA;
|
||||
}
|
||||
}else{
|
||||
Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
|
||||
return TCL_ERROR;
|
||||
|
||||
+10
-7
@@ -6329,7 +6329,7 @@ static int SQLITE_TCLAPI reset_prng_state(
|
||||
/*
|
||||
** tclcmd: database_may_be_corrupt
|
||||
**
|
||||
** Indicate that database files might be corrupt. In other words, set the normal
|
||||
** Indicate that database files might be corrupt. In other words, set the normal
|
||||
** state of operation.
|
||||
*/
|
||||
static int SQLITE_TCLAPI database_may_be_corrupt(
|
||||
@@ -6344,8 +6344,9 @@ static int SQLITE_TCLAPI database_may_be_corrupt(
|
||||
/*
|
||||
** tclcmd: database_never_corrupt
|
||||
**
|
||||
** Indicate that database files are always well-formed. This enables extra assert()
|
||||
** statements that test conditions that are always true for well-formed databases.
|
||||
** Indicate that database files are always well-formed. This enables
|
||||
** extra assert() statements that test conditions that are always true
|
||||
** for well-formed databases.
|
||||
*/
|
||||
static int SQLITE_TCLAPI database_never_corrupt(
|
||||
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
||||
@@ -6711,9 +6712,10 @@ static int SQLITE_TCLAPI test_test_control(
|
||||
const char *zName;
|
||||
int i;
|
||||
} aVerb[] = {
|
||||
{ "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
|
||||
{ "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
|
||||
{ "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
|
||||
{ "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
|
||||
{ "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
|
||||
{ "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
|
||||
{ "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS},
|
||||
};
|
||||
int iVerb;
|
||||
int iFlag;
|
||||
@@ -6731,6 +6733,7 @@ static int SQLITE_TCLAPI test_test_control(
|
||||
|
||||
iFlag = aVerb[iVerb].i;
|
||||
switch( iFlag ){
|
||||
case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
|
||||
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
|
||||
int val;
|
||||
if( objc!=3 ){
|
||||
@@ -6738,7 +6741,7 @@ static int SQLITE_TCLAPI test_test_control(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
|
||||
sqlite3_test_control(iFlag, val);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+23
-30
@@ -215,7 +215,7 @@ void sqlite3BeginTrigger(
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( !IN_RENAME_OBJECT ){
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0);
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
int code = SQLITE_CREATE_TRIGGER;
|
||||
const char *zDb = db->aDb[iTabDb].zDbSName;
|
||||
const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb;
|
||||
@@ -291,7 +291,7 @@ void sqlite3FinishTrigger(
|
||||
pParse->pNewTrigger = 0;
|
||||
if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
|
||||
zName = pTrig->zName;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
|
||||
pTrig->step_list = pStepList;
|
||||
while( pStepList ){
|
||||
pStepList->pTrig = pTrig;
|
||||
@@ -332,7 +332,7 @@ void sqlite3FinishTrigger(
|
||||
pTrig->table, z);
|
||||
sqlite3DbFree(db, z);
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb,
|
||||
sqlite3VdbeAddParseSchemaOp(v, iDb,
|
||||
sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
|
||||
}
|
||||
|
||||
@@ -610,9 +610,8 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb;
|
||||
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
pTable = tableOfTrigger(pTrigger);
|
||||
assert( pTable );
|
||||
assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
|
||||
@@ -729,12 +728,20 @@ static SrcList *targetSrcList(
|
||||
TriggerStep *pStep /* The trigger containing the target token */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb; /* Index of the database to use */
|
||||
SrcList *pSrc; /* SrcList to be returned */
|
||||
|
||||
pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
|
||||
if( pSrc ){
|
||||
assert( pSrc->nSrc>0 );
|
||||
pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
|
||||
iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
|
||||
if( iDb==0 || iDb>=2 ){
|
||||
const char *zDb;
|
||||
assert( iDb<db->nDb );
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb);
|
||||
}
|
||||
}
|
||||
return pSrc;
|
||||
}
|
||||
@@ -896,7 +903,6 @@ static TriggerPrg *codeRowTrigger(
|
||||
pPrg->orconf = orconf;
|
||||
pPrg->aColmask[0] = 0xffffffff;
|
||||
pPrg->aColmask[1] = 0xffffffff;
|
||||
pPrg->iFixDb = pParse->iFixDb;
|
||||
|
||||
/* Allocate and populate a new Parse context to use for coding the
|
||||
** trigger sub-program. */
|
||||
@@ -910,12 +916,11 @@ static TriggerPrg *codeRowTrigger(
|
||||
pSubParse->zAuthContext = pTrigger->zName;
|
||||
pSubParse->eTriggerOp = pTrigger->op;
|
||||
pSubParse->nQueryLoop = pParse->nQueryLoop;
|
||||
pSubParse->iFixDb = pParse->iFixDb;
|
||||
|
||||
v = sqlite3GetVdbe(pSubParse);
|
||||
if( v ){
|
||||
VdbeComment((v, "Start: %s.%s (%d) (%s %s%s%s ON %s)",
|
||||
pTrigger->zName, onErrorText(orconf), pParse->iFixDb-1,
|
||||
VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
|
||||
pTrigger->zName, onErrorText(orconf),
|
||||
(pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
|
||||
(pTrigger->op==TK_UPDATE ? "UPDATE" : ""),
|
||||
(pTrigger->op==TK_INSERT ? "INSERT" : ""),
|
||||
@@ -961,7 +966,6 @@ static TriggerPrg *codeRowTrigger(
|
||||
pProgram->nMem = pSubParse->nMem;
|
||||
pProgram->nCsr = pSubParse->nTab;
|
||||
pProgram->token = (void *)pTrigger;
|
||||
pProgram->itoken = pParse->iFixDb;
|
||||
pPrg->aColmask[0] = pSubParse->oldmask;
|
||||
pPrg->aColmask[1] = pSubParse->newmask;
|
||||
sqlite3VdbeDelete(v);
|
||||
@@ -983,15 +987,12 @@ static TriggerPrg *codeRowTrigger(
|
||||
*/
|
||||
static TriggerPrg *getRowTrigger(
|
||||
Parse *pParse, /* Current parse context */
|
||||
int iDb, /* Database containing pTab */
|
||||
Trigger *pTrigger, /* Trigger to code */
|
||||
Table *pTab, /* The table trigger pTrigger is attached to */
|
||||
int orconf /* ON CONFLICT algorithm. */
|
||||
){
|
||||
Parse *pRoot = sqlite3ParseToplevel(pParse);
|
||||
TriggerPrg *pPrg;
|
||||
int iFixDb = pParse->iFixDb;
|
||||
pParse->iFixDb = (pTrigger->pSchema==pRoot->db->aDb[1].pSchema)?0:(iDb+1);
|
||||
|
||||
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
|
||||
|
||||
@@ -999,19 +1000,16 @@ static TriggerPrg *getRowTrigger(
|
||||
** process of being coded). If this is the case, then an entry with
|
||||
** a matching TriggerPrg.pTrigger field will be present somewhere
|
||||
** in the Parse.pTriggerPrg list. Search for such an entry. */
|
||||
for(pPrg=pRoot->pTriggerPrg; pPrg; pPrg=pPrg->pNext){
|
||||
if( pPrg->pTrigger==pTrigger
|
||||
&& pPrg->orconf==orconf
|
||||
&& pParse->iFixDb==pPrg->iFixDb
|
||||
) break;
|
||||
}
|
||||
for(pPrg=pRoot->pTriggerPrg;
|
||||
pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf);
|
||||
pPrg=pPrg->pNext
|
||||
);
|
||||
|
||||
/* If an existing TriggerPrg could not be located, create a new one. */
|
||||
if( !pPrg ){
|
||||
pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf);
|
||||
}
|
||||
|
||||
pParse->iFixDb = iFixDb;
|
||||
return pPrg;
|
||||
}
|
||||
|
||||
@@ -1023,7 +1021,6 @@ static TriggerPrg *getRowTrigger(
|
||||
*/
|
||||
void sqlite3CodeRowTriggerDirect(
|
||||
Parse *pParse, /* Parse context */
|
||||
int iDb, /* Database containing pTrigger */
|
||||
Trigger *p, /* Trigger to code */
|
||||
Table *pTab, /* The table to code triggers from */
|
||||
int reg, /* Reg array containing OLD.* and NEW.* values */
|
||||
@@ -1032,8 +1029,7 @@ void sqlite3CodeRowTriggerDirect(
|
||||
){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
|
||||
TriggerPrg *pPrg;
|
||||
|
||||
pPrg = getRowTrigger(pParse, iDb, p, pTab, orconf);
|
||||
pPrg = getRowTrigger(pParse, p, pTab, orconf);
|
||||
assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
|
||||
|
||||
/* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
|
||||
@@ -1043,9 +1039,8 @@ void sqlite3CodeRowTriggerDirect(
|
||||
|
||||
sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem,
|
||||
(const char *)pPrg->pProgram, P4_SUBPROGRAM);
|
||||
VdbeComment((v, "Call: %s.%s (%d)",
|
||||
(p->zName?p->zName:"fkey"), onErrorText(orconf), iDb
|
||||
));
|
||||
VdbeComment(
|
||||
(v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf)));
|
||||
|
||||
/* Set the P5 operand of the OP_Program instruction to non-zero if
|
||||
** recursive invocation of this trigger program is disallowed. Recursive
|
||||
@@ -1098,7 +1093,6 @@ void sqlite3CodeRowTriggerDirect(
|
||||
*/
|
||||
void sqlite3CodeRowTrigger(
|
||||
Parse *pParse, /* Parse context */
|
||||
int iDb,
|
||||
Trigger *pTrigger, /* List of triggers on table pTab */
|
||||
int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
|
||||
ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
|
||||
@@ -1129,7 +1123,7 @@ void sqlite3CodeRowTrigger(
|
||||
&& p->tr_tm==tr_tm
|
||||
&& checkColumnOverlap(p->pColumns, pChanges)
|
||||
){
|
||||
sqlite3CodeRowTriggerDirect(pParse, iDb, p, pTab, reg, orconf,ignoreJump);
|
||||
sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1161,7 +1155,6 @@ void sqlite3CodeRowTrigger(
|
||||
*/
|
||||
u32 sqlite3TriggerColmask(
|
||||
Parse *pParse, /* Parse context */
|
||||
int iDb,
|
||||
Trigger *pTrigger, /* List of triggers on table pTab */
|
||||
ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
|
||||
int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */
|
||||
@@ -1179,7 +1172,7 @@ u32 sqlite3TriggerColmask(
|
||||
&& checkColumnOverlap(p->pColumns,pChanges)
|
||||
){
|
||||
TriggerPrg *pPrg;
|
||||
pPrg = getRowTrigger(pParse, iDb, p, pTab, orconf);
|
||||
pPrg = getRowTrigger(pParse, p, pTab, orconf);
|
||||
if( pPrg ){
|
||||
mask |= pPrg->aColmask[isNew];
|
||||
}
|
||||
|
||||
+17
-19
@@ -18,7 +18,6 @@
|
||||
/* Forward declaration */
|
||||
static void updateVirtualTable(
|
||||
Parse *pParse, /* The parsing context */
|
||||
int iDb,
|
||||
SrcList *pSrc, /* The virtual table to be modified */
|
||||
Table *pTab, /* The virtual table */
|
||||
ExprList *pChanges, /* The columns to change in the UPDATE statement */
|
||||
@@ -212,7 +211,7 @@ void sqlite3Update(
|
||||
*/
|
||||
pTab = sqlite3SrcListLookup(pParse, pTabList);
|
||||
if( pTab==0 ) goto update_cleanup;
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pTabList->a[0].zDatabase);
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
|
||||
/* Figure out if we have any triggers and if the table being
|
||||
** updated is a view.
|
||||
@@ -241,7 +240,7 @@ void sqlite3Update(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3ViewGetColumnNames(pParse, iDb, pTab) ){
|
||||
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
|
||||
goto update_cleanup;
|
||||
}
|
||||
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
|
||||
@@ -417,7 +416,7 @@ void sqlite3Update(
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
if( isView ){
|
||||
sqlite3MaterializeView(pParse, iDb, pTab,
|
||||
sqlite3MaterializeView(pParse, pTab,
|
||||
pWhere, pOrderBy, pLimit, iDataCur
|
||||
);
|
||||
pOrderBy = 0;
|
||||
@@ -435,7 +434,7 @@ void sqlite3Update(
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Virtual tables must be handled separately */
|
||||
if( IsVirtual(pTab) ){
|
||||
updateVirtualTable(pParse, iDb, pTabList, pTab, pChanges, pRowidExpr, aXRef,
|
||||
updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
|
||||
pWhere, onError);
|
||||
goto update_cleanup;
|
||||
}
|
||||
@@ -564,7 +563,7 @@ void sqlite3Update(
|
||||
if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){
|
||||
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
}
|
||||
sqlite3OpenTableAndIndices(pParse, iDb, pTab, OP_OpenWrite, 0, iBaseCur,
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur,
|
||||
aToOpen, 0, 0);
|
||||
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
|
||||
}
|
||||
@@ -611,7 +610,7 @@ void sqlite3Update(
|
||||
** information is needed */
|
||||
if( chngPk || hasFK || pTrigger ){
|
||||
u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
|
||||
oldmask |= sqlite3TriggerColmask(pParse, iDb,
|
||||
oldmask |= sqlite3TriggerColmask(pParse,
|
||||
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
|
||||
);
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
@@ -644,7 +643,7 @@ void sqlite3Update(
|
||||
** be used eliminates some redundant opcodes.
|
||||
*/
|
||||
newmask = sqlite3TriggerColmask(
|
||||
pParse, iDb, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
|
||||
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
|
||||
);
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( i==pTab->iPKey ){
|
||||
@@ -673,7 +672,7 @@ void sqlite3Update(
|
||||
*/
|
||||
if( tmask&TRIGGER_BEFORE ){
|
||||
sqlite3TableAffinity(v, pTab, regNew);
|
||||
sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_UPDATE, pChanges,
|
||||
sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
|
||||
TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue);
|
||||
|
||||
/* The row-trigger may have deleted the row being updated. In this
|
||||
@@ -711,13 +710,13 @@ void sqlite3Update(
|
||||
|
||||
/* Do constraint checks. */
|
||||
assert( regOldRowid>0 );
|
||||
sqlite3GenerateConstraintChecks(pParse, iDb, pTab, aRegIdx, iDataCur,
|
||||
iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue,
|
||||
&bReplace, aXRef, 0);
|
||||
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
|
||||
regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,
|
||||
aXRef, 0);
|
||||
|
||||
/* Do FK constraint checks. */
|
||||
if( hasFK ){
|
||||
sqlite3FkCheck(pParse, iDb, pTab, regOldRowid, 0, aXRef, chngKey);
|
||||
sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
|
||||
}
|
||||
|
||||
/* Delete the index entries associated with the current record. */
|
||||
@@ -763,7 +762,7 @@ void sqlite3Update(
|
||||
}
|
||||
|
||||
if( hasFK ){
|
||||
sqlite3FkCheck(pParse, iDb, pTab, 0, regNewRowid, aXRef, chngKey);
|
||||
sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);
|
||||
}
|
||||
|
||||
/* Insert the new index entries and the new record. */
|
||||
@@ -777,7 +776,7 @@ void sqlite3Update(
|
||||
** handle rows (possibly in other tables) that refer via a foreign key
|
||||
** to the row just updated. */
|
||||
if( hasFK ){
|
||||
sqlite3FkActions(pParse, iDb, pTab, pChanges, regOldRowid, aXRef,chngKey);
|
||||
sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -787,7 +786,7 @@ void sqlite3Update(
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
|
||||
}
|
||||
|
||||
sqlite3CodeRowTrigger(pParse, iDb, pTrigger, TK_UPDATE, pChanges,
|
||||
sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
|
||||
TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue);
|
||||
|
||||
/* Repeat the above with the next record to be updated, until
|
||||
@@ -870,7 +869,6 @@ update_cleanup:
|
||||
*/
|
||||
static void updateVirtualTable(
|
||||
Parse *pParse, /* The parsing context */
|
||||
int iDb,
|
||||
SrcList *pSrc, /* The virtual table to be modified */
|
||||
Table *pTab, /* The virtual table */
|
||||
ExprList *pChanges, /* The columns to change in the UPDATE statement */
|
||||
@@ -883,7 +881,7 @@ static void updateVirtualTable(
|
||||
int ephemTab; /* Table holding the result of the SELECT */
|
||||
int i; /* Loop counter */
|
||||
sqlite3 *db = pParse->db; /* Database connection */
|
||||
const char *pVTab = (const char*)sqlite3GetVTable(db, iDb, pTab);
|
||||
const char *pVTab = (const char*)sqlite3GetVTable(db, pTab);
|
||||
WhereInfo *pWInfo;
|
||||
int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */
|
||||
int regArg; /* First register in VUpdate arg array */
|
||||
@@ -974,7 +972,7 @@ static void updateVirtualTable(
|
||||
sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i);
|
||||
}
|
||||
}
|
||||
sqlite3VtabMakeWritable(pParse, iDb, pTab);
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
|
||||
sqlite3MayAbort(pParse);
|
||||
|
||||
@@ -123,7 +123,6 @@ void sqlite3Vacuum(Parse *pParse, Token *pNm){
|
||||
#endif
|
||||
}
|
||||
if( iDb!=1 ){
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
sqlite3VdbeAddOp1(v, OP_Vacuum, iDb);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
}
|
||||
|
||||
+1
-6
@@ -6038,7 +6038,6 @@ case OP_Program: { /* jump */
|
||||
VdbeFrame *pFrame; /* New vdbe frame to execute in */
|
||||
SubProgram *pProgram; /* Sub-program to execute */
|
||||
void *t; /* Token identifying trigger */
|
||||
int i; /* Second part of token identifying trigger */
|
||||
|
||||
pProgram = pOp->p4.pProgram;
|
||||
pRt = &aMem[pOp->p3];
|
||||
@@ -6057,10 +6056,7 @@ case OP_Program: { /* jump */
|
||||
** variable. */
|
||||
if( pOp->p5 ){
|
||||
t = pProgram->token;
|
||||
i = pProgram->itoken;
|
||||
for(pFrame=p->pFrame;
|
||||
pFrame && (pFrame->token!=t || pFrame->itoken!=i);
|
||||
pFrame=pFrame->pParent);
|
||||
for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
|
||||
if( pFrame ) break;
|
||||
}
|
||||
|
||||
@@ -6108,7 +6104,6 @@ case OP_Program: { /* jump */
|
||||
pFrame->aOp = p->aOp;
|
||||
pFrame->nOp = p->nOp;
|
||||
pFrame->token = pProgram->token;
|
||||
pFrame->itoken = pProgram->itoken;
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
pFrame->anExec = p->anExec;
|
||||
#endif
|
||||
|
||||
+1
-2
@@ -90,7 +90,6 @@ struct SubProgram {
|
||||
int nCsr; /* Number of cursors required */
|
||||
u8 *aOnce; /* Array of OP_Once flags */
|
||||
void *token; /* id that may be used to recursive triggers */
|
||||
int itoken; /* Second part of id to identify rec. trig. */
|
||||
SubProgram *pNext; /* Next sub-program already visited */
|
||||
};
|
||||
|
||||
@@ -217,7 +216,7 @@ VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
|
||||
# define ExplainQueryPlanPop(P)
|
||||
# define ExplainQueryPlanParent(P) 0
|
||||
#endif
|
||||
void sqlite3VdbeAddParseSchemaOp(Parse*,int,char*);
|
||||
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
|
||||
void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
|
||||
void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
|
||||
void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
|
||||
|
||||
@@ -167,7 +167,6 @@ struct VdbeFrame {
|
||||
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
|
||||
u8 *aOnce; /* Bitmask used by OP_Once */
|
||||
void *token; /* Copy of SubProgram.token */
|
||||
int itoken; /* Copy of SubProgram.itoken */
|
||||
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
|
||||
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
||||
#if SQLITE_DEBUG
|
||||
|
||||
+13
-9
@@ -62,14 +62,16 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
|
||||
sqlite3_int64 iNow;
|
||||
sqlite3_int64 iElapse;
|
||||
assert( p->startTime>0 );
|
||||
assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 );
|
||||
assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
|
||||
assert( db->init.busy==0 );
|
||||
assert( p->zSql!=0 );
|
||||
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
|
||||
iElapse = (iNow - p->startTime)*1000000;
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
if( db->xProfile ){
|
||||
db->xProfile(db->pProfileArg, p->zSql, iElapse);
|
||||
}
|
||||
#endif
|
||||
if( db->mTrace & SQLITE_TRACE_PROFILE ){
|
||||
db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
|
||||
}
|
||||
@@ -602,7 +604,7 @@ static int sqlite3Step(Vdbe *p){
|
||||
);
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0)
|
||||
if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
|
||||
&& !db->init.busy && p->zSql ){
|
||||
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
|
||||
}else{
|
||||
@@ -629,16 +631,18 @@ static int sqlite3Step(Vdbe *p){
|
||||
db->nVdbeExec--;
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_ROW ){
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
/* If the statement completed successfully, invoke the profile callback */
|
||||
if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
|
||||
/* If the statement completed successfully, invoke the profile callback */
|
||||
checkProfileCallback(db, p);
|
||||
#endif
|
||||
|
||||
if( rc==SQLITE_DONE && db->autoCommit ){
|
||||
assert( p->rc==SQLITE_OK );
|
||||
p->rc = doWalCallbacks(db);
|
||||
if( p->rc!=SQLITE_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
if( rc==SQLITE_DONE && db->autoCommit ){
|
||||
assert( p->rc==SQLITE_OK );
|
||||
p->rc = doWalCallbacks(db);
|
||||
if( p->rc!=SQLITE_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -358,10 +358,8 @@ void sqlite3VdbeExplainPop(Parse *pParse){
|
||||
** The zWhere string must have been obtained from sqlite3_malloc().
|
||||
** This routine will take ownership of the allocated memory.
|
||||
*/
|
||||
void sqlite3VdbeAddParseSchemaOp(Parse *pParse, int iDb, char *zWhere){
|
||||
Vdbe *p = pParse->pVdbe;
|
||||
void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
|
||||
int j;
|
||||
sqlite3SchemaWritable(pParse, iDb);
|
||||
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
|
||||
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
|
||||
}
|
||||
|
||||
+2
-2
@@ -183,7 +183,7 @@ int sqlite3_blob_open(
|
||||
goto blob_open_out;
|
||||
}
|
||||
pBlob->pTab = pTab;
|
||||
pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db,pTab->pSchema,zDb)].zDbSName;
|
||||
pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
|
||||
|
||||
/* Now search pTab for the exact column. */
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++) {
|
||||
@@ -270,7 +270,7 @@ int sqlite3_blob_open(
|
||||
{OP_Halt, 0, 0, 0}, /* 5 */
|
||||
};
|
||||
Vdbe *v = (Vdbe *)pBlob->pStmt;
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema, zDb);
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
VdbeOp *aOp;
|
||||
|
||||
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
|
||||
|
||||
+21
-29
@@ -141,15 +141,10 @@ void sqlite3VtabLock(VTable *pVTab){
|
||||
** Return a pointer to the VTable object used by connection db to access
|
||||
** this virtual-table, if one has been created, or NULL otherwise.
|
||||
*/
|
||||
VTable *sqlite3GetVTable(sqlite3 *db, int iDb, Table *pTab){
|
||||
VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
|
||||
VTable *pVtab;
|
||||
assert( IsVirtual(pTab) );
|
||||
if( iDb>=0 ){
|
||||
Btree *pBt = db->aDb[iDb].pBt;
|
||||
for(pVtab=pTab->pVTable; pVtab && pVtab->pBt!=pBt; pVtab=pVtab->pNext);
|
||||
}else{
|
||||
for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
|
||||
}
|
||||
for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
|
||||
return pVtab;
|
||||
}
|
||||
|
||||
@@ -223,19 +218,17 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
|
||||
*/
|
||||
void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
|
||||
VTable **ppVTab;
|
||||
VTable **ppNext;
|
||||
|
||||
assert( IsVirtual(p) );
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
|
||||
for(ppVTab=&p->pVTable; *ppVTab; ){
|
||||
for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
|
||||
if( (*ppVTab)->db==db ){
|
||||
VTable *pVTab = *ppVTab;
|
||||
*ppVTab = pVTab->pNext;
|
||||
sqlite3VtabUnlock(pVTab);
|
||||
}else{
|
||||
ppVTab = &(*ppVTab)->pNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,7 +356,7 @@ void sqlite3VtabBeginParse(
|
||||
** The second call, to obtain permission to create the table, is made now.
|
||||
*/
|
||||
if( pTable->azModuleArg ){
|
||||
int iDb = sqlite3SchemaToIndex(db, pTable->pSchema, 0); /* TODO */
|
||||
int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
|
||||
assert( iDb>=0 ); /* The database the table is being created in */
|
||||
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
|
||||
pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
|
||||
@@ -425,7 +418,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
||||
** entry in the sqlite_master table tht was created for this vtab
|
||||
** by sqlite3StartTable().
|
||||
*/
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, 0);
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
sqlite3NestedParse(pParse,
|
||||
"UPDATE %Q.%s "
|
||||
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
|
||||
@@ -442,7 +435,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
||||
|
||||
sqlite3VdbeAddOp0(v, OP_Expire);
|
||||
zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
|
||||
sqlite3VdbeAddParseSchemaOp(pParse, iDb, zWhere);
|
||||
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
|
||||
|
||||
iReg = ++pParse->nMem;
|
||||
sqlite3VdbeLoadString(v, iReg, pTab->zName);
|
||||
@@ -501,7 +494,6 @@ void sqlite3VtabArgExtend(Parse *pParse, Token *p){
|
||||
*/
|
||||
static int vtabCallConstructor(
|
||||
sqlite3 *db,
|
||||
int iDb, /* Database containing pTab */
|
||||
Table *pTab,
|
||||
Module *pMod,
|
||||
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
|
||||
@@ -514,6 +506,7 @@ static int vtabCallConstructor(
|
||||
int nArg = pTab->nModuleArg;
|
||||
char *zErr = 0;
|
||||
char *zModuleName;
|
||||
int iDb;
|
||||
VtabCtx *pCtx;
|
||||
|
||||
/* Check that the virtual-table is not already being initialized */
|
||||
@@ -538,9 +531,9 @@ static int vtabCallConstructor(
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
pVTable->db = db;
|
||||
pVTable->pBt = db->aDb[iDb].pBt;
|
||||
pVTable->pMod = pMod;
|
||||
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
|
||||
|
||||
/* Invoke the virtual table constructor */
|
||||
@@ -629,14 +622,14 @@ static int vtabCallConstructor(
|
||||
**
|
||||
** This call is a no-op if table pTab is not a virtual table.
|
||||
*/
|
||||
int sqlite3VtabCallConnect(Parse *pParse, int iDb, Table *pTab){
|
||||
int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
|
||||
sqlite3 *db = pParse->db;
|
||||
const char *zMod;
|
||||
Module *pMod;
|
||||
int rc;
|
||||
|
||||
assert( pTab );
|
||||
if( !IsVirtual(pTab) || sqlite3GetVTable(db, iDb, pTab) ){
|
||||
if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -650,7 +643,7 @@ int sqlite3VtabCallConnect(Parse *pParse, int iDb, Table *pTab){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
char *zErr = 0;
|
||||
rc = vtabCallConstructor(db, iDb, pTab, pMod,pMod->pModule->xConnect,&zErr);
|
||||
rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3ErrorMsg(pParse, "%s", zErr);
|
||||
pParse->rc = rc;
|
||||
@@ -721,15 +714,15 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
|
||||
*pzErr = sqlite3MPrintf(db, "no such module: %s", zMod);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = vtabCallConstructor(db, iDb, pTab, pMod, pMod->pModule->xCreate,pzErr);
|
||||
rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
|
||||
}
|
||||
|
||||
/* Justification of ALWAYS(): The xConstructor method is required to
|
||||
** create a valid sqlite3_vtab if it returns SQLITE_OK. */
|
||||
if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, iDb, pTab)) ){
|
||||
if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){
|
||||
rc = growVTrans(db);
|
||||
if( rc==SQLITE_OK ){
|
||||
addToVTrans(db, sqlite3GetVTable(db, iDb, pTab));
|
||||
addToVTrans(db, sqlite3GetVTable(db, pTab));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1062,7 +1055,7 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
pTab = pExpr->y.pTab;
|
||||
if( pTab==0 ) return pDef;
|
||||
if( !IsVirtual(pTab) ) return pDef;
|
||||
pVtab = sqlite3GetVTable(db, -1, pTab)->pVtab;
|
||||
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
|
||||
assert( pVtab!=0 );
|
||||
assert( pVtab->pModule!=0 );
|
||||
pMod = (sqlite3_module *)pVtab->pModule;
|
||||
@@ -1111,21 +1104,20 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
** array if it is missing. If pTab is already in the array, this routine
|
||||
** is a no-op.
|
||||
*/
|
||||
void sqlite3VtabMakeWritable(Parse *pParse, int iDb, Table *pTab){
|
||||
void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
|
||||
Parse *pToplevel = sqlite3ParseToplevel(pParse);
|
||||
VTable *pVTab = sqlite3GetVTable(pParse->db, iDb, pTab);
|
||||
int i, n;
|
||||
VTable **apVtabLock;
|
||||
Table **apVtabLock;
|
||||
|
||||
assert( IsVirtual(pTab) );
|
||||
for(i=0; i<pToplevel->nVtabLock; i++){
|
||||
if( pVTab==pToplevel->apVtabLock[i] ) return;
|
||||
if( pTab==pToplevel->apVtabLock[i] ) return;
|
||||
}
|
||||
n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
|
||||
apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
|
||||
if( apVtabLock ){
|
||||
pToplevel->apVtabLock = apVtabLock;
|
||||
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pVTab;
|
||||
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
|
||||
}else{
|
||||
sqlite3OomFault(pToplevel->db);
|
||||
}
|
||||
@@ -1168,7 +1160,7 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
|
||||
addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
|
||||
addModuleArgument(db, pTab, 0);
|
||||
addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName));
|
||||
rc = vtabCallConstructor(db, 0, pTab, pMod, pModule->xConnect, &zErr);
|
||||
rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
|
||||
if( rc ){
|
||||
sqlite3ErrorMsg(pParse, "%s", zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
|
||||
+5
-11
@@ -1041,14 +1041,8 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
|
||||
** that this is required.
|
||||
*/
|
||||
static int vtabBestIndex(
|
||||
Parse *pParse,
|
||||
struct SrcList_item *pSrc,
|
||||
sqlite3_index_info *p
|
||||
){
|
||||
Table *pTab = pSrc->pTab;
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema, pSrc->zDatabase);
|
||||
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, iDb, pTab)->pVtab;
|
||||
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
|
||||
int rc;
|
||||
|
||||
TRACE_IDX_INPUTS(p);
|
||||
@@ -3138,7 +3132,7 @@ static int whereLoopAddVirtualOne(
|
||||
pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
|
||||
|
||||
/* Invoke the virtual table xBestIndex() method */
|
||||
rc = vtabBestIndex(pParse, pSrc, pIdxInfo);
|
||||
rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
|
||||
if( rc ){
|
||||
if( rc==SQLITE_CONSTRAINT ){
|
||||
/* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
|
||||
@@ -4948,14 +4942,14 @@ WhereInfo *sqlite3WhereBegin(
|
||||
|
||||
pTabItem = &pTabList->a[pLevel->iFrom];
|
||||
pTab = pTabItem->pTab;
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema, pTabItem->zDatabase);
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
pLoop = pLevel->pWLoop;
|
||||
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
|
||||
/* Do nothing */
|
||||
}else
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, iDb, pTab);
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
||||
int iCur = pTabItem->iCursor;
|
||||
sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
|
||||
}else if( IsVirtual(pTab) ){
|
||||
|
||||
+1
-1
@@ -409,7 +409,7 @@ static int isAuxiliaryVtabOperator(
|
||||
sqlite3_module *pMod;
|
||||
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
|
||||
void *pNotUsed;
|
||||
pVtab = sqlite3GetVTable(db, -1, pCol->y.pTab)->pVtab;
|
||||
pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
|
||||
assert( pVtab!=0 );
|
||||
assert( pVtab->pModule!=0 );
|
||||
pMod = (sqlite3_module *)pVtab->pModule;
|
||||
|
||||
@@ -684,6 +684,7 @@ do_test alter-8.2 {
|
||||
# alter-9.X - Special test: Make sure the sqlite_rename_column() and
|
||||
# rename_table() functions do not crash when handed bad input.
|
||||
#
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_test alter-9.1 {
|
||||
execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0)}
|
||||
} {{}}
|
||||
@@ -696,6 +697,14 @@ foreach {tn sql} {
|
||||
catch { execsql $sql }
|
||||
} 1
|
||||
}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
|
||||
# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default),
|
||||
# then the sqlite_rename_table() SQL function is not accessible to ordinary SQL.
|
||||
#
|
||||
do_catchsql_test alter-9.3 {
|
||||
SELECT sqlite_rename_table(0,0,0,0,0,0,0);
|
||||
} {1 {no such function: sqlite_rename_table}}
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters
|
||||
|
||||
@@ -618,6 +618,7 @@ foreach {tn trigger error} {
|
||||
#-------------------------------------------------------------------------
|
||||
# Passing invalid parameters directly to sqlite_rename_column().
|
||||
#
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_execsql_test 14.1 {
|
||||
CREATE TABLE ddd(sql, type, object, db, tbl, icol, znew, bquote);
|
||||
INSERT INTO ddd VALUES(
|
||||
@@ -640,6 +641,15 @@ do_execsql_test 14.2 {
|
||||
sqlite_rename_column(sql, type, object, db, tbl, icol, znew, bquote, 0)
|
||||
FROM ddd;
|
||||
} {{} {} {} {}}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
|
||||
# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default)
|
||||
# then the sqlite_rename_table() SQL function is not accessible to
|
||||
# ordinary SQL.
|
||||
#
|
||||
do_catchsql_test 14.3 {
|
||||
SELECT sqlite_rename_column(0,0,0,0,0,0,0,0,0);
|
||||
} {1 {no such function: sqlite_rename_column}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -240,11 +240,13 @@ ifcapable vtab {
|
||||
);
|
||||
} {}
|
||||
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_execsql_test 7.2 {
|
||||
SELECT
|
||||
sqlite_rename_table(db, 0, 0, sql, zOld, zNew, bTemp)
|
||||
FROM ddd;
|
||||
} {{} {} {}}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -726,7 +726,7 @@ ifcapable subquery {
|
||||
} db2
|
||||
} {1 {trigger r5 cannot reference objects in database temp}}
|
||||
} ;# endif subquery
|
||||
ifcapable json1 {
|
||||
ifcapable json1&&vtab {
|
||||
do_test attach-5.10 {
|
||||
db close
|
||||
catch {db2 close}
|
||||
|
||||
@@ -987,6 +987,7 @@ ifcapable altertable {
|
||||
'main', 'table', 't1', $zCreate, $zOld, $zNew, 0
|
||||
)}
|
||||
}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_test fkey2-14.2.1.1 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
@@ -996,6 +997,7 @@ ifcapable altertable {
|
||||
do_test fkey2-14.2.1.3 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
|
||||
# Test ALTER TABLE RENAME TABLE a bit.
|
||||
#
|
||||
@@ -1068,6 +1070,7 @@ ifcapable altertable {
|
||||
}
|
||||
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
|
||||
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_test fkey2-14.2tmp.1.1 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
@@ -1077,6 +1080,7 @@ ifcapable altertable {
|
||||
do_test fkey2-14.2tmp.1.3 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
|
||||
# Test ALTER TABLE RENAME TABLE a bit.
|
||||
#
|
||||
@@ -1150,6 +1154,7 @@ ifcapable altertable {
|
||||
}
|
||||
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
|
||||
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_test fkey2-14.2aux.1.1 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
@@ -1159,6 +1164,7 @@ ifcapable altertable {
|
||||
do_test fkey2-14.2aux.1.3 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
|
||||
# Test ALTER TABLE RENAME TABLE a bit.
|
||||
#
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# 2018 December 3
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts4umlaut
|
||||
|
||||
ifcapable !fts3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
CREATE VIRTUAL TABLE t2 USING fts4(
|
||||
x,
|
||||
tokenize=unicode61 "remove_diacritics=2"
|
||||
);
|
||||
}
|
||||
|
||||
foreach {tn q res1 res2} {
|
||||
1 "Hà Nội" 0 1
|
||||
2 "Hà Noi" 1 1
|
||||
3 "Ha Noi" 1 1
|
||||
4 "Ha N\u1ed9i" 0 1
|
||||
5 "Ha N\u006fi" 1 1
|
||||
6 "Ha N\u006f\u0302i" 1 1
|
||||
7 "Ha N\u006f\u0323\u0302i" 1 1
|
||||
} {
|
||||
do_execsql_test 1.$tn.1 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(rowid, x) VALUES (1, 'Ha Noi');
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH $q
|
||||
} $res1
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(rowid, x) VALUES (1, $q);
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'Ha Noi'
|
||||
} $res1
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2(rowid, x) VALUES (1, 'Ha Noi');
|
||||
SELECT count(*) FROM t2 WHERE t2 MATCH $q
|
||||
} $res2
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t2;
|
||||
INSERT INTO t2(rowid, x) VALUES (1, $q);
|
||||
SELECT count(*) FROM t2 WHERE t2 MATCH 'Ha Noi'
|
||||
} $res2
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+5
-1
@@ -405,7 +405,10 @@ static void blobListFree(Blob *p){
|
||||
static sqlite3_int64 timeOfDay(void){
|
||||
static sqlite3_vfs *clockVfs = 0;
|
||||
sqlite3_int64 t;
|
||||
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
|
||||
if( clockVfs==0 ){
|
||||
clockVfs = sqlite3_vfs_find(0);
|
||||
if( clockVfs==0 ) return 0;
|
||||
}
|
||||
if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
|
||||
clockVfs->xCurrentTimeInt64(clockVfs, &t);
|
||||
}else{
|
||||
@@ -866,6 +869,7 @@ int main(int argc, char **argv){
|
||||
sqlite3_vfs *pDfltVfs; /* The default VFS */
|
||||
int openFlags4Data; /* Flags for sqlite3_open_v2() */
|
||||
|
||||
sqlite3_initialize();
|
||||
iBegin = timeOfDay();
|
||||
#ifdef __unix__
|
||||
signal(SIGALRM, timeoutHandler);
|
||||
|
||||
@@ -783,4 +783,54 @@ do_test incrvacuum-15.1 {
|
||||
}
|
||||
} {ok}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# At one point it was unsafe to truncate a db file on windows while there
|
||||
# were outstanding xFetch() references. This test case attempts to hit
|
||||
# that case.
|
||||
#
|
||||
ifcapable mmap {
|
||||
reset_db
|
||||
do_execsql_test incrvacuum-16.0 {
|
||||
PRAGMA auto_vacuum = 2;
|
||||
CREATE TABLE t3(a);
|
||||
INSERT INTO t3 VALUES(1), (2), (3), (4);
|
||||
|
||||
CREATE TABLE t2(x);
|
||||
INSERT INTO t2 VALUES( randomblob(1000) );
|
||||
INSERT INTO t2 VALUES( randomblob(1000) );
|
||||
INSERT INTO t2 VALUES( randomblob(1000) );
|
||||
INSERT INTO t2 VALUES( randomblob(1000) );
|
||||
INSERT INTO t2 VALUES( randomblob(1000) );
|
||||
INSERT INTO t2 VALUES( randomblob(1000) );
|
||||
} {}
|
||||
|
||||
# Reopen db to ensure the page-cache is empty.
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
# Open db in mmap-mode. Open a transaction, delete some data, then run
|
||||
# incremental-vacuum. Do not commit the transaction.
|
||||
#
|
||||
do_execsql_test incrvacuum-16.1 {
|
||||
PRAGMA mmap_size = 1000000;
|
||||
BEGIN;
|
||||
DELETE FROM t2;
|
||||
PRAGMA incremental_vacuum = 1000;
|
||||
} {1000000}
|
||||
|
||||
# Scan through table t3 (which is all clean pages - so mmap is used). Then,
|
||||
# midway through, commit the transaction. This causes the db to be truncated
|
||||
# while there are outstanding xFetch pages.
|
||||
#
|
||||
do_test incrvacuum-16.2 {
|
||||
set res [list]
|
||||
db eval { SELECT a FROM t3 } {
|
||||
if {$a==3} { db eval COMMIT }
|
||||
lappend res $a
|
||||
}
|
||||
set res
|
||||
} {1 2 3 4}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+29
-27
@@ -201,33 +201,35 @@ do_test 4.130 {
|
||||
# Additional test cases to show that UPDATE does not modify indexes that
|
||||
# do not involve unchanged columns.
|
||||
#
|
||||
load_static_extension db explain
|
||||
do_execsql_test 4.200 {
|
||||
CREATE TABLE t2(a,b,c,d,e,f);
|
||||
INSERT INTO t2 VALUES(2,3,4,5,6,7);
|
||||
CREATE INDEX t2abc ON t2(a+b+c);
|
||||
CREATE INDEX t2cd ON t2(c*d);
|
||||
CREATE INDEX t2def ON t2(d,e+25*f);
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET b=b+1')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc}
|
||||
do_execsql_test 4.210 {
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET c=c+1')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc t2cd}
|
||||
do_execsql_test 4.220 {
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET c=c+1, f=NULL')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc t2cd t2def}
|
||||
ifcapable vtab {
|
||||
load_static_extension db explain
|
||||
do_execsql_test 4.200 {
|
||||
CREATE TABLE t2(a,b,c,d,e,f);
|
||||
INSERT INTO t2 VALUES(2,3,4,5,6,7);
|
||||
CREATE INDEX t2abc ON t2(a+b+c);
|
||||
CREATE INDEX t2cd ON t2(c*d);
|
||||
CREATE INDEX t2def ON t2(d,e+25*f);
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET b=b+1')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc}
|
||||
do_execsql_test 4.210 {
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET c=c+1')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc t2cd}
|
||||
do_execsql_test 4.220 {
|
||||
SELECT sqlite_master.name
|
||||
FROM sqlite_master, explain('UPDATE t2 SET c=c+1, f=NULL')
|
||||
WHERE explain.opcode LIKE 'Open%'
|
||||
AND sqlite_master.rootpage=explain.p2
|
||||
ORDER BY 1;
|
||||
} {t2 t2abc t2cd t2def}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+18
-1
@@ -813,6 +813,23 @@ do_execsql_test json-14.170 {
|
||||
SELECT fullkey FROM json_tree('null');
|
||||
} {$}
|
||||
|
||||
|
||||
# 2018-12-03
|
||||
# Make sure the table-valued functions contained within parentheses
|
||||
# work correctly.
|
||||
#
|
||||
# Bug reported via private email. See TH3 for more information.
|
||||
#
|
||||
do_execsql_test json-15.100 {
|
||||
SELECT * FROM JSON_EACH('{"a":1, "b":2}');
|
||||
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
|
||||
do_execsql_test json-15.110 {
|
||||
SELECT xyz.* FROM JSON_EACH('{"a":1, "b":2}') AS xyz;
|
||||
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
|
||||
do_execsql_test json-15.120 {
|
||||
SELECT * FROM (JSON_EACH('{"a":1, "b":2}'));
|
||||
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
|
||||
do_execsql_test json-15.130 {
|
||||
SELECT xyz.* FROM (JSON_EACH('{"a":1, "b":2}')) AS xyz;
|
||||
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// A test case for the LEMON parser generator. Run as follows:
|
||||
//
|
||||
// lemon lemon-test01.y && gcc -g lemon-test01.c && ./a.out
|
||||
//
|
||||
%token_prefix TK_
|
||||
%token_type int
|
||||
%default_type int
|
||||
%include {
|
||||
static int nSyntaxError = 0;
|
||||
static int nAccept = 0;
|
||||
static int nFailure = 0;
|
||||
}
|
||||
|
||||
all ::= A B.
|
||||
all ::= error B.
|
||||
|
||||
%syntax_error {
|
||||
nSyntaxError++;
|
||||
}
|
||||
%parse_accept {
|
||||
nAccept++;
|
||||
}
|
||||
%parse_failure {
|
||||
nFailure++;
|
||||
}
|
||||
%code {
|
||||
#include <assert.h>
|
||||
#include "lemon-test01.h"
|
||||
static int nTest = 0;
|
||||
static int nErr = 0;
|
||||
static int testCase(int testId, int shouldBe, int actual){
|
||||
nTest++;
|
||||
if( shouldBe==actual ){
|
||||
printf("test %d: ok\n", testId);
|
||||
}else{
|
||||
printf("test %d: got %d, expected %d\n", testId, actual, shouldBe);
|
||||
nErr++;
|
||||
}
|
||||
}
|
||||
int main(int argc, char **argv){
|
||||
yyParser xp;
|
||||
ParseInit(&xp);
|
||||
Parse(&xp, TK_A, 0);
|
||||
Parse(&xp, TK_B, 0);
|
||||
Parse(&xp, 0, 0);
|
||||
ParseFinalize(&xp);
|
||||
testCase(100, 0, nSyntaxError);
|
||||
testCase(110, 1, nAccept);
|
||||
testCase(120, 0, nFailure);
|
||||
nSyntaxError = nAccept = nFailure = 0;
|
||||
ParseInit(&xp);
|
||||
Parse(&xp, TK_B, 0);
|
||||
Parse(&xp, TK_B, 0);
|
||||
Parse(&xp, 0, 0);
|
||||
ParseFinalize(&xp);
|
||||
testCase(200, 1, nSyntaxError);
|
||||
testCase(210, 1, nAccept);
|
||||
testCase(220, 0, nFailure);
|
||||
nSyntaxError = nAccept = nFailure = 0;
|
||||
ParseInit(&xp);
|
||||
Parse(&xp, TK_A, 0);
|
||||
Parse(&xp, TK_A, 0);
|
||||
Parse(&xp, 0, 0);
|
||||
ParseFinalize(&xp);
|
||||
testCase(200, 1, nSyntaxError);
|
||||
testCase(210, 0, nAccept);
|
||||
testCase(220, 0, nFailure);
|
||||
if( nErr==0 ){
|
||||
printf("%d tests pass\n", nTest);
|
||||
}else{
|
||||
printf("%d errors out %d tests\n", nErr, nTest);
|
||||
}
|
||||
return nErr;
|
||||
}
|
||||
}
|
||||
+12
-9
@@ -36,7 +36,10 @@ void ossfuzz_set_debug_flags(unsigned x){
|
||||
static sqlite3_int64 timeOfDay(void){
|
||||
static sqlite3_vfs *clockVfs = 0;
|
||||
sqlite3_int64 t;
|
||||
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
|
||||
if( clockVfs==0 ){
|
||||
clockVfs = sqlite3_vfs_find(0);
|
||||
if( clockVfs==0 ) return 0;
|
||||
}
|
||||
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
|
||||
clockVfs->xCurrentTimeInt64(clockVfs, &t);
|
||||
}else{
|
||||
@@ -56,9 +59,9 @@ typedef struct FuzzCtx {
|
||||
sqlite3_int64 iLastCb; /* Time recorded for previous progress callback */
|
||||
sqlite3_int64 mxInterval; /* Longest interval between two progress calls */
|
||||
unsigned nCb; /* Number of progress callbacks */
|
||||
unsigned execCnt; /* Number of calls to the sqlite3_exec callback */
|
||||
} FuzzCtx;
|
||||
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
/*
|
||||
** Progress handler callback.
|
||||
**
|
||||
@@ -74,7 +77,6 @@ static int progress_handler(void *pClientData) {
|
||||
p->nCb++;
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and
|
||||
@@ -101,12 +103,13 @@ static int block_debug_pragmas(
|
||||
/*
|
||||
** Callback for sqlite3_exec().
|
||||
*/
|
||||
static int exec_handler(void *pCnt, int argc, char **argv, char **namev){
|
||||
static int exec_handler(void *pClientData, int argc, char **argv, char **namev){
|
||||
FuzzCtx *p = (FuzzCtx*)pClientData;
|
||||
int i;
|
||||
if( argv ){
|
||||
for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i]));
|
||||
}
|
||||
return ((*(int*)pCnt)--)<=0;
|
||||
return (p->execCnt--)<=0 || progress_handler(pClientData);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -114,7 +117,6 @@ static int exec_handler(void *pCnt, int argc, char **argv, char **namev){
|
||||
** fuzzed input.
|
||||
*/
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
int execCnt = 0; /* Abort row callback when count reaches zero */
|
||||
char *zErrMsg = 0; /* Error message returned by sqlite_exec() */
|
||||
uint8_t uSelector; /* First byte of input data[] */
|
||||
int rc; /* Return code from various interfaces */
|
||||
@@ -134,11 +136,11 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
/* Open the database connection. Only use an in-memory database. */
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
rc = sqlite3_open_v2("fuzz.db", &cx.db,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
|
||||
if( rc ) return 0;
|
||||
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
/* Invoke the progress handler frequently to check to see if we
|
||||
** are taking too long. The progress handler will return true
|
||||
** (which will block further processing) if more than 10 seconds have
|
||||
@@ -146,6 +148,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
*/
|
||||
cx.iLastCb = timeOfDay();
|
||||
cx.iCutoffTime = cx.iLastCb + 10000; /* Now + 10 seconds */
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
|
||||
#endif
|
||||
|
||||
@@ -161,7 +164,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
/* Remaining bits of the selector determine a limit on the number of
|
||||
** output rows */
|
||||
execCnt = uSelector + 1;
|
||||
cx.execCnt = uSelector + 1;
|
||||
|
||||
/* Run the SQL. The sqlite_exec() interface expects a zero-terminated
|
||||
** string, so make a copy. */
|
||||
@@ -169,7 +172,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
#ifndef SQLITE_OMIT_COMPLETE
|
||||
sqlite3_complete(zSql);
|
||||
#endif
|
||||
sqlite3_exec(cx.db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);
|
||||
sqlite3_exec(cx.db, zSql, exec_handler, (void*)&cx, &zErrMsg);
|
||||
|
||||
/* Show any errors */
|
||||
if( (mDebug & FUZZ_SHOW_ERRORS)!=0 && zErrMsg ){
|
||||
|
||||
@@ -100,4 +100,146 @@ do_test pragma4-2.100 {
|
||||
[db eval {EXPLAIN PRAGMA integrity_check}]
|
||||
} {/ IntegrityCk 2 2 1 x[0-9]+,1x /}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 4.1.1 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE aux.t2(d, e, f);
|
||||
}
|
||||
do_execsql_test 4.1.2 { PRAGMA table_info = t1 } {
|
||||
0 a {} 0 {} 0 1 b {} 0 {} 0 2 c {} 0 {} 0
|
||||
}
|
||||
do_execsql_test 4.1.3 { PRAGMA table_info = t2 } {
|
||||
0 d {} 0 {} 0 1 e {} 0 {} 0 2 f {} 0 {} 0
|
||||
}
|
||||
do_test 4.1.4 {
|
||||
sqlite3 db3 test.db
|
||||
sqlite3 db2 test.db2
|
||||
execsql { DROP TABLE t1 } db3
|
||||
execsql { DROP TABLE t2 } db2
|
||||
} {}
|
||||
do_execsql_test 4.1.5 { PRAGMA table_info(t1) }
|
||||
do_execsql_test 4.1.6 { PRAGMA table_info(t2) }
|
||||
|
||||
db2 close
|
||||
db3 close
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 4.2.1 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE aux.t2(d, e, f);
|
||||
}
|
||||
ifcapable vtab {
|
||||
do_execsql_test 4.2.2 { SELECT * FROM pragma_table_info('t1') } {
|
||||
0 a {} 0 {} 0 1 b {} 0 {} 0 2 c {} 0 {} 0
|
||||
}
|
||||
do_execsql_test 4.2.3 { SELECT * FROM pragma_table_info('t2') } {
|
||||
0 d {} 0 {} 0 1 e {} 0 {} 0 2 f {} 0 {} 0
|
||||
}
|
||||
}
|
||||
do_test 4.2.4 {
|
||||
sqlite3 db3 test.db
|
||||
sqlite3 db2 test.db2
|
||||
execsql { DROP TABLE t1 } db3
|
||||
execsql { DROP TABLE t2 } db2
|
||||
} {}
|
||||
ifcapable vtab {
|
||||
do_execsql_test 4.2.5 { SELECT * FROM pragma_table_info('t1') }
|
||||
do_execsql_test 4.2.6 { SELECT * FROM pragma_table_info('t2') }
|
||||
}
|
||||
|
||||
db2 close
|
||||
db3 close
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 4.3.1 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE aux.t2(d, e, f);
|
||||
CREATE INDEX aux.i2 ON t2(e);
|
||||
}
|
||||
ifcapable vtab {
|
||||
do_execsql_test 4.3.2 { SELECT * FROM pragma_index_info('i1') } {0 1 b}
|
||||
do_execsql_test 4.3.3 { SELECT * FROM pragma_index_info('i2') } {0 1 e}
|
||||
}
|
||||
do_test 4.3.4 {
|
||||
sqlite3 db3 test.db
|
||||
sqlite3 db2 test.db2
|
||||
execsql { DROP INDEX i1 } db3
|
||||
execsql { DROP INDEX i2 } db2
|
||||
} {}
|
||||
ifcapable vtab {
|
||||
do_execsql_test 4.3.5 { SELECT * FROM pragma_index_info('i1') }
|
||||
do_execsql_test 4.3.6 { SELECT * FROM pragma_index_info('i2') }
|
||||
}
|
||||
|
||||
execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master}
|
||||
do_execsql_test 4.4.0 {
|
||||
CREATE INDEX main.i1 ON t1(b, c);
|
||||
CREATE INDEX aux.i2 ON t2(e, f);
|
||||
}
|
||||
ifcapable vtab {
|
||||
do_execsql_test 4.4.1 { SELECT * FROM pragma_index_list('t1') } {0 i1 0 c 0}
|
||||
do_execsql_test 4.4.2 { SELECT * FROM pragma_index_list('t2') } {0 i2 0 c 0}
|
||||
}
|
||||
do_test 4.4.3 {
|
||||
execsql { DROP INDEX i1 } db3
|
||||
execsql { DROP INDEX i2 } db2
|
||||
} {}
|
||||
ifcapable vtab {
|
||||
do_execsql_test 4.4.5 { SELECT * FROM pragma_index_list('t1') } {}
|
||||
do_execsql_test 4.4.6 { SELECT * FROM pragma_index_list('t2') } {}
|
||||
}
|
||||
execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master}
|
||||
|
||||
do_execsql_test 4.5.0 {
|
||||
CREATE UNIQUE INDEX main.i1 ON t1(a);
|
||||
CREATE UNIQUE INDEX aux.i2 ON t2(d);
|
||||
CREATE TABLE main.c1 (a, b, c REFERENCES t1(a));
|
||||
CREATE TABLE aux.c2 (d, e, r REFERENCES t2(d));
|
||||
}
|
||||
ifcapable vtab {
|
||||
do_execsql_test 4.5.1 { SELECT * FROM pragma_foreign_key_list('c1') } {
|
||||
0 0 t1 c a {NO ACTION} {NO ACTION} NONE
|
||||
}
|
||||
do_execsql_test 4.5.2 { SELECT * FROM pragma_foreign_key_list('c2') } {
|
||||
0 0 t2 r d {NO ACTION} {NO ACTION} NONE
|
||||
}
|
||||
}
|
||||
do_test 4.5.3 {
|
||||
execsql { DROP TABLE c1 } db3
|
||||
execsql { DROP TABLE c2 } db2
|
||||
} {}
|
||||
ifcapable vtab {
|
||||
do_execsql_test 4.5.4 { SELECT * FROM pragma_foreign_key_list('c1') }
|
||||
do_execsql_test 4.5.5 { SELECT * FROM pragma_foreign_key_list('c2') }
|
||||
}
|
||||
execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master}
|
||||
|
||||
do_execsql_test 4.6.0 {
|
||||
CREATE TABLE main.c1 (a, b, c REFERENCES t1(a));
|
||||
CREATE TABLE aux.c2 (d, e, r REFERENCES t2(d));
|
||||
INSERT INTO main.c1 VALUES(1, 2, 3);
|
||||
INSERT INTO aux.c2 VALUES(4, 5, 6);
|
||||
}
|
||||
do_execsql_test 4.6.1 { pragma foreign_key_check('c1') } {
|
||||
c1 1 t1 0
|
||||
}
|
||||
do_execsql_test 4.6.2 { pragma foreign_key_check('c2') } {
|
||||
c2 1 t2 0
|
||||
}
|
||||
do_test 4.6.3 {
|
||||
execsql { DROP TABLE c2 } db2
|
||||
} {}
|
||||
do_execsql_test 4.6.4 { pragma foreign_key_check('c1') } {c1 1 t1 0}
|
||||
do_catchsql_test 4.6.5 {
|
||||
pragma foreign_key_check('c2')
|
||||
} {1 {no such table: c2}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -79,6 +79,9 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
-DSQLITE_THREADSAFE
|
||||
-DSQLITE_TCL_DEFAULT_FULLMUTEX=1
|
||||
}
|
||||
"User-Auth" {
|
||||
-O2
|
||||
-DSQLITE_USER_AUTHENTICATION=1
|
||||
}
|
||||
"Secure-Delete" {
|
||||
@@ -274,6 +277,7 @@ array set ::Platforms [strip_comments {
|
||||
"Have-Not" test
|
||||
"Secure-Delete" test
|
||||
"Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
|
||||
"User-Auth" tcltest
|
||||
"Update-Delete-Limit" test
|
||||
"Extra-Robustness" test
|
||||
"Device-Two" test
|
||||
|
||||
@@ -1,388 +0,0 @@
|
||||
# 2017 August 9
|
||||
#
|
||||
# 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 reuse1
|
||||
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
|
||||
CREATE INDEX i1 ON t1(z);
|
||||
PRAGMA schema_version;
|
||||
} {2}
|
||||
|
||||
do_execsql_test -db db2 1.1 {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
|
||||
CREATE INDEX i1 ON t1(z);
|
||||
PRAGMA schema_version;
|
||||
} {2}
|
||||
|
||||
do_test 1.2 {
|
||||
db close
|
||||
db2 close
|
||||
sqlite3 db2 test.db2 -reuse-schema 1
|
||||
sqlite3 db test.db -reuse-schema 1
|
||||
} {}
|
||||
|
||||
do_execsql_test -db db2 1.3.1 {
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
}
|
||||
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT * FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_execsql_test -db db2 1.3.3 {
|
||||
SELECT * FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} {1 2 3 4 5 6 ok}
|
||||
|
||||
sqlite3 db3 test.db2
|
||||
do_execsql_test -db db3 1.4.1 {
|
||||
ALTER TABLE t1 ADD COLUMN a;
|
||||
}
|
||||
do_execsql_test -db db2 1.4.2 {
|
||||
SELECT * FROM t1;
|
||||
} {1 2 3 {} 4 5 6 {}}
|
||||
do_execsql_test 1.4.3 {
|
||||
SELECT * FROM t1;
|
||||
} {}
|
||||
|
||||
db3 close
|
||||
sqlite3 db3 test.db
|
||||
do_execsql_test -db db3 1.5.0 {
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
|
||||
SELECT 1, 2, 3;
|
||||
END;
|
||||
}
|
||||
|
||||
# Check that the schema cannot be modified if the db was opened with
|
||||
# SQLITE_OPEN_REUSE_SCHEMA.
|
||||
#
|
||||
foreach {tn sql} {
|
||||
1 { CREATE TABLE t2(x, y) }
|
||||
2 { CREATE INDEX i2 ON t1(z) }
|
||||
3 { CREATE VIEW v2 AS SELECT * FROM t2 }
|
||||
4 { ALTER TABLE t1 RENAME TO t3 }
|
||||
5 { ALTER TABLE t1 ADD COLUMN xyz }
|
||||
6 { VACUUM }
|
||||
7 { DROP INDEX i1 }
|
||||
8 { DROP TABLE t1 }
|
||||
9 { DROP TRIGGER tr1 }
|
||||
10 { ANALYZE }
|
||||
} {
|
||||
do_catchsql_test 1.5.$tn $sql {1 {attempt to modify read-only schema}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a);
|
||||
INSERT INTO ft VALUES('one'), ('two'), ('three');
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE VIRTUAL TABLE aux.ft USING fts5(a);
|
||||
INSERT INTO aux.ft VALUES('aux1'), ('aux2'), ('aux3');
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db -reuse-schema 1
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
SELECT * FROM main.ft;
|
||||
} {one two three}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT * FROM aux.ft;
|
||||
} {aux1 aux2 aux3}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT * FROM aux.ft_content;
|
||||
} {1 aux1 2 aux2 3 aux3}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
CREATE TRIGGER v1_ins INSTEAD OF INSERT ON v1 BEGIN
|
||||
INSERT INTO t1 VALUES(new.a, new.b, new.c);
|
||||
END;
|
||||
CREATE TRIGGER v1_del INSTEAD OF DELETE ON v1 BEGIN
|
||||
DELETE FROM t1 WHERE a=old.a;
|
||||
END;
|
||||
CREATE TRIGGER v1_up INSTEAD OF UPDATE ON v1 BEGIN
|
||||
UPDATE t1 SET a=new.a, b=new.b, c=new.c WHERE a=old.a;
|
||||
END;
|
||||
}
|
||||
forcecopy test.db test.db2
|
||||
|
||||
do_test 3.1 {
|
||||
sqlite3 db2 test.db2
|
||||
execsql { INSERT INTO t1 VALUES(1, 2, 3) } db
|
||||
execsql { INSERT INTO t1 VALUES(4, 5, 6) } db2
|
||||
db2 close
|
||||
execsql { ATTACH 'test.db2' AS aux; }
|
||||
} {}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM main.v1;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
SELECT * FROM aux.v1;
|
||||
} {4 5 6}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db -reuse-schema 1
|
||||
|
||||
do_execsql_test 3.4 { ATTACH 'test.db2' AS aux } {}
|
||||
do_execsql_test 3.5 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.6 { SELECT * FROM aux.v1 } {4 5 6}
|
||||
|
||||
do_execsql_test 3.7.1 { INSERT INTO aux.t1 VALUES(8, 9, 10); }
|
||||
do_execsql_test 3.7.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.7.3 { SELECT * FROM aux.v1 } {4 5 6 8 9 10}
|
||||
|
||||
do_execsql_test 3.8.1 { DELETE FROM aux.t1 WHERE b=5 }
|
||||
do_execsql_test 3.8.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.8.3 { SELECT * FROM aux.v1 } {8 9 10}
|
||||
|
||||
do_execsql_test 3.9.1 { UPDATE aux.t1 SET b='abc' }
|
||||
do_execsql_test 3.9.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.9.3 { SELECT * FROM aux.v1 } {8 abc 10}
|
||||
|
||||
do_execsql_test 3.10.1 { INSERT INTO aux.v1 VALUES(11, 12, 13) }
|
||||
do_execsql_test 3.10.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.10.3 { SELECT * FROM aux.v1 } {8 abc 10 11 12 13}
|
||||
|
||||
do_execsql_test 3.11.1 { DELETE FROM aux.v1 WHERE b='abc' }
|
||||
do_execsql_test 3.11.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.11.3 { SELECT * FROM aux.v1 } {11 12 13}
|
||||
|
||||
do_execsql_test 3.12.1 { UPDATE aux.v1 SET b='def' }
|
||||
do_execsql_test 3.12.2 { SELECT * FROM main.v1 } {1 2 3}
|
||||
do_execsql_test 3.12.3 { SELECT * FROM aux.v1 } {11 def 13}
|
||||
|
||||
do_execsql_test 3.13.1 {
|
||||
CREATE TEMP TRIGGER xyz AFTER INSERT ON aux.t1 BEGIN
|
||||
INSERT INTO v1 VALUES(new.a, new.b, new.c);
|
||||
END;
|
||||
}
|
||||
do_execsql_test 3.13.2 {
|
||||
INSERT INTO aux.v1 VALUES('x', 'y', 'z');
|
||||
}
|
||||
do_execsql_test 3.13.3 {
|
||||
SELECT * FROM v1;
|
||||
} {1 2 3 x y z}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
forcedelete test.db2
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE);
|
||||
CREATE TABLE del(a, b, c);
|
||||
CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN
|
||||
INSERT INTO del VALUES(old.a, old.b, old.c);
|
||||
END;
|
||||
}
|
||||
forcecopy test.db test.db2
|
||||
|
||||
db close
|
||||
sqlite3 db test.db -reuse-schema 1
|
||||
execsql {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
PRAGMA recursive_triggers = 1;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
INSERT INTO main.t1 VALUES(1, 2, 3);
|
||||
INSERT INTO aux.t1 VALUES(4, 5, 6);
|
||||
}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
INSERT OR REPLACE INTO aux.t1 VALUES('a', 'b', 6);
|
||||
SELECT * FROM aux.t1;
|
||||
} {a b 6}
|
||||
do_execsql_test 4.2.2 { SELECT * FROM aux.del } {4 5 6}
|
||||
do_execsql_test 4.2.3 { SELECT * FROM main.del } {}
|
||||
|
||||
do_execsql_test 4.3.1 {
|
||||
INSERT INTO aux.t1 VALUES('x', 'y', 'z');
|
||||
UPDATE OR REPLACE aux.t1 SET c='z' WHERE a='a';
|
||||
} {}
|
||||
do_execsql_test 4.3.2 { SELECT * FROM aux.del } {4 5 6 x y z}
|
||||
do_execsql_test 4.3.3 { SELECT * FROM main.del } {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6);
|
||||
ANALYZE;
|
||||
PRAGMA writable_schema = 1;
|
||||
DELETE FROM sqlite_stat1;
|
||||
}
|
||||
db close
|
||||
forcecopy test.db test.db2
|
||||
sqlite3 db test.db -reuse-schema 1
|
||||
execsql { ATTACH 'test.db2' AS aux }
|
||||
|
||||
foreach {tn sql} {
|
||||
1 { CREATE TABLE t3(x) }
|
||||
2 { DROP TABLE t2 }
|
||||
3 { CREATE INDEX i2 ON t2(b) }
|
||||
4 { DROP INDEX i1 }
|
||||
5 { ALTER TABLE t1 ADD COLUMN d }
|
||||
6 { ALTER TABLE t1 RENAME TO t3 }
|
||||
7 { ALTER TABLE t1 RENAME c TO d }
|
||||
} {
|
||||
do_catchsql_test 5.1.$tn $sql {1 {attempt to modify read-only schema}}
|
||||
}
|
||||
|
||||
do_execsql_test 5.2.1 { ANALYZE aux.t1 } {}
|
||||
do_execsql_test 5.2.2 { SELECT * FROM aux.sqlite_stat1 } {t1 i1 {2 1}}
|
||||
do_execsql_test 5.2.3 { SELECT * FROM main.sqlite_stat1 } {}
|
||||
|
||||
do_test 5.3.0 {
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval {
|
||||
PRAGMA writable_schema = 1;
|
||||
DELETE FROM sqlite_stat1;
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 5.3.1 { SELECT * FROM aux.sqlite_stat1 } {}
|
||||
do_execsql_test 5.3.2 { ANALYZE aux } {}
|
||||
do_execsql_test 5.3.3 { SELECT * FROM aux.sqlite_stat1 } {t1 i1 {2 1}}
|
||||
do_execsql_test 5.3.4 { SELECT * FROM main.sqlite_stat1 } {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Attempting to run ANALYZE when the required sqlite_statXX functions
|
||||
# are missing is an error (because it would modify the database schema).
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.4 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
INSERT INTO t1 VALUES(1, 2, 3), (4, 5, 6);
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db -reuse-schema 1
|
||||
foreach {tn sql} {
|
||||
1 { ANALYZE }
|
||||
2 { ANALYZE t1 }
|
||||
3 { ANALYZE i1 }
|
||||
4 { ANALYZE main }
|
||||
5 { ANALYZE main.t1 }
|
||||
6 { ANALYZE main.i1 }
|
||||
} {
|
||||
do_catchsql_test 5.4.$tn $sql {1 {attempt to modify read-only schema}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
}
|
||||
db close
|
||||
forcecopy test.db test.db2
|
||||
sqlite3 db test.db -reuse-schema 1
|
||||
execsql { ATTACH 'test.db2' AS aux }
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
INSERT INTO main.t1(a) VALUES(1), (2), (3);
|
||||
INSERT INTO aux.t1(a) VALUES(4), (5), (6);
|
||||
CREATE TEMP TABLE t2(i,t);
|
||||
INSERT INTO t2 VALUES(2, 'two'), (5, 'five');
|
||||
}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.t1)
|
||||
} {five}
|
||||
do_execsql_test 6.3 {
|
||||
SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.v1)
|
||||
} {five}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
CREATE TABLE p1(a PRIMARY KEY, b);
|
||||
CREATE TABLE p2(a PRIMARY KEY, b);
|
||||
CREATE TABLE c1(x REFERENCES p1 ON UPDATE CASCADE ON DELETE CASCADE);
|
||||
}
|
||||
|
||||
db close
|
||||
forcecopy test.db test.db2
|
||||
sqlite3 db test.db -reuse-schema 1
|
||||
execsql { ATTACH 'test.db2' AS aux }
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
INSERT INTO aux.p1 VALUES(1, 'one');
|
||||
INSERT INTO aux.p1 VALUES(2, 'two');
|
||||
PRAGMA foreign_keys = on;
|
||||
}
|
||||
|
||||
do_execsql_test 7.2 {
|
||||
INSERT INTO aux.c1 VALUES(2);
|
||||
}
|
||||
|
||||
do_execsql_test 7.3.1 {
|
||||
PRAGMA foreign_keys = off;
|
||||
INSERT INTO main.p2 SELECT * FROM aux.p1;
|
||||
}
|
||||
do_execsql_test 7.3.2 {
|
||||
SELECT * FROM main.p2;
|
||||
} {1 one 2 two}
|
||||
|
||||
do_execsql_test 7.3.3 {
|
||||
INSERT INTO aux.p2 VALUES(1, 2);
|
||||
}
|
||||
|
||||
do_execsql_test 7.3.4 {
|
||||
SELECT main.p2.a FROM main.p2, aux.p2;
|
||||
} {1 2}
|
||||
|
||||
do_execsql_test 7.3.5 {
|
||||
SELECT * FROM main.p2, aux.p2;
|
||||
} {1 one 1 2 2 two 1 2}
|
||||
|
||||
do_execsql_test 7.4 {
|
||||
SELECT count(*) FROM aux.p2;
|
||||
} {1}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -125,6 +125,11 @@ do_execsql_test tabfunc01-4.3 {
|
||||
SELECT * FROM aux1.generate_series(1,4)
|
||||
} {1 2 3 4}
|
||||
|
||||
# 2018-12-03: Fix bug reported by by private email.
|
||||
do_execsql_test tabfunc01-4.4 {
|
||||
SELECT * FROM (generate_series(1,5,2)) AS x LIMIT 10;
|
||||
} {1 3 5}
|
||||
|
||||
# The next series of tests is verifying that virtual table are able
|
||||
# to optimize the IN operator, even on terms that are not marked "omit".
|
||||
# When the generate_series virtual table is compiled for the testfixture,
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ source $testdir/tester.tcl
|
||||
|
||||
# Check the error messages generated by tclsqlite
|
||||
#
|
||||
set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN? ?-reuse-schema BOOLEAN?"
|
||||
set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
||||
if {[sqlite3 -has-codec]} {
|
||||
append r " ?-key CODECKEY?"
|
||||
}
|
||||
|
||||
@@ -76,4 +76,25 @@ do_execsql_test 1.4 {
|
||||
SELECT b=int2str(2) FROM t1
|
||||
} {1 1 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
db close
|
||||
sqlite3 db ""
|
||||
db func int2str int2str
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
PRAGMA cache_size = -100;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
WITH c(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100 )
|
||||
INSERT INTO t1 SELECT x, int2str(x) FROM c;
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
INSERT INTO t1 VALUES(10001, int2str(1001) || int2str(1001) || int2str(1001));
|
||||
}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT b FROM t1 WHERE a = 10001;
|
||||
} "[int2str 1001][int2str 1001][int2str 1001]"
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+22
-1
@@ -20,7 +20,6 @@ ifcapable !vtab {
|
||||
}
|
||||
|
||||
|
||||
|
||||
unset -nocomplain echo_module_begin_fail
|
||||
do_ioerr_test vtab_err-1 -tclprep {
|
||||
register_echo_module [sqlite3_connection_pointer db]
|
||||
@@ -63,4 +62,26 @@ do_malloc_test vtab_err-2 -tclprep {
|
||||
|
||||
sqlite3_memdebug_fail -1
|
||||
|
||||
reset_db
|
||||
register_echo_module [sqlite3_connection_pointer db]
|
||||
do_execsql_test vtab_err-3.0 {
|
||||
CREATE TABLE r(a PRIMARY KEY, b, c);
|
||||
CREATE VIRTUAL TABLE e USING echo(r);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test vtab_err-3 -faults oom-t* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
register_echo_module [sqlite3_connection_pointer db]
|
||||
} -body {
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE xyz(x);
|
||||
SELECT a FROM e;
|
||||
COMMIT;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -953,6 +953,7 @@ ifcapable altertable {
|
||||
'main', 'table', 't1', $zCreate, $zOld, $zNew, 0
|
||||
)}
|
||||
}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_test without_rowid3-14.2.1.1 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
@@ -962,6 +963,7 @@ ifcapable altertable {
|
||||
do_test without_rowid3-14.2.1.3 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
|
||||
# Test ALTER TABLE RENAME TABLE a bit.
|
||||
#
|
||||
@@ -1037,6 +1039,7 @@ ifcapable altertable {
|
||||
}
|
||||
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
|
||||
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_test without_rowid3-14.2tmp.1.1 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
@@ -1046,6 +1049,7 @@ ifcapable altertable {
|
||||
do_test without_rowid3-14.2tmp.1.3 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
|
||||
# Test ALTER TABLE RENAME TABLE a bit.
|
||||
#
|
||||
@@ -1122,6 +1126,7 @@ ifcapable altertable {
|
||||
}
|
||||
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
|
||||
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
|
||||
do_test without_rowid3-14.2aux.1.1 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
@@ -1131,6 +1136,7 @@ ifcapable altertable {
|
||||
do_test without_rowid3-14.2aux.1.3 {
|
||||
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
|
||||
} {{CREATE TABLE t1(a REFERENCES "t3")}}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0
|
||||
|
||||
# Test ALTER TABLE RENAME TABLE a bit.
|
||||
#
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
** 2018-12-04
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file implements a utility program used to help determine which
|
||||
** indexes in a database schema are used and unused, and how often specific
|
||||
** indexes are used.
|
||||
*/
|
||||
#include "sqlite3.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
static void usage(const char *argv0){
|
||||
printf("Usage: %s DATABASE LOG\n\n", argv0);
|
||||
printf(
|
||||
"DATABASE is an SQLite database against which various statements\n"
|
||||
"have been run. The SQL text is stored in LOG. LOG is an SQLite\n"
|
||||
"database with this schema:\n"
|
||||
"\n"
|
||||
" CREATE TABLE sqllog(sql TEXT);\n"
|
||||
"\n"
|
||||
"This utility program analyzes statements contained in LOG and prints\n"
|
||||
"a report showing how many times each index in DATABASE is used by the\n"
|
||||
"statements in LOG.\n"
|
||||
"\n"
|
||||
"DATABASE only needs to contain the schema used by the statements in\n"
|
||||
"LOG. The content can be removed from DATABASE.\n"
|
||||
);
|
||||
printf("\nAnalysis will be done by SQLite version %s dated %.20s\n"
|
||||
"checkin number %.40s. Different versions\n"
|
||||
"of SQLite might use different indexes.\n",
|
||||
sqlite3_libversion(), sqlite3_sourceid(), sqlite3_sourceid()+21);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
sqlite3 *db = 0; /* The main database */
|
||||
sqlite3_stmt *pStmt = 0; /* a query */
|
||||
char *zSql;
|
||||
int nErr = 0;
|
||||
int rc;
|
||||
|
||||
if( argc!=3 ) usage(argv[0]);
|
||||
rc = sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READONLY, 0);
|
||||
if( rc ){
|
||||
printf("Cannot open \"%s\" for reading: %s\n", argv[1], sqlite3_errmsg(db));
|
||||
goto errorOut;
|
||||
}
|
||||
rc = sqlite3_prepare_v2(db, "SELECT * FROM sqlite_master", -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
printf("Cannot read the schema from \"%s\" - %s\n", argv[1],
|
||||
sqlite3_errmsg(db));
|
||||
goto errorOut;
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
rc = sqlite3_exec(db,
|
||||
"CREATE TABLE temp.idxu(\n"
|
||||
" tbl TEXT,\n"
|
||||
" idx TEXT,\n"
|
||||
" cnt INT,\n"
|
||||
" PRIMARY KEY(idx)\n"
|
||||
") WITHOUT ROWID;", 0, 0, 0);
|
||||
if( rc ){
|
||||
printf("Cannot create the result table - %s\n",
|
||||
sqlite3_errmsg(db));
|
||||
goto errorOut;
|
||||
}
|
||||
rc = sqlite3_exec(db,
|
||||
"INSERT INTO temp.idxu(tbl,idx,cnt)"
|
||||
" SELECT tbl_name, name, 0 FROM sqlite_master"
|
||||
" WHERE type='index' AND sql IS NOT NULL", 0, 0, 0);
|
||||
|
||||
/* Open the LOG database */
|
||||
zSql = sqlite3_mprintf("ATTACH %Q AS log", argv[2]);
|
||||
rc = sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
printf("Cannot open the LOG database \"%s\" - %s\n",
|
||||
argv[2], sqlite3_errmsg(db));
|
||||
goto errorOut;
|
||||
}
|
||||
rc = sqlite3_prepare_v2(db, "SELECT sql, rowid FROM log.sqllog",
|
||||
-1, &pStmt, 0);
|
||||
if( rc ){
|
||||
printf("Cannot read the SQLLOG table in the LOG database \"%s\" - %s\n",
|
||||
argv[2], sqlite3_errmsg(db));
|
||||
goto errorOut;
|
||||
}
|
||||
|
||||
/* Update the counts based on LOG */
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
const char *zLog = (const char*)sqlite3_column_text(pStmt, 0);
|
||||
sqlite3_stmt *pS2;
|
||||
if( zLog==0 ) continue;
|
||||
zSql = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zLog);
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pS2, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
printf("Cannot compile LOG entry %d (%s): %s\n",
|
||||
sqlite3_column_int(pStmt, 1), zLog, sqlite3_errmsg(db));
|
||||
nErr++;
|
||||
}else{
|
||||
while( sqlite3_step(pS2)==SQLITE_ROW ){
|
||||
const char *zExplain = (const char*)sqlite3_column_text(pS2,3);
|
||||
const char *z1, *z2;
|
||||
int n;
|
||||
/* printf("EXPLAIN: %s\n", zExplain); */
|
||||
z1 = strstr(zExplain, " USING INDEX ");
|
||||
if( z1==0 ) continue;
|
||||
z1 += 13;
|
||||
for(z2=z1+1; z2[1] && z2[1]!='('; z2++){}
|
||||
n = z2 - z1;
|
||||
zSql = sqlite3_mprintf(
|
||||
"UPDATE temp.idxu SET cnt=cnt+1 WHERE idx='%.*q'", n, z1
|
||||
);
|
||||
/* printf("sql: %s\n", zSql); */
|
||||
sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pS2);
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
|
||||
/* Generate the report */
|
||||
rc = sqlite3_prepare_v2(db,
|
||||
"SELECT tbl, idx, cnt, "
|
||||
" (SELECT group_concat(name,',') FROM pragma_index_info(idx))"
|
||||
" FROM temp.idxu, main.sqlite_master"
|
||||
" WHERE temp.idxu.tbl=main.sqlite_master.tbl_name"
|
||||
" AND temp.idxu.idx=main.sqlite_master.name"
|
||||
" ORDER BY cnt DESC, tbl, idx",
|
||||
-1, &pStmt, 0);
|
||||
if( rc ){
|
||||
printf("Cannot query the result table - %s\n",
|
||||
sqlite3_errmsg(db));
|
||||
goto errorOut;
|
||||
}
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
printf("%10d %s on %s(%s)\n",
|
||||
sqlite3_column_int(pStmt, 2),
|
||||
sqlite3_column_text(pStmt, 1),
|
||||
sqlite3_column_text(pStmt, 0),
|
||||
sqlite3_column_text(pStmt, 3));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
|
||||
errorOut:
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_close(db);
|
||||
return nErr;
|
||||
}
|
||||
+9
-2
@@ -4590,13 +4590,20 @@ void ReportTable(
|
||||
tplt_print(out,lemp,lemp->overflow,&lineno);
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate the table of rule information
|
||||
/* Generate the tables of rule information. yyRuleInfoLhs[] and
|
||||
** yyRuleInfoNRhs[].
|
||||
**
|
||||
** Note: This code depends on the fact that rules are number
|
||||
** sequentually beginning with 0.
|
||||
*/
|
||||
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
|
||||
fprintf(out," { %4d, %4d }, /* (%d) ",rp->lhs->index,-rp->nrhs,i);
|
||||
fprintf(out," %4d, /* (%d) ", rp->lhs->index, i);
|
||||
rule_print(out, rp);
|
||||
fprintf(out," */\n"); lineno++;
|
||||
}
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
|
||||
fprintf(out," %3d, /* (%d) ", -rp->nrhs, i);
|
||||
rule_print(out, rp);
|
||||
fprintf(out," */\n"); lineno++;
|
||||
}
|
||||
|
||||
+16
-14
@@ -23,6 +23,7 @@
|
||||
** input grammar file:
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
/************ Begin %include sections from the grammar ************************/
|
||||
%%
|
||||
/**************** End of %include directives **********************************/
|
||||
@@ -685,13 +686,15 @@ static void yy_shift(
|
||||
yyTraceShift(yypParser, yyNewState, "Shift");
|
||||
}
|
||||
|
||||
/* The following table contains information about every rule that
|
||||
** is used during the reduce.
|
||||
*/
|
||||
static const struct {
|
||||
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
|
||||
signed char nrhs; /* Negative of the number of RHS symbols in the rule */
|
||||
} yyRuleInfo[] = {
|
||||
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
|
||||
** of that rule */
|
||||
static const YYCODETYPE yyRuleInfoLhs[] = {
|
||||
%%
|
||||
};
|
||||
|
||||
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
|
||||
** of symbols on the right-hand side of that rule. */
|
||||
static const signed char yyRuleInfoNRhs[] = {
|
||||
%%
|
||||
};
|
||||
|
||||
@@ -724,7 +727,7 @@ static YYACTIONTYPE yy_reduce(
|
||||
yymsp = yypParser->yytos;
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
|
||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||
yysize = yyRuleInfoNRhs[yyruleno];
|
||||
if( yysize ){
|
||||
fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
|
||||
yyTracePrompt,
|
||||
@@ -739,7 +742,7 @@ static YYACTIONTYPE yy_reduce(
|
||||
/* Check that the stack is large enough to grow by a single entry
|
||||
** if the RHS of the rule is empty. This ensures that there is room
|
||||
** enough on the stack to push the LHS value */
|
||||
if( yyRuleInfo[yyruleno].nrhs==0 ){
|
||||
if( yyRuleInfoNRhs[yyruleno]==0 ){
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
|
||||
yypParser->yyhwm++;
|
||||
@@ -781,9 +784,9 @@ static YYACTIONTYPE yy_reduce(
|
||||
%%
|
||||
/********** End reduce actions ************************************************/
|
||||
};
|
||||
assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
|
||||
yygoto = yyRuleInfo[yyruleno].lhs;
|
||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||
assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
|
||||
yygoto = yyRuleInfoLhs[yyruleno];
|
||||
yysize = yyRuleInfoNRhs[yyruleno];
|
||||
yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
|
||||
|
||||
/* There are no SHIFTREDUCE actions on nonterminals because the table
|
||||
@@ -987,10 +990,9 @@ void Parse(
|
||||
yymajor = YYNOCODE;
|
||||
}else{
|
||||
while( yypParser->yytos >= yypParser->yystack
|
||||
&& yymx != YYERRORSYMBOL
|
||||
&& (yyact = yy_find_reduce_action(
|
||||
yypParser->yytos->stateno,
|
||||
YYERRORSYMBOL)) >= YY_MIN_REDUCE
|
||||
YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE
|
||||
){
|
||||
yy_pop_parser_stack(yypParser);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user