Compare commits
104 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bc76063cd2 | |||
| 781e34cde3 | |||
| 344510e62b | |||
| 0e682099a1 | |||
| a70a073b3f | |||
| 18c7e40ca3 | |||
| d88e521f59 | |||
| 82d25da5b0 | |||
| 87af14a639 | |||
| 468108628c | |||
| 8073c70b33 | |||
| 3afca7d18c | |||
| 89212fb9f9 | |||
| b06a4ec1f0 | |||
| 55aeee4b48 | |||
| b72cad14d0 | |||
| f3ccc38a69 | |||
| eb443925ef | |||
| 8879481868 | |||
| f0ec2a5ea7 | |||
| fe70510aa7 | |||
| 0df163a9f0 | |||
| 378d01aa94 | |||
| b6e8fd105c | |||
| 62117159d0 | |||
| 0d71d121ae | |||
| dc90d3d8af | |||
| a6eaa635cc | |||
| fc5717cc99 | |||
| 03af2168db | |||
| 13ef14afc1 | |||
| 6d1626eb7c | |||
| 1496566560 | |||
| 817492630a | |||
| b1a1c29a07 | |||
| ef4668bc05 | |||
| d520041bc0 | |||
| afc14f72ef | |||
| 19c6d96aec | |||
| 052c6784ee | |||
| d1053a4314 | |||
| ed79b45cf7 | |||
| a4660bd695 | |||
| 5f1d536b53 | |||
| b64fa0adf7 | |||
| ad4b262545 | |||
| 5810d0315b | |||
| 9d42cc994c | |||
| ffe6bc2b93 | |||
| d34ab07507 | |||
| f926d1ea47 | |||
| a9e0aeb552 | |||
| f2c135fabd | |||
| 13a747e5e4 | |||
| 9b8afef260 | |||
| 5668969a69 | |||
| 295aedf097 | |||
| 80b2f97234 | |||
| 6295524e3d | |||
| dea63f24e1 | |||
| fcb44a89f2 | |||
| 900defa07a | |||
| fbf0f0e1f6 | |||
| f21fa489b1 | |||
| 7e065fcf7d | |||
| 3833e934d3 | |||
| c91b2fd310 | |||
| 75fd054201 | |||
| defbd9dade | |||
| efbf3b1a10 | |||
| 07901eb8c3 | |||
| 597515d70c | |||
| 063d4a041a | |||
| a6efad8a97 | |||
| 3b9330f83c | |||
| 69b30abd59 | |||
| c718190768 | |||
| 7e4efaecad | |||
| 3852b68edd | |||
| 434a93147c | |||
| 0baa035a1e | |||
| 1fed5dab0d | |||
| e8c1eba9a9 | |||
| 5e990bea51 | |||
| 151d05cd39 | |||
| edb4ece65e | |||
| 1925a2e6f8 | |||
| 98c91905c9 | |||
| 9d41bc105d | |||
| 15ab9418d9 | |||
| 5b4627e957 | |||
| 4d87aaed56 | |||
| 06280ee582 | |||
| 4300c1ae3b | |||
| 5655c549aa | |||
| 3d77dee935 | |||
| c0bf493ea5 | |||
| 49d9ba6354 | |||
| f4345e40a0 | |||
| 7d1761059b | |||
| 552fd45441 | |||
| bb13813ed1 | |||
| 65acf373c9 | |||
| a7b3b63524 |
@@ -1319,6 +1319,9 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR)
|
||||
$(TESTFIXTURE_SRC) \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
extensiontest: testfixture.exe testloadext.dll
|
||||
.\testfixture.exe $(TOP)\test\loadext.test
|
||||
|
||||
fulltest: testfixture.exe sqlite3.exe
|
||||
.\testfixture.exe $(TOP)\test\all.test
|
||||
|
||||
@@ -1345,6 +1348,12 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
$(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
testloadext.lo: $(TOP)\src\test_loadext.c
|
||||
$(LTCOMPILE) -c $(TOP)\src\test_loadext.c
|
||||
|
||||
testloadext.dll: testloadext.lo
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
|
||||
|
||||
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C)
|
||||
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showdb.c $(SQLITE3C)
|
||||
@@ -1363,6 +1372,7 @@ clean:
|
||||
del /Q sqlite3.h opcodes.c opcodes.h
|
||||
del /Q lemon.exe lempar.c parse.*
|
||||
del /Q mkkeywordhash.exe keywordhash.h
|
||||
del /Q notasharedlib.*
|
||||
-rmdir /Q/S .deps
|
||||
-rmdir /Q/S .libs
|
||||
-rmdir /Q/S quota2a
|
||||
@@ -1371,6 +1381,7 @@ clean:
|
||||
-rmdir /Q/S tsrc
|
||||
del /Q .target_source
|
||||
del /Q tclsqlite3.exe tclsqlite3.exp
|
||||
del /Q testloadext.dll testloadext.exp
|
||||
del /Q testfixture.exe testfixture.exp test.db
|
||||
del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
|
||||
del /Q sqlite3.c sqlite3-*.c
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.4.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.4.1.
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
@@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.8.4'
|
||||
PACKAGE_STRING='sqlite 3.8.4'
|
||||
PACKAGE_VERSION='3.8.4.1'
|
||||
PACKAGE_STRING='sqlite 3.8.4.1'
|
||||
PACKAGE_BUGREPORT=''
|
||||
|
||||
# Factoring default headers for most tests.
|
||||
@@ -1483,7 +1483,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.8.4 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.8.4.1 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1548,7 +1548,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.4:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.4.1:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1664,7 +1664,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.8.4
|
||||
sqlite configure 3.8.4.1
|
||||
generated by GNU Autoconf 2.62
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@@ -1678,7 +1678,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.8.4, which was
|
||||
It was created by sqlite $as_me 3.8.4.1, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -14021,7 +14021,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.8.4, which was
|
||||
This file was extended by sqlite $as_me 3.8.4.1, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -14074,7 +14074,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.8.4
|
||||
sqlite config.status 3.8.4.1
|
||||
configured by $0, generated by GNU Autoconf 2.62,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
||||
+37
-7
@@ -1410,10 +1410,7 @@ static int fts3InitVtab(
|
||||
** addition of a %_stat table so that it can use incremental merge.
|
||||
*/
|
||||
if( !isFts4 && !isCreate ){
|
||||
int rc2 = SQLITE_OK;
|
||||
fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2",
|
||||
p->zDb, p->zName);
|
||||
if( rc2==SQLITE_OK ) p->bHasStat = 1;
|
||||
p->bHasStat = 2;
|
||||
}
|
||||
|
||||
/* Figure out the page-size for the database. This is required in order to
|
||||
@@ -3320,7 +3317,34 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of xBegin() method. This is a no-op.
|
||||
** If it is currently unknown whether or not the FTS table has an %_stat
|
||||
** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat
|
||||
** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code
|
||||
** if an error occurs.
|
||||
*/
|
||||
static int fts3SetHasStat(Fts3Table *p){
|
||||
int rc = SQLITE_OK;
|
||||
if( p->bHasStat==2 ){
|
||||
const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
|
||||
char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
|
||||
if( zSql ){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of xBegin() method.
|
||||
*/
|
||||
static int fts3BeginMethod(sqlite3_vtab *pVtab){
|
||||
Fts3Table *p = (Fts3Table*)pVtab;
|
||||
@@ -3331,7 +3355,7 @@ static int fts3BeginMethod(sqlite3_vtab *pVtab){
|
||||
TESTONLY( p->inTransaction = 1 );
|
||||
TESTONLY( p->mxSavepoint = -1; );
|
||||
p->nLeafAdd = 0;
|
||||
return SQLITE_OK;
|
||||
return fts3SetHasStat(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3580,6 +3604,10 @@ static int fts3RenameMethod(
|
||||
sqlite3 *db = p->db; /* Database connection */
|
||||
int rc; /* Return Code */
|
||||
|
||||
/* At this point it must be known if the %_stat table exists or not.
|
||||
** So bHasStat may not be 2. */
|
||||
rc = fts3SetHasStat(p);
|
||||
|
||||
/* As it happens, the pending terms table is always empty here. This is
|
||||
** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
|
||||
** always opens a savepoint transaction. And the xSavepoint() method
|
||||
@@ -3587,7 +3615,9 @@ static int fts3RenameMethod(
|
||||
** PendingTermsFlush() in in case that changes.
|
||||
*/
|
||||
assert( p->nPendingData==0 );
|
||||
rc = sqlite3Fts3PendingTermsFlush(p);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3PendingTermsFlush(p);
|
||||
}
|
||||
|
||||
if( p->zContentTbl==0 ){
|
||||
fts3DbExec(&rc, db,
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ struct Fts3Table {
|
||||
|
||||
int nNodeSize; /* Soft limit for node size */
|
||||
u8 bFts4; /* True for FTS4, false for FTS3 */
|
||||
u8 bHasStat; /* True if %_stat table exists */
|
||||
u8 bHasStat; /* True if %_stat table exists (2==unknown) */
|
||||
u8 bHasDocsize; /* True if %_docsize table exists */
|
||||
u8 bDescIdx; /* True if doclists are in reverse order */
|
||||
u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */
|
||||
|
||||
@@ -5271,6 +5271,10 @@ int sqlite3Fts3UpdateMethod(
|
||||
int nChng = 0; /* Net change in number of documents */
|
||||
int bInsertDone = 0;
|
||||
|
||||
/* At this point it must be known if the %_stat table exists or not.
|
||||
** So bHasStat may not be 2. */
|
||||
assert( p->bHasStat==0 || p->bHasStat==1 );
|
||||
|
||||
assert( p->pSegments==0 );
|
||||
assert(
|
||||
nArg==1 /* DELETE operations */
|
||||
|
||||
+1
-1
@@ -26,8 +26,8 @@ SQLITE_EXTENSION_INIT1
|
||||
# define NEVER(X) 0
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
|
||||
+23
-15
@@ -2947,26 +2947,32 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
|
||||
** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
|
||||
*/
|
||||
static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
|
||||
const char *zSql = "SELECT stat FROM sqlite_stat1 WHERE tbl= ? || '_rowid'";
|
||||
const char *zFmt = "SELECT stat FROM %Q.sqlite_stat1 WHERE tbl = '%q_rowid'";
|
||||
char *zSql;
|
||||
sqlite3_stmt *p;
|
||||
int rc;
|
||||
i64 nRow = 0;
|
||||
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_text(p, 1, pRtree->zName, -1, SQLITE_STATIC);
|
||||
if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
|
||||
rc = sqlite3_finalize(p);
|
||||
}else if( rc!=SQLITE_NOMEM ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( nRow==0 ){
|
||||
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
|
||||
}else{
|
||||
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
|
||||
zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
|
||||
rc = sqlite3_finalize(p);
|
||||
}else if( rc!=SQLITE_NOMEM ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( nRow==0 ){
|
||||
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
|
||||
}else{
|
||||
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
|
||||
}
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -3235,6 +3241,8 @@ static int rtreeInit(
|
||||
if( rc==SQLITE_OK ){
|
||||
*ppVtab = (sqlite3_vtab *)pRtree;
|
||||
}else{
|
||||
assert( *ppVtab==0 );
|
||||
assert( pRtree->nBusy==1 );
|
||||
rtreeRelease(pRtree);
|
||||
}
|
||||
return rc;
|
||||
|
||||
@@ -158,5 +158,117 @@ do_execsql_test 4.3 {
|
||||
SELECT b, a FROM t2 LEFT JOIN t1 ON (+a = +b);
|
||||
} {1 1 3 {}}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Test that the sqlite_stat1 data is used correctly.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.1 {
|
||||
CREATE TABLE t1(x PRIMARY KEY, y);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
|
||||
|
||||
INSERT INTO t1(x) VALUES(1);
|
||||
INSERT INTO t1(x) SELECT x+1 FROM t1; -- 2
|
||||
INSERT INTO t1(x) SELECT x+2 FROM t1; -- 4
|
||||
INSERT INTO t1(x) SELECT x+4 FROM t1; -- 8
|
||||
INSERT INTO t1(x) SELECT x+8 FROM t1; -- 16
|
||||
INSERT INTO t1(x) SELECT x+16 FROM t1; -- 32
|
||||
INSERT INTO t1(x) SELECT x+32 FROM t1; -- 64
|
||||
INSERT INTO t1(x) SELECT x+64 FROM t1; -- 128
|
||||
INSERT INTO t1(x) SELECT x+128 FROM t1; -- 256
|
||||
INSERT INTO t1(x) SELECT x+256 FROM t1; -- 512
|
||||
INSERT INTO t1(x) SELECT x+512 FROM t1; --1024
|
||||
|
||||
INSERT INTO rt SELECT x, x, x+1 FROM t1 WHERE x<=5;
|
||||
}
|
||||
|
||||
# First test a query with no ANALYZE data at all. The outer loop is
|
||||
# real table "t1".
|
||||
#
|
||||
do_eqp_test 5.2 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
|
||||
}
|
||||
|
||||
# Now create enough ANALYZE data to tell SQLite that virtual table "rt"
|
||||
# contains very few rows. This causes it to move "rt" to the outer loop.
|
||||
#
|
||||
do_execsql_test 5.3 {
|
||||
ANALYZE;
|
||||
DELETE FROM sqlite_stat1 WHERE tbl='t1';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_eqp_test 5.4 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
0 0 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:}
|
||||
0 1 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)}
|
||||
}
|
||||
|
||||
# Delete the ANALYZE data. "t1" should be the outer loop again.
|
||||
#
|
||||
do_execsql_test 5.5 { DROP TABLE sqlite_stat1; }
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_eqp_test 5.6 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
|
||||
}
|
||||
|
||||
# This time create and attach a database that contains ANALYZE data for
|
||||
# tables of the same names as those used internally by virtual table
|
||||
# "rt". Check that the rtree module is not fooled into using this data.
|
||||
# Table "t1" should remain the outer loop.
|
||||
#
|
||||
do_test 5.7 {
|
||||
db backup test.db2
|
||||
sqlite3 db2 test.db2
|
||||
db2 eval {
|
||||
ANALYZE;
|
||||
DELETE FROM sqlite_stat1 WHERE tbl='t1';
|
||||
}
|
||||
db2 close
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
execsql { ATTACH 'test.db2' AS aux; }
|
||||
} {}
|
||||
do_eqp_test 5.8 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Test that having a second connection drop the sqlite_stat1 table
|
||||
# before it is required by rtreeConnect() does not cause problems.
|
||||
#
|
||||
ifcapable rtree {
|
||||
reset_db
|
||||
do_execsql_test 6.1 {
|
||||
CREATE TABLE t1(x);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO rt VALUES(1,2,3);
|
||||
ANALYZE;
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 6.2 { SELECT * FROM t1 } {1}
|
||||
|
||||
do_test 6.3 {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval { DROP TABLE sqlite_stat1 }
|
||||
db2 close
|
||||
execsql { SELECT * FROM rt }
|
||||
} {1 2.0 3.0}
|
||||
db close
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# 2014 March 11
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Miscellaneous tests for errors in the rtree constructor.
|
||||
#
|
||||
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
ifcapable !rtree {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
set testprefix rtreeD
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that if an SQLITE_BUSY is encountered within the vtable
|
||||
# constructor, a relevant error message is returned.
|
||||
#
|
||||
do_multiclient_test tn {
|
||||
do_test 1.$tn.1 {
|
||||
sql1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy);
|
||||
INSERT INTO rt VALUES(1,2,3,4,5);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 1.$tn.2 {
|
||||
sql2 { SELECT * FROM t1; }
|
||||
} {1 2}
|
||||
|
||||
do_test 1.$tn.3 {
|
||||
sql1 { BEGIN EXCLUSIVE; INSERT INTO t1 VALUES(3, 4); }
|
||||
} {}
|
||||
|
||||
do_test 1.$tn.4 {
|
||||
list [catch { sql2 { SELECT * FROM rt } } msg] $msg
|
||||
} {1 {database is locked}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C Add\slogic\sto\sdo\stest\scoverage\smeasurements\son\sthe\sVDBE\scode.
|
||||
D 2014-02-17T22:40:43.958
|
||||
C Add\sa\stest\sto\sensure\sos_unix.c\sworks\swith\s64KiB\sOS\spages.
|
||||
D 2014-03-20T09:42:09.744
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 371a17ef9cd011b103cfa1964119a8528f5427c9
|
||||
F Makefile.msc fdacba6fb574868c71fde6db6b77789a383a4c19
|
||||
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
|
||||
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
|
||||
F VERSION 0dc30ad5cf90736d5fd9e540c9f05c542658abe7
|
||||
F VERSION c3b0d47c3c5cf25c5bd4ff9e6f3af2f9d7934ea6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure e12e1a4f031354f9af735bcb377941a72dc2cca5 x
|
||||
F configure 6a7a482649dd20b7ee31424bf6553c6f20ca7936 x
|
||||
F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
@@ -78,9 +78,9 @@ 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 3fe91e36a0304ad4b35020f0e22ff37e95873166
|
||||
F ext/fts3/fts3.c 41b1920b9a8657963f09cb93b208c2671c5568db
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h eb5f8029589f3d8f1dc7fd50c773326a640388b1
|
||||
F ext/fts3/fts3Int.h bdeb9015405e8facffb8fc7e09174521a2a780f4
|
||||
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
|
||||
F ext/fts3/fts3_expr.c 5165c365cb5a035f5be8bb296f7aa3211d43e4ac
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
@@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c 92391b4b4fb043564c6539ea9b8661e3bcba47b9
|
||||
F ext/fts3/fts3_unicode2.c 0113d3acf13429e6dc38e0647d1bc71211c31a4d
|
||||
F ext/fts3/fts3_write.c cdebe72171a217b1465032dec103f8d17f7dad4d
|
||||
F ext/fts3/fts3_write.c 74c00329006c3ed6325ba4e5ab7c9b5fc99c8934
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
|
||||
@@ -114,13 +114,13 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/spellfix.c 3548c433f473c2054e080b6382771636fcaa2c4c
|
||||
F ext/misc/spellfix.c 93f3961074cebe63c31fcefe62ca2a032ee8dfed
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c a4e18b2c150adad20aecbeb3408cd235a0a57441
|
||||
F ext/rtree/rtree.c 2d9f95da404d850474e628c720c5ce15d29b47de
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
@@ -133,7 +133,8 @@ F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
|
||||
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34
|
||||
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
|
||||
F ext/rtree/rtreeB.test 983e567b49b5dca165940f66b87e161aa30e82b2
|
||||
F ext/rtree/rtreeC.test 03975565f40a0bee165f613143e4dec716dd5a59
|
||||
F ext/rtree/rtreeC.test 16d7aa86ecb6a876d2a38cf590a1471a41b3a46d
|
||||
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
|
||||
F ext/rtree/sqlite3rtree.h c34c1e41d1ab80bb8ad09aae402c9c956871a765
|
||||
@@ -156,42 +157,42 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 829d67a359b7c5d37120be994af2c0eac730070c
|
||||
F src/analyze.c 69761e1677142d180a9f55250dee2952f45e4793
|
||||
F src/alter.c 5d99edbac5bc416032772b723ee30182ee6e5de0
|
||||
F src/analyze.c 663e0b291d27eb03c9fd6b421e2d61ba348a2389
|
||||
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c b945df4f0114b4cc71006acc2fbb1333fb33a200
|
||||
F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f
|
||||
F src/btree.c 2a0e73f26c329f49e426237e71a879ffd205d778
|
||||
F src/btree.h da1b69b441ecee21f8b34ba73f0ae339540c4025
|
||||
F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4
|
||||
F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0
|
||||
F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0
|
||||
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
||||
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
|
||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c a00bf893bd39868c51020eba1fc5182eb36bfeb7
|
||||
F src/expr.c d1a8ccbf7e4dac6198674d33853e8ed01072eca4
|
||||
F src/delete.c cdd57149543bb28304d8f717c243f2a86b1fc280
|
||||
F src/expr.c 014b8087a15c4c314bdd798cb1cb0b32693f8b40
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 3cd6ce998404fb1b7203d886d6fdff71cf3c8846
|
||||
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
|
||||
F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf
|
||||
F src/func.c 2945bb2c4cdc0ac43733046285a4434310be1811
|
||||
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
|
||||
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
|
||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 5d5e1d78f74804739b424c92346bdc26c146dfa4
|
||||
F src/insert.c d8bb30535c8c0785876025a4a07f9074640a15d1
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
|
||||
F src/main.c e054917b1beb3081b0f23e8bdd3d6c0e12933dd3
|
||||
F src/main.c 691b25754bef596108fe60ff1bcbe8445369c9db
|
||||
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
|
||||
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c 19d9271cb936742707b6118ed44d779657c7c511
|
||||
F src/mem5.c aeb019f271ea53de83d651ec526877e6ba863450
|
||||
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
|
||||
F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
|
||||
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
|
||||
@@ -202,26 +203,26 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
|
||||
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_unix.c 18f7f95dc6bcb9cf4d4a238d8e2de96611bc2ae5
|
||||
F src/os_win.c d4284f003445054a26689f1264b1b9bf7261bd1b
|
||||
F src/pager.c 0ffa313a30ed6d061d9c6601b7b175cc50a1cab7
|
||||
F src/os_unix.c ae4b5240af4619d711301d7992396e182585269f
|
||||
F src/os_win.c e71678ac927d0a0fb11d993db20a9748eabf808e
|
||||
F src/pager.c 97a8908bf4e6e7c3adea09d3597cfa48ae33ab4e
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
F src/parse.y cce844ccb80b5f969b04c25100c8d94338488efb
|
||||
F src/parse.y 2613ca5d609c2f3d71dd297351f010bcec16e1e0
|
||||
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
|
||||
F src/pragma.c 2635d6bf8b54003ebefd773df2f50258cece2bec
|
||||
F src/pragma.c e78b4bf2a267de2c17ee09f90b6807cf8d40e6a3
|
||||
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
|
||||
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
|
||||
F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e
|
||||
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c 618b53bd4553bd7a9ef95069396f12a8f28489e7
|
||||
F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239
|
||||
F src/select.c 0adf172d33cc610ff5ffe26edfd2ba67c3551655
|
||||
F src/shell.c bab4de12b441369491812ecc93212ff4deda68fa
|
||||
F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 004bd50575a05eefba7228c2d0fee432a53200de
|
||||
F src/sqliteInt.h fa7161b3de18a9c355d4148233f3563c92311fcc
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@@ -230,7 +231,7 @@ F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299
|
||||
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
|
||||
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
|
||||
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
|
||||
F src/test5.c 41e6e732f14a54c7b47f753e364700760f6521b0
|
||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
|
||||
F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2
|
||||
F src/test8.c 54ccd7b1df5062f0ecbf50a8f7b618f8b1f13b20
|
||||
@@ -243,13 +244,13 @@ F src/test_config.c 0336e0bdbe541b4af89d7e3dd0656e8e6b51e585
|
||||
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
F src/test_func.c f8235719dff4bf9ffee04c55a190af8782ce9ab5
|
||||
F src/test_func.c d3013ce36f19ac72a99c73864930fd1fa41832f8
|
||||
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
|
||||
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
|
||||
F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61
|
||||
F src/test_intarray.h 2ece66438cfd177b78d1bfda7a4180cd3a10844d
|
||||
F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64
|
||||
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c 1ff5b1243d96124c9a180f3b89424820a1f337f3
|
||||
F src/test_multiplex.c 9f304bf04170c91c0318238d512df2da039eb1c8
|
||||
F src/test_multiplex.h 110a8c4d356e0aa464ca8730375608a9a0b61ae1
|
||||
@@ -265,32 +266,32 @@ F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
|
||||
F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e
|
||||
F src/test_stat.c 9898687a6c2beca733b0dd6fe19163d987826d31
|
||||
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||
F src/test_syscall.c 16dbe79fb320fadb5acd7a0a59f49e52ab2d2091
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
|
||||
F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
|
||||
F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
|
||||
F src/trigger.c a80036fcbd992729adc7cd34a875d59a71fa10cc
|
||||
F src/update.c 16d6555a32298da18ce6e2a00637c462d9e3ac97
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
|
||||
F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115
|
||||
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
|
||||
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 392f03b25152eb44565a78b8b809743c97e5852b
|
||||
F src/vdbe.h f429f5e5e14b02acbdffb2b2e8ba6e865e66e320
|
||||
F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8
|
||||
F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820
|
||||
F src/vdbeaux.c 0e01d6fda149c689039caadb8c89b20abb58e21d
|
||||
F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50
|
||||
F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda
|
||||
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
|
||||
F src/vdbe.c 5f0fffa9bf49a90c05dc3d46d8217603fd0ee00e
|
||||
F src/vdbe.h fb2c48c198300a7c632f09fc940011d2ad2fc2ae
|
||||
F src/vdbeInt.h e54fc4f289fce48e81b3371128446033d097733b
|
||||
F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4
|
||||
F src/vdbeaux.c e45e3f9daf38c5be3fd39e9aacc1c9066af57a06
|
||||
F src/vdbeblob.c 15377abfb59251bccedd5a9c7d014a895f0c04aa
|
||||
F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
|
||||
F src/vdbesort.c 0a9e5e63d7ce196651610d1a264eeb0b2152d3ba
|
||||
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
|
||||
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c 7825dce3f92d7c7de9329505deefe176cbd5ba43
|
||||
F src/where.c bb50b5aed4f9b2284eb92c944253e60df2fb8259
|
||||
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -300,7 +301,7 @@ F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
|
||||
F test/alter.test e88dfa77e020c2b48e52a8020c70171ab828e079
|
||||
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
|
||||
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
|
||||
F test/alter4.test 8e93bf7a7e6919b14b0c9a6c1e4908bcf21b0165
|
||||
F test/alter4.test d6c011fa0d6227abba762498cafbb607c9609e93
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
@@ -310,7 +311,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test d31defa011a561b938b4608d3538c1b4e0b5e92c
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
||||
F test/analyze9.test 339e87723cd4dc158dc5e9095acd8df9e87faf79
|
||||
F test/analyze9.test e072a5172d55afcba98d6ca6a219ce8878c2f5c9
|
||||
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
||||
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
@@ -361,7 +362,7 @@ F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
|
||||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
|
||||
F test/capi3.test 6cdd49656bd62a296924f4d2fcfd05cd2a298369
|
||||
F test/capi3.test 71bcf2fbd36a9732f617766dfd752552c8e491b5
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test a21869e4d50d5dbb7e566e328fc0bc7c2efa6a32
|
||||
F test/capi3d.test 6d0fc0a86d73f42dd19a7d8b7761ab9bc02277d0
|
||||
@@ -402,8 +403,9 @@ F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb
|
||||
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
|
||||
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test c150f156dace653c00a121ad0f5772a0568c41ba
|
||||
F test/corruptH.test 9d8186f6f8751efdfd445d8546fd98f073499039
|
||||
F test/corruptG.test 58ec333a01997fe655e34e5bea52b7a2a6b9704d
|
||||
F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb
|
||||
F test/corruptI.test 88886ec9cd1bdba835263566bbf60ee009c6ea09
|
||||
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
|
||||
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
|
||||
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
|
||||
@@ -521,7 +523,7 @@ F test/fts3ak.test bd14deafe9d1586e8e9bf032411026ac4f8c925d
|
||||
F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
|
||||
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
|
||||
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
|
||||
F test/fts3ao.test 71b0675e3df5c512a5a03daaa95ee1916de23dda
|
||||
F test/fts3ao.test 3e4e3d5e75c076520341d0bdf4eb17c00e8cbde2
|
||||
F test/fts3atoken.test fca30fd86db9241d571c637751e9a8a2f50f1451
|
||||
F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
|
||||
F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221
|
||||
@@ -533,7 +535,7 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
|
||||
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||
F test/fts3d.test c8a193513a269ec4c205ca09645e26e0bc71b860
|
||||
F test/fts3d.test 597b0b76e41f0d672e2731c4d7b631d628efd13f
|
||||
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
|
||||
F test/fts3defer2.test a3b6cbeabaf28c9398652a4d101ea224d9358479
|
||||
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
|
||||
@@ -572,7 +574,7 @@ F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
|
||||
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
|
||||
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test 00667bbeac044d007f6f021af1b9f6150f0c7ff8
|
||||
F test/func.test a21814945d32137412b553d98ad2107f9b2173a9
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
|
||||
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
|
||||
@@ -629,7 +631,7 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
|
||||
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
||||
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/join.test 8d63cc4d230a7affafa4b6ab0b97c49b8ccb365c
|
||||
F test/join.test 559b81eb56ae350246f9c25986aa52c81c725c7e
|
||||
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
@@ -647,7 +649,7 @@ F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test e191e536d0fcd722a6b965e7cd1ee0bfd12a5991
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/limit.test cc0ab63385239b63c72452b0e93700bf5e8f0b99
|
||||
F test/loadext.test 92e6dfefd1229c3ef4aaabd87419efd8fa57a7a5
|
||||
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b
|
||||
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
|
||||
F test/lock.test 87af515b0c4cf928576d0f89946d67d7c265dfb4
|
||||
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
|
||||
@@ -735,7 +737,7 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
|
||||
F test/permutations.test 40add071ba71aefe1c04f5845308cf46f7de8d04
|
||||
F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429
|
||||
F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0
|
||||
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/printf2.test bed79b4c3e5da08ba88ad637c0bf62586843cfb1
|
||||
@@ -777,7 +779,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test fc2a61f226a649393664ad54bc5376631801517c
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test 00179be44e531fe04c1c3f15df216439dff2519d
|
||||
F test/select4.test 8c5a60d439e2df824aed56223566877a883c5c84
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2
|
||||
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
||||
@@ -788,6 +790,7 @@ F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
|
||||
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
|
||||
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
|
||||
F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7
|
||||
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
|
||||
F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
|
||||
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
@@ -804,11 +807,11 @@ F test/shell1.test f2a1d471e5cd2b42f7a65b166dc1ace2b8d11583
|
||||
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
|
||||
F test/shell5.test cee83b4385f842fec1f2a0bec9ea811f35386edf
|
||||
F test/shell5.test bb755ea9144b8078a752fc56223582627070b5f1
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test 8c777ffd9dad6ee6d2568160cb2158f0b5cd9dd2
|
||||
F test/skipscan1.test bed8cbe9d554c8c27afb6c88500f704c86a9196f
|
||||
F test/skipscan2.test 5a4db0799c338ddbacb154aaa5589c0254b36a8d
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
@@ -832,7 +835,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test a653783d985108c4912cc64d341ffbbb55ad2806
|
||||
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/table.test 580d23530187026d4502fae74a490f0408cf2cc7
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
@@ -841,7 +844,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
F test/tester.tcl 9bd04481b8b0ef1f2049ad01f28e175ee9a14f7b
|
||||
F test/tester.tcl f31bea1483ea1d39620f982130026e76f872d744
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -868,6 +871,7 @@ F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70
|
||||
F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0
|
||||
F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
|
||||
F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407
|
||||
F test/tkt-4ef7e3cfca.test 3965ae11cc9cf6e334f9d7d3c1e20bf8d56254b1
|
||||
F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
|
||||
F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa
|
||||
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
|
||||
@@ -881,6 +885,7 @@ F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
|
||||
F test/tkt-80e031a00f.test 9a154173461a4dbe2de49cda73963e04842d52f7
|
||||
F test/tkt-8454a207b9.test c583a9f814a82a2b5ba95207f55001c9f0cd816c
|
||||
F test/tkt-868145d012.test a5f941107ece6a64410ca4755c6329b7eb57a356
|
||||
F test/tkt-8c63ff0ec.test 258b7fc8d7e4e1cb5362c7d65c143528b9c4cbed
|
||||
F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5
|
||||
F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223
|
||||
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
|
||||
@@ -1016,7 +1021,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
|
||||
F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
|
||||
F test/unordered.test ef85ac8f2f3c93ed2b9e811b684de73175fc464c
|
||||
F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb
|
||||
F test/uri.test 63e03df051620a18f794b4f4adcdefb3c23b6751
|
||||
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
|
||||
@@ -1024,7 +1029,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
|
||||
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test 4057630287bfa5955628fe90a13d4c225d1c7352
|
||||
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
|
||||
F test/vtab1.test b631d147b198cfd7903ab5fed028eb2a3d321dc6
|
||||
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
|
||||
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
|
||||
@@ -1042,13 +1047,14 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
|
||||
F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
|
||||
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test 6acafaae7126c9f49be72c2f57eb8bef3024f1cb
|
||||
F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772
|
||||
F test/wal.test 40073e54359d43354925b2b700b7eebd5e207285
|
||||
F test/wal2.test a8e3963abf6b232cf0b852b09b53665ef34007af
|
||||
F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b
|
||||
F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e
|
||||
F test/wal64k.test 63828c2161ad76ddd4109dee0a096b6ef6895698
|
||||
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
|
||||
F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216
|
||||
F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
|
||||
@@ -1064,12 +1070,12 @@ F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
|
||||
F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
|
||||
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
|
||||
F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6
|
||||
F test/walro.test 6cc247a0cc9b36aeea2057dd28a922a1cdfbd630
|
||||
F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57
|
||||
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
|
||||
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
|
||||
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
|
||||
F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b
|
||||
F test/where2.test ed6baa9420a109d8be683dbef5d153d186f3690b
|
||||
F test/where2.test 455a2eb2666e66c1e84e2cb5815173a85e6237db
|
||||
F test/where3.test d28c51f257e60be30f74308fa385ceeddfb54a6e
|
||||
F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
@@ -1120,7 +1126,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02
|
||||
F tool/mksqlite3c.tcl e2ba20d3f690990079d17f3e5a7417dfb7ada543
|
||||
F tool/mksqlite3c.tcl ed5b4e9ca8bf209ff401059a16362f37710fd8b8
|
||||
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
|
||||
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
|
||||
F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5
|
||||
@@ -1151,7 +1157,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P f29d194e03d6bcc78bf883b77e591dbccada02f0
|
||||
R 3842d7f2fc20472907a26e6db9a0b24a
|
||||
U drh
|
||||
Z 8a746710251048df8d65813e18590ec6
|
||||
P 6f3a5c24d254fc6faf607b505bdef4a7aafc21af
|
||||
R 20782a7f4b1e1e0590156d829fb7cb71
|
||||
U dan
|
||||
Z 523769a43e90bd1d8c3037ea221853f3
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
ce184c7bb16988641d37c908d9b3042456d4be3d
|
||||
e3d2be3ba47cdaafd26347620ae3bc2813203f16
|
||||
+7
-6
@@ -77,8 +77,8 @@ static void renameTableFunc(
|
||||
assert( len>0 );
|
||||
} while( token!=TK_LP && token!=TK_USING );
|
||||
|
||||
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
|
||||
zTableName, tname.z+tname.n);
|
||||
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
|
||||
zSql, zTableName, tname.z+tname.n);
|
||||
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
@@ -130,7 +130,7 @@ static void renameParentFunc(
|
||||
sqlite3Dequote(zParent);
|
||||
if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){
|
||||
char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
|
||||
(zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew
|
||||
(zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew
|
||||
);
|
||||
sqlite3DbFree(db, zOutput);
|
||||
zOutput = zOut;
|
||||
@@ -216,8 +216,8 @@ static void renameTriggerFunc(
|
||||
/* Variable tname now contains the token that is the old table-name
|
||||
** in the CREATE TRIGGER statement.
|
||||
*/
|
||||
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
|
||||
zTableName, tname.z+tname.n);
|
||||
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
|
||||
zSql, zTableName, tname.z+tname.n);
|
||||
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
@@ -604,7 +604,8 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
|
||||
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2);
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); VdbeCoverage(v);
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
|
||||
+5
-2
@@ -1178,7 +1178,10 @@ static void analyzeOneTable(
|
||||
callStatGet(v, regStat4, STAT_GET_NLT, regLt);
|
||||
callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
|
||||
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
|
||||
VdbeCoverage(v);
|
||||
/* We know that the regSampleRowid row exists because it was read by
|
||||
** the previous loop. Thus the not-found jump of seekOp will never
|
||||
** be taken */
|
||||
VdbeCoverageNeverTaken(v);
|
||||
#ifdef SQLITE_ENABLE_STAT3
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
|
||||
pIdx->aiColumn[0], regSample);
|
||||
@@ -1192,7 +1195,7 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */
|
||||
sqlite3VdbeJumpHere(v, addrIsNull);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
||||
|
||||
+17
-4
@@ -2161,6 +2161,7 @@ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
/*
|
||||
** Change the limit on the amount of the database file that may be
|
||||
** memory mapped.
|
||||
@@ -2173,6 +2174,7 @@ int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
|
||||
sqlite3BtreeLeave(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
|
||||
|
||||
/*
|
||||
** Change the way data is synced to disk in order to increase or decrease
|
||||
@@ -4547,6 +4549,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
int *pRes /* Write search results here */
|
||||
){
|
||||
int rc;
|
||||
RecordCompare xRecordCompare;
|
||||
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
@@ -4568,6 +4571,16 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
}
|
||||
}
|
||||
|
||||
if( pIdxKey ){
|
||||
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
|
||||
assert( pIdxKey->default_rc==1
|
||||
|| pIdxKey->default_rc==0
|
||||
|| pIdxKey->default_rc==-1
|
||||
);
|
||||
}else{
|
||||
xRecordCompare = 0; /* All keys are integers */
|
||||
}
|
||||
|
||||
rc = moveToRoot(pCur);
|
||||
if( rc ){
|
||||
return rc;
|
||||
@@ -4600,7 +4613,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
assert( biasRight==0 || biasRight==1 );
|
||||
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
|
||||
pCur->aiIdx[pCur->iPage] = (u16)idx;
|
||||
if( pPage->intKey ){
|
||||
if( xRecordCompare==0 ){
|
||||
for(;;){
|
||||
i64 nCellKey;
|
||||
pCell = findCell(pPage, idx) + pPage->childPtrSize;
|
||||
@@ -4652,14 +4665,14 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
** single byte varint and the record fits entirely on the main
|
||||
** b-tree page. */
|
||||
testcase( pCell+nCell+1==pPage->aDataEnd );
|
||||
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
|
||||
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0);
|
||||
}else if( !(pCell[1] & 0x80)
|
||||
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
|
||||
){
|
||||
/* The record-size field is a 2 byte varint and the record
|
||||
** fits entirely on the main b-tree page. */
|
||||
testcase( pCell+nCell+2==pPage->aDataEnd );
|
||||
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
|
||||
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0);
|
||||
}else{
|
||||
/* The record flows over onto one or more overflow pages. In
|
||||
** this case the whole cell needs to be parsed, a buffer allocated
|
||||
@@ -4680,7 +4693,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
sqlite3_free(pCellKey);
|
||||
goto moveto_finish;
|
||||
}
|
||||
c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
|
||||
c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
|
||||
sqlite3_free(pCellKey);
|
||||
}
|
||||
if( c<0 ){
|
||||
|
||||
+3
-1
@@ -63,7 +63,9 @@ int sqlite3BtreeOpen(
|
||||
|
||||
int sqlite3BtreeClose(Btree*);
|
||||
int sqlite3BtreeSetCacheSize(Btree*,int);
|
||||
int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
|
||||
#endif
|
||||
int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
|
||||
int sqlite3BtreeSyncDisabled(Btree*);
|
||||
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
|
||||
|
||||
+3
-3
@@ -3473,7 +3473,7 @@ SrcList *sqlite3SrcListEnlarge(
|
||||
assert( iStart<=pSrc->nSrc );
|
||||
|
||||
/* Allocate additional space if needed */
|
||||
if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
|
||||
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
|
||||
SrcList *pNew;
|
||||
int nAlloc = pSrc->nSrc+nExtra;
|
||||
int nGot;
|
||||
@@ -3485,7 +3485,7 @@ SrcList *sqlite3SrcListEnlarge(
|
||||
}
|
||||
pSrc = pNew;
|
||||
nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
|
||||
pSrc->nAlloc = (u8)nGot;
|
||||
pSrc->nAlloc = nGot;
|
||||
}
|
||||
|
||||
/* Move existing slots that come after the newly inserted slots
|
||||
@@ -3493,7 +3493,7 @@ SrcList *sqlite3SrcListEnlarge(
|
||||
for(i=pSrc->nSrc-1; i>=iStart; i--){
|
||||
pSrc->a[i+nExtra] = pSrc->a[i];
|
||||
}
|
||||
pSrc->nSrc += (i8)nExtra;
|
||||
pSrc->nSrc += nExtra;
|
||||
|
||||
/* Zero the newly allocated slots */
|
||||
memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
|
||||
|
||||
@@ -215,6 +215,9 @@ static const char * const azCompileOpt[] = {
|
||||
#ifdef SQLITE_OMIT_COMPOUND_SELECT
|
||||
"OMIT_COMPOUND_SELECT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_CTE
|
||||
"OMIT_CTE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DATETIME_FUNCS
|
||||
"OMIT_DATETIME_FUNCS",
|
||||
#endif
|
||||
|
||||
+4
-2
@@ -613,7 +613,8 @@ void sqlite3GenerateRowDelete(
|
||||
opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
|
||||
if( !bNoSeek ){
|
||||
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, opSeek==OP_NotExists);
|
||||
VdbeCoverageIf(v, opSeek==OP_NotFound);
|
||||
}
|
||||
|
||||
/* If there are any triggers to fire, allocate a range of registers to
|
||||
@@ -656,7 +657,8 @@ void sqlite3GenerateRowDelete(
|
||||
*/
|
||||
if( addrStart<sqlite3VdbeCurrentAddr(v) ){
|
||||
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, opSeek==OP_NotExists);
|
||||
VdbeCoverageIf(v, opSeek==OP_NotFound);
|
||||
}
|
||||
|
||||
/* Do FK processing. This call checks that any FK constraints that
|
||||
|
||||
+70
-116
@@ -1369,24 +1369,6 @@ int sqlite3ExprCanBeNull(const Expr *p){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate an OP_IsNull instruction that tests register iReg and jumps
|
||||
** to location iDest if the value in iReg is NULL. The value in iReg
|
||||
** was computed by pExpr. If we can look at pExpr at compile-time and
|
||||
** determine that it can never generate a NULL, then the OP_IsNull operation
|
||||
** can be omitted.
|
||||
*/
|
||||
void sqlite3ExprCodeIsNullJump(
|
||||
Vdbe *v, /* The VDBE under construction */
|
||||
const Expr *pExpr, /* Only generate OP_IsNull if this expr can be NULL */
|
||||
int iReg, /* Test the value in this register for NULL */
|
||||
int iDest /* Jump here if the value is null */
|
||||
){
|
||||
if( sqlite3ExprCanBeNull(pExpr) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest); VdbeCoverage(v);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the given expression is a constant which would be
|
||||
** unchanged by OP_Affinity with the affinity given in the second
|
||||
@@ -1486,9 +1468,7 @@ static int isCandidateForInOpt(Select *p){
|
||||
*/
|
||||
int sqlite3CodeOnce(Parse *pParse){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
|
||||
int addr = sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
|
||||
VdbeCoverage(v);
|
||||
return addr;
|
||||
return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1596,9 +1576,8 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
||||
*/
|
||||
assert(v);
|
||||
if( iCol<0 ){
|
||||
int iAddr;
|
||||
|
||||
iAddr = sqlite3CodeOnce(pParse);
|
||||
int iAddr = sqlite3CodeOnce(pParse);
|
||||
VdbeCoverage(v);
|
||||
|
||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||
eType = IN_INDEX_ROWID;
|
||||
@@ -1623,18 +1602,18 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
||||
&& sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
|
||||
&& (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None))
|
||||
){
|
||||
int iAddr = sqlite3CodeOnce(pParse);
|
||||
int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
|
||||
eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
|
||||
|
||||
sqlite3VdbeJumpHere(v, iAddr);
|
||||
if( prNotFound && !pTab->aCol[iCol].notNull ){
|
||||
*prNotFound = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, iAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1723,7 +1702,7 @@ int sqlite3CodeSubselect(
|
||||
** save the results, and reuse the same result on subsequent invocations.
|
||||
*/
|
||||
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
|
||||
testAddr = sqlite3CodeOnce(pParse);
|
||||
testAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
@@ -2004,7 +1983,7 @@ static void sqlite3ExprCodeIN(
|
||||
** the presence of a NULL on the RHS makes a difference in the
|
||||
** outcome.
|
||||
*/
|
||||
int j1, j2, j3;
|
||||
int j1, j2;
|
||||
|
||||
/* First check to see if the LHS is contained in the RHS. If so,
|
||||
** then the presence of NULLs in the RHS does not matter, so jump
|
||||
@@ -2019,19 +1998,15 @@ static void sqlite3ExprCodeIN(
|
||||
** jump to destIfNull. If there are no NULLs in the RHS then
|
||||
** jump to destIfFalse.
|
||||
*/
|
||||
j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); VdbeCoverage(v);
|
||||
j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull);
|
||||
sqlite3VdbeJumpHere(v, j3);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1);
|
||||
sqlite3VdbeJumpHere(v, j2);
|
||||
|
||||
/* Jump to the appropriate target depending on whether or not
|
||||
** the RHS contains a NULL
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_IfNot, rRhsHasNull, destIfFalse); VdbeCoverage(v);
|
||||
j2 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, rRhsHasNull);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
|
||||
sqlite3VdbeJumpHere(v, j2);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, rRhsHasNull);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
|
||||
|
||||
/* The OP_Found at the top of this branch jumps here when true,
|
||||
** causing the overall IN expression evaluation to fall through.
|
||||
@@ -2552,22 +2527,16 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
case TK_GE:
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
assert( TK_LT==OP_Lt );
|
||||
assert( TK_LE==OP_Le );
|
||||
assert( TK_GT==OP_Gt );
|
||||
assert( TK_GE==OP_Ge );
|
||||
assert( TK_EQ==OP_Eq );
|
||||
assert( TK_NE==OP_Ne );
|
||||
testcase( op==TK_LT );
|
||||
testcase( op==TK_LE );
|
||||
testcase( op==TK_GT );
|
||||
testcase( op==TK_GE );
|
||||
testcase( op==TK_EQ );
|
||||
testcase( op==TK_NE );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, inReg, SQLITE_STOREP2); VdbeCoverage(v);
|
||||
r1, r2, inReg, SQLITE_STOREP2);
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
||||
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
||||
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
||||
testcase( regFree1==0 );
|
||||
testcase( regFree2==0 );
|
||||
break;
|
||||
@@ -2581,7 +2550,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, op==TK_EQ);
|
||||
VdbeCoverageIf(v, op==TK_NE);
|
||||
testcase( regFree1==0 );
|
||||
testcase( regFree2==0 );
|
||||
break;
|
||||
@@ -2598,28 +2568,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
case TK_LSHIFT:
|
||||
case TK_RSHIFT:
|
||||
case TK_CONCAT: {
|
||||
assert( TK_AND==OP_And );
|
||||
assert( TK_OR==OP_Or );
|
||||
assert( TK_PLUS==OP_Add );
|
||||
assert( TK_MINUS==OP_Subtract );
|
||||
assert( TK_REM==OP_Remainder );
|
||||
assert( TK_BITAND==OP_BitAnd );
|
||||
assert( TK_BITOR==OP_BitOr );
|
||||
assert( TK_SLASH==OP_Divide );
|
||||
assert( TK_LSHIFT==OP_ShiftLeft );
|
||||
assert( TK_RSHIFT==OP_ShiftRight );
|
||||
assert( TK_CONCAT==OP_Concat );
|
||||
testcase( op==TK_AND );
|
||||
testcase( op==TK_OR );
|
||||
testcase( op==TK_PLUS );
|
||||
testcase( op==TK_MINUS );
|
||||
testcase( op==TK_REM );
|
||||
testcase( op==TK_BITAND );
|
||||
testcase( op==TK_BITOR );
|
||||
testcase( op==TK_SLASH );
|
||||
testcase( op==TK_LSHIFT );
|
||||
testcase( op==TK_RSHIFT );
|
||||
testcase( op==TK_CONCAT );
|
||||
assert( TK_AND==OP_And ); testcase( op==TK_AND );
|
||||
assert( TK_OR==OP_Or ); testcase( op==TK_OR );
|
||||
assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS );
|
||||
assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS );
|
||||
assert( TK_REM==OP_Remainder ); testcase( op==TK_REM );
|
||||
assert( TK_BITAND==OP_BitAnd ); testcase( op==TK_BITAND );
|
||||
assert( TK_BITOR==OP_BitOr ); testcase( op==TK_BITOR );
|
||||
assert( TK_SLASH==OP_Divide ); testcase( op==TK_SLASH );
|
||||
assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT );
|
||||
assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
|
||||
assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
sqlite3VdbeAddOp3(v, op, r2, r1, target);
|
||||
@@ -2651,10 +2610,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
}
|
||||
case TK_BITNOT:
|
||||
case TK_NOT: {
|
||||
assert( TK_BITNOT==OP_BitNot );
|
||||
assert( TK_NOT==OP_Not );
|
||||
testcase( op==TK_BITNOT );
|
||||
testcase( op==TK_NOT );
|
||||
assert( TK_BITNOT==OP_BitNot ); testcase( op==TK_BITNOT );
|
||||
assert( TK_NOT==OP_Not ); testcase( op==TK_NOT );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
testcase( regFree1==0 );
|
||||
inReg = target;
|
||||
@@ -2664,14 +2621,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
case TK_ISNULL:
|
||||
case TK_NOTNULL: {
|
||||
int addr;
|
||||
assert( TK_ISNULL==OP_IsNull );
|
||||
assert( TK_NOTNULL==OP_NotNull );
|
||||
testcase( op==TK_ISNULL );
|
||||
testcase( op==TK_NOTNULL );
|
||||
assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
|
||||
assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
testcase( regFree1==0 );
|
||||
addr = sqlite3VdbeAddOp1(v, op, r1); VdbeCoverage(v);
|
||||
addr = sqlite3VdbeAddOp1(v, op, r1);
|
||||
VdbeCoverageIf(v, op==TK_ISNULL);
|
||||
VdbeCoverageIf(v, op==TK_NOTNULL);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
break;
|
||||
@@ -2861,8 +2818,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
r3 = sqlite3GetTempReg(pParse);
|
||||
r4 = sqlite3GetTempReg(pParse);
|
||||
codeCompare(pParse, pLeft, pRight, OP_Ge,
|
||||
r1, r2, r3, SQLITE_STOREP2);
|
||||
VdbeCoverage(v);
|
||||
r1, r2, r3, SQLITE_STOREP2); VdbeCoverage(v);
|
||||
pLItem++;
|
||||
pRight = pLItem->pExpr;
|
||||
sqlite3ReleaseTempReg(pParse, regFree2);
|
||||
@@ -3609,23 +3565,17 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_GE:
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
assert( TK_LT==OP_Lt );
|
||||
assert( TK_LE==OP_Le );
|
||||
assert( TK_GT==OP_Gt );
|
||||
assert( TK_GE==OP_Ge );
|
||||
assert( TK_EQ==OP_Eq );
|
||||
assert( TK_NE==OP_Ne );
|
||||
testcase( op==TK_LT );
|
||||
testcase( op==TK_LE );
|
||||
testcase( op==TK_GT );
|
||||
testcase( op==TK_GE );
|
||||
testcase( op==TK_EQ );
|
||||
testcase( op==TK_NE );
|
||||
testcase( jumpIfNull==0 );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, jumpIfNull); VdbeCoverage(v);
|
||||
r1, r2, dest, jumpIfNull);
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
||||
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
||||
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
||||
testcase( regFree1==0 );
|
||||
testcase( regFree2==0 );
|
||||
break;
|
||||
@@ -3638,19 +3588,21 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v);
|
||||
r1, r2, dest, SQLITE_NULLEQ);
|
||||
VdbeCoverageIf(v, op==TK_EQ);
|
||||
VdbeCoverageIf(v, op==TK_NE);
|
||||
testcase( regFree1==0 );
|
||||
testcase( regFree2==0 );
|
||||
break;
|
||||
}
|
||||
case TK_ISNULL:
|
||||
case TK_NOTNULL: {
|
||||
assert( TK_ISNULL==OP_IsNull );
|
||||
assert( TK_NOTNULL==OP_NotNull );
|
||||
testcase( op==TK_ISNULL );
|
||||
testcase( op==TK_NOTNULL );
|
||||
assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
|
||||
assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, op, r1, dest);
|
||||
VdbeCoverageIf(v, op==TK_ISNULL);
|
||||
VdbeCoverageIf(v, op==TK_NOTNULL);
|
||||
testcase( regFree1==0 );
|
||||
break;
|
||||
}
|
||||
@@ -3769,17 +3721,17 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_GE:
|
||||
case TK_NE:
|
||||
case TK_EQ: {
|
||||
testcase( op==TK_LT );
|
||||
testcase( op==TK_LE );
|
||||
testcase( op==TK_GT );
|
||||
testcase( op==TK_GE );
|
||||
testcase( op==TK_EQ );
|
||||
testcase( op==TK_NE );
|
||||
testcase( jumpIfNull==0 );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, jumpIfNull); VdbeCoverage(v);
|
||||
r1, r2, dest, jumpIfNull);
|
||||
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
||||
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
||||
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
||||
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
|
||||
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
|
||||
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
|
||||
testcase( regFree1==0 );
|
||||
testcase( regFree2==0 );
|
||||
break;
|
||||
@@ -3792,17 +3744,19 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, SQLITE_NULLEQ); VdbeCoverage(v);
|
||||
r1, r2, dest, SQLITE_NULLEQ);
|
||||
VdbeCoverageIf(v, op==TK_EQ);
|
||||
VdbeCoverageIf(v, op==TK_NE);
|
||||
testcase( regFree1==0 );
|
||||
testcase( regFree2==0 );
|
||||
break;
|
||||
}
|
||||
case TK_ISNULL:
|
||||
case TK_NOTNULL: {
|
||||
testcase( op==TK_ISNULL );
|
||||
testcase( op==TK_NOTNULL );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, op, r1, dest);
|
||||
testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
|
||||
testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
|
||||
testcase( regFree1==0 );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -369,6 +369,7 @@ static void fkLookupParent(
|
||||
** increment the constraint-counter. */
|
||||
if( pTab==pFKey->pFrom && nIncr==1 ){
|
||||
sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
||||
}
|
||||
|
||||
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
|
||||
|
||||
+1
-1
@@ -1017,7 +1017,7 @@ static void charFunc(
|
||||
){
|
||||
unsigned char *z, *zOut;
|
||||
int i;
|
||||
zOut = z = sqlite3_malloc( argc*4 );
|
||||
zOut = z = sqlite3_malloc( argc*4+1 );
|
||||
if( z==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
|
||||
+15
-20
@@ -101,13 +101,13 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
||||
** Compute the affinity string for table pTab, if it has not already been
|
||||
** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities.
|
||||
**
|
||||
** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values and
|
||||
** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and
|
||||
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
|
||||
** for register iReg and following. Or if affinities exists and iReg==0,
|
||||
** then just set the P4 operand of the previous opcode (which should be
|
||||
** an OP_MakeRecord) to the affinity string.
|
||||
**
|
||||
** A column affinity string has one character column:
|
||||
** A column affinity string has one character per column:
|
||||
**
|
||||
** Character Column affinity
|
||||
** ------------------------------
|
||||
@@ -148,10 +148,9 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
||||
|
||||
/*
|
||||
** Return non-zero if the table pTab in database iDb or any of its indices
|
||||
** have been opened at any point in the VDBE program beginning at location
|
||||
** iStartAddr throught the end of the program. This is used to see if
|
||||
** have been opened at any point in the VDBE program. This is used to see if
|
||||
** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can
|
||||
** run without using temporary table for the results of the SELECT.
|
||||
** run without using a temporary table for the results of the SELECT.
|
||||
*/
|
||||
static int readsTable(Parse *p, int iDb, Table *pTab){
|
||||
Vdbe *v = sqlite3GetVdbe(p);
|
||||
@@ -304,7 +303,7 @@ void sqlite3AutoincrementEnd(Parse *pParse){
|
||||
assert( v );
|
||||
for(p = pParse->pAinc; p; p = p->pNext){
|
||||
Db *pDb = &db->aDb[p->iDb];
|
||||
int j1, j2, j3, j4, j5;
|
||||
int j1;
|
||||
int iRec;
|
||||
int memId = p->regCtr;
|
||||
|
||||
@@ -312,17 +311,8 @@ void sqlite3AutoincrementEnd(Parse *pParse){
|
||||
assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
|
||||
sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
|
||||
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v);
|
||||
j2 = sqlite3VdbeAddOp0(v, OP_Rewind); VdbeCoverage(v);
|
||||
j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec);
|
||||
j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, 0, j3); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, j2);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1);
|
||||
j5 = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
sqlite3VdbeJumpHere(v, j4);
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
sqlite3VdbeJumpHere(v, j5);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
||||
@@ -686,18 +676,18 @@ void sqlite3Insert(
|
||||
*/
|
||||
int regRec; /* Register to hold packed record */
|
||||
int regTempRowid; /* Register to hold temp table ROWID */
|
||||
int addrTop; /* Label "L" */
|
||||
int addrL; /* Label "L" */
|
||||
|
||||
srcTab = pParse->nTab++;
|
||||
regRec = sqlite3GetTempReg(pParse);
|
||||
regTempRowid = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v);
|
||||
addrL = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
|
||||
sqlite3VdbeJumpHere(v, addrTop);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrL);
|
||||
sqlite3VdbeJumpHere(v, addrL);
|
||||
sqlite3ReleaseTempReg(pParse, regRec);
|
||||
sqlite3ReleaseTempReg(pParse, regTempRowid);
|
||||
}
|
||||
@@ -1275,6 +1265,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
** it might have changed. Skip the conflict logic below if the rowid
|
||||
** is unchanged. */
|
||||
sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
|
||||
@@ -1446,6 +1437,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
** is different from old-rowid */
|
||||
if( isUpdate ){
|
||||
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
}else{
|
||||
@@ -1481,7 +1473,10 @@ void sqlite3GenerateConstraintChecks(
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, op,
|
||||
regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
|
||||
); VdbeCoverage(v);
|
||||
);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
||||
VdbeCoverageIf(v, op==OP_Eq);
|
||||
VdbeCoverageIf(v, op==OP_Ne);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -800,6 +800,7 @@ static void disconnectAllVtab(sqlite3 *db){
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3VtabUnlockList(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
#else
|
||||
UNUSED_PARAMETER(db);
|
||||
|
||||
+13
@@ -275,6 +275,12 @@ static void *memsys5MallocUnsafe(int nByte){
|
||||
if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
|
||||
if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Make sure the allocated memory does not assume that it is set to zero
|
||||
** or retains a value from a previous allocation */
|
||||
memset(&mem5.zPool[i*mem5.szAtom], 0xAA, iFullSz);
|
||||
#endif
|
||||
|
||||
/* Return a pointer to the allocated memory. */
|
||||
return (void*)&mem5.zPool[i*mem5.szAtom];
|
||||
}
|
||||
@@ -332,6 +338,13 @@ static void memsys5FreeUnsafe(void *pOld){
|
||||
}
|
||||
size *= 2;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Overwrite freed memory with the 0x55 bit pattern to verify that it is
|
||||
** not used after being freed */
|
||||
memset(&mem5.zPool[iBlock*mem5.szAtom], 0x55, size);
|
||||
#endif
|
||||
|
||||
memsys5Link(iBlock, iLogsize);
|
||||
}
|
||||
|
||||
|
||||
+59
-23
@@ -323,6 +323,7 @@ static int posixFchown(int fd, uid_t uid, gid_t gid){
|
||||
|
||||
/* Forward reference */
|
||||
static int openDirectory(const char*, int*);
|
||||
static int unixGetpagesize(void);
|
||||
|
||||
/*
|
||||
** Many system calls are accessed through pointer-to-functions so that
|
||||
@@ -446,6 +447,9 @@ static struct unix_syscall {
|
||||
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
|
||||
#endif
|
||||
|
||||
{ "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
|
||||
#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent)
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
|
||||
/*
|
||||
@@ -4105,6 +4109,36 @@ static int unixShmSystemLock(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the system page size.
|
||||
**
|
||||
** This function should not be called directly by other code in this file.
|
||||
** Instead, it should be called via macro osGetpagesize().
|
||||
*/
|
||||
static int unixGetpagesize(void){
|
||||
#if defined(_BSD_SOURCE)
|
||||
return getpagesize();
|
||||
#else
|
||||
return (int)sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the minimum number of 32KB shm regions that should be mapped at
|
||||
** a time, assuming that each mapping must be an integer multiple of the
|
||||
** current system page-size.
|
||||
**
|
||||
** Usually, this is 1. The exception seems to be systems that are configured
|
||||
** to use 64KB pages - in this case each mapping must cover at least two
|
||||
** shm regions.
|
||||
*/
|
||||
static int unixShmRegionPerMap(void){
|
||||
int shmsz = 32*1024; /* SHM region size */
|
||||
int pgsz = osGetpagesize(); /* System page size */
|
||||
assert( ((pgsz-1)&pgsz)==0 ); /* Page size must be a power of 2 */
|
||||
if( pgsz<shmsz ) return 1;
|
||||
return pgsz/shmsz;
|
||||
}
|
||||
|
||||
/*
|
||||
** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
|
||||
@@ -4116,10 +4150,11 @@ static void unixShmPurge(unixFile *pFd){
|
||||
unixShmNode *p = pFd->pInode->pShmNode;
|
||||
assert( unixMutexHeld() );
|
||||
if( p && p->nRef==0 ){
|
||||
int nShmPerMap = unixShmRegionPerMap();
|
||||
int i;
|
||||
assert( p->pInode==pFd->pInode );
|
||||
sqlite3_mutex_free(p->mutex);
|
||||
for(i=0; i<p->nRegion; i++){
|
||||
for(i=0; i<p->nRegion; i+=nShmPerMap){
|
||||
if( p->h>=0 ){
|
||||
osMunmap(p->apRegion[i], p->szRegion);
|
||||
}else{
|
||||
@@ -4326,6 +4361,8 @@ static int unixShmMap(
|
||||
unixShm *p;
|
||||
unixShmNode *pShmNode;
|
||||
int rc = SQLITE_OK;
|
||||
int nShmPerMap = unixShmRegionPerMap();
|
||||
int nReqRegion;
|
||||
|
||||
/* If the shared-memory file has not yet been opened, open it now. */
|
||||
if( pDbFd->pShm==0 ){
|
||||
@@ -4341,9 +4378,12 @@ static int unixShmMap(
|
||||
assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
|
||||
assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
|
||||
|
||||
if( pShmNode->nRegion<=iRegion ){
|
||||
/* Minimum number of regions required to be mapped. */
|
||||
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
|
||||
|
||||
if( pShmNode->nRegion<nReqRegion ){
|
||||
char **apNew; /* New apRegion[] array */
|
||||
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
|
||||
int nByte = nReqRegion*szRegion; /* Minimum required file size */
|
||||
struct stat sStat; /* Used by fstat() */
|
||||
|
||||
pShmNode->szRegion = szRegion;
|
||||
@@ -4392,17 +4432,19 @@ static int unixShmMap(
|
||||
|
||||
/* Map the requested memory region into this processes address space. */
|
||||
apNew = (char **)sqlite3_realloc(
|
||||
pShmNode->apRegion, (iRegion+1)*sizeof(char *)
|
||||
pShmNode->apRegion, nReqRegion*sizeof(char *)
|
||||
);
|
||||
if( !apNew ){
|
||||
rc = SQLITE_IOERR_NOMEM;
|
||||
goto shmpage_out;
|
||||
}
|
||||
pShmNode->apRegion = apNew;
|
||||
while(pShmNode->nRegion<=iRegion){
|
||||
while( pShmNode->nRegion<nReqRegion ){
|
||||
int nMap = szRegion*nShmPerMap;
|
||||
int i;
|
||||
void *pMem;
|
||||
if( pShmNode->h>=0 ){
|
||||
pMem = osMmap(0, szRegion,
|
||||
pMem = osMmap(0, nMap,
|
||||
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
|
||||
);
|
||||
@@ -4418,8 +4460,11 @@ static int unixShmMap(
|
||||
}
|
||||
memset(pMem, 0, szRegion);
|
||||
}
|
||||
pShmNode->apRegion[pShmNode->nRegion] = pMem;
|
||||
pShmNode->nRegion++;
|
||||
|
||||
for(i=0; i<nShmPerMap; i++){
|
||||
pShmNode->apRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i];
|
||||
}
|
||||
pShmNode->nRegion += nShmPerMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4633,19 +4678,6 @@ static void unixUnmapfile(unixFile *pFd){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the system page size.
|
||||
*/
|
||||
static int unixGetPagesize(void){
|
||||
#if HAVE_MREMAP
|
||||
return 512;
|
||||
#elif defined(_BSD_SOURCE)
|
||||
return getpagesize();
|
||||
#else
|
||||
return (int)sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to set the size of the memory mapping maintained by file
|
||||
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
|
||||
@@ -4682,8 +4714,12 @@ static void unixRemapfile(
|
||||
if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
|
||||
|
||||
if( pOrig ){
|
||||
const int szSyspage = unixGetPagesize();
|
||||
#if HAVE_MREMAP
|
||||
i64 nReuse = pFd->mmapSize;
|
||||
#else
|
||||
const int szSyspage = osGetpagesize();
|
||||
i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
|
||||
#endif
|
||||
u8 *pReq = &pOrig[nReuse];
|
||||
|
||||
/* Unmap any pages of the existing mapping that cannot be reused. */
|
||||
@@ -7429,7 +7465,7 @@ int sqlite3_os_init(void){
|
||||
|
||||
/* Double-check that the aSyscall[] array has been constructed
|
||||
** correctly. See ticket [bb3a86e890c8e96ab] */
|
||||
assert( ArraySize(aSyscall)==24 );
|
||||
assert( ArraySize(aSyscall)==25 );
|
||||
|
||||
/* Register all VFSes defined in the aVfs[] array */
|
||||
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
|
||||
|
||||
+25
-5
@@ -5135,15 +5135,29 @@ static int winFullPathname(
|
||||
** Interfaces for opening a shared library, finding entry points
|
||||
** within the shared library, and closing the shared library.
|
||||
*/
|
||||
/*
|
||||
** Interfaces for opening a shared library, finding entry points
|
||||
** within the shared library, and closing the shared library.
|
||||
*/
|
||||
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
|
||||
HANDLE h;
|
||||
#if defined(__CYGWIN__)
|
||||
int nFull = pVfs->mxPathname+1;
|
||||
char *zFull = sqlite3MallocZero( nFull );
|
||||
void *zConverted = 0;
|
||||
if( zFull==0 ){
|
||||
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
||||
return 0;
|
||||
}
|
||||
if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
|
||||
sqlite3_free(zFull);
|
||||
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
||||
return 0;
|
||||
}
|
||||
zConverted = winConvertFromUtf8Filename(zFull);
|
||||
sqlite3_free(zFull);
|
||||
#else
|
||||
void *zConverted = winConvertFromUtf8Filename(zFilename);
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
#endif
|
||||
if( zConverted==0 ){
|
||||
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
||||
return 0;
|
||||
}
|
||||
if( osIsNT() ){
|
||||
@@ -5158,6 +5172,7 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
|
||||
h = osLoadLibraryA((char*)zConverted);
|
||||
}
|
||||
#endif
|
||||
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h));
|
||||
sqlite3_free(zConverted);
|
||||
return (void*)h;
|
||||
}
|
||||
@@ -5166,12 +5181,17 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
|
||||
winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
|
||||
}
|
||||
static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
|
||||
FARPROC proc;
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
|
||||
proc = osGetProcAddressA((HANDLE)pH, zSym);
|
||||
OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n",
|
||||
(void*)pH, zSym, (void*)proc));
|
||||
return (void(*)(void))proc;
|
||||
}
|
||||
static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
osFreeLibrary((HANDLE)pHandle);
|
||||
OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle));
|
||||
}
|
||||
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
|
||||
#define winDlOpen 0
|
||||
|
||||
+9
-7
@@ -4889,15 +4889,17 @@ static int hasHotJournal(Pager *pPager, int *pExists){
|
||||
if( rc==SQLITE_OK && !locked ){
|
||||
Pgno nPage; /* Number of pages in database file */
|
||||
|
||||
/* Check the size of the database file. If it consists of 0 pages,
|
||||
** then delete the journal file. See the header comment above for
|
||||
** the reasoning here. Delete the obsolete journal file under
|
||||
** a RESERVED lock to avoid race conditions and to avoid violating
|
||||
** [H33020].
|
||||
*/
|
||||
rc = pagerPagecount(pPager, &nPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( nPage==0 ){
|
||||
/* If the database is zero pages in size, that means that either (1) the
|
||||
** journal is a remnant from a prior database with the same name where
|
||||
** the database file but not the journal was deleted, or (2) the initial
|
||||
** transaction that populates a new database is being rolled back.
|
||||
** In either case, the journal file can be deleted. However, take care
|
||||
** not to delete the journal file if it is already open due to
|
||||
** journal_mode=PERSIST.
|
||||
*/
|
||||
if( nPage==0 && !jrnlOpen ){
|
||||
sqlite3BeginBenignMalloc();
|
||||
if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
|
||||
sqlite3OsDelete(pVfs, pPager->zJournal, 0);
|
||||
|
||||
+12
-4
@@ -437,14 +437,22 @@ select(A) ::= with(W) selectnowith(X). {
|
||||
selectnowith(A) ::= oneselect(X). {A = X;}
|
||||
%ifndef SQLITE_OMIT_COMPOUND_SELECT
|
||||
selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). {
|
||||
if( Z ){
|
||||
Z->op = (u8)Y;
|
||||
Z->pPrior = X;
|
||||
Select *pRhs = Z;
|
||||
if( pRhs && pRhs->pPrior ){
|
||||
SrcList *pFrom;
|
||||
Token x;
|
||||
x.n = 0;
|
||||
pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
|
||||
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0);
|
||||
}
|
||||
if( pRhs ){
|
||||
pRhs->op = (u8)Y;
|
||||
pRhs->pPrior = X;
|
||||
if( Y!=TK_ALL ) pParse->hasCompound = 1;
|
||||
}else{
|
||||
sqlite3SelectDelete(pParse->db, X);
|
||||
}
|
||||
A = Z;
|
||||
A = pRhs;
|
||||
}
|
||||
%type multiselect_op {int}
|
||||
multiselect_op(A) ::= UNION(OP). {A = @OP;}
|
||||
|
||||
+4
-3
@@ -824,7 +824,7 @@ void sqlite3Pragma(
|
||||
** size of historical compatibility.
|
||||
*/
|
||||
case PragTyp_DEFAULT_CACHE_SIZE: {
|
||||
static const int iLn = __LINE__+2;
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList getCacheSize[] = {
|
||||
{ OP_Transaction, 0, 0, 0}, /* 0 */
|
||||
{ OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */
|
||||
@@ -1087,7 +1087,7 @@ void sqlite3Pragma(
|
||||
** file. Before writing to meta[6], check that meta[3] indicates
|
||||
** that this really is an auto-vacuum capable database.
|
||||
*/
|
||||
static const int iLn = __LINE__+2;
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList setMeta6[] = {
|
||||
{ OP_Transaction, 0, 1, 0}, /* 0 */
|
||||
{ OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
|
||||
@@ -1790,7 +1790,7 @@ void sqlite3Pragma(
|
||||
** messages have been generated, output OK. Otherwise output the
|
||||
** error message
|
||||
*/
|
||||
static const int iLn = __LINE__+2;
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList endCode[] = {
|
||||
{ OP_AddImm, 1, 0, 0}, /* 0 */
|
||||
{ OP_IfNeg, 1, 0, 0}, /* 1 */
|
||||
@@ -1942,6 +1942,7 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
|
||||
sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
|
||||
|
||||
+84
-77
@@ -134,20 +134,6 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
|
||||
}
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
|
||||
/*
|
||||
** Append N space characters to the given string buffer.
|
||||
*/
|
||||
void sqlite3AppendSpace(StrAccum *pAccum, int N){
|
||||
static const char zSpaces[] = " ";
|
||||
while( N>=(int)sizeof(zSpaces)-1 ){
|
||||
sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
|
||||
N -= sizeof(zSpaces)-1;
|
||||
}
|
||||
if( N>0 ){
|
||||
sqlite3StrAccumAppend(pAccum, zSpaces, N);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the StrAccum object to an error mode.
|
||||
*/
|
||||
@@ -237,11 +223,9 @@ void sqlite3VXPrintf(
|
||||
}
|
||||
for(; (c=(*fmt))!=0; ++fmt){
|
||||
if( c!='%' ){
|
||||
int amt;
|
||||
bufpt = (char *)fmt;
|
||||
amt = 1;
|
||||
while( (c=(*++fmt))!='%' && c!=0 ) amt++;
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, amt);
|
||||
while( (c=(*++fmt))!='%' && c!=0 ){};
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt));
|
||||
if( c==0 ) break;
|
||||
}
|
||||
if( (c=(*++fmt))==0 ){
|
||||
@@ -422,10 +406,8 @@ void sqlite3VXPrintf(
|
||||
*(--bufpt) = zOrd[x*2];
|
||||
}
|
||||
{
|
||||
register const char *cset; /* Use registers for speed */
|
||||
register int base;
|
||||
cset = &aDigits[infop->charset];
|
||||
base = infop->base;
|
||||
const char *cset = &aDigits[infop->charset];
|
||||
u8 base = infop->base;
|
||||
do{ /* Convert to ascii */
|
||||
*(--bufpt) = cset[longvalue%base];
|
||||
longvalue = longvalue/base;
|
||||
@@ -729,29 +711,89 @@ void sqlite3VXPrintf(
|
||||
** "length" characters long. The field width is "width". Do
|
||||
** the output.
|
||||
*/
|
||||
if( !flag_leftjustify ){
|
||||
register int nspace;
|
||||
nspace = width-length;
|
||||
if( nspace>0 ){
|
||||
sqlite3AppendSpace(pAccum, nspace);
|
||||
}
|
||||
}
|
||||
if( length>0 ){
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, length);
|
||||
}
|
||||
if( flag_leftjustify ){
|
||||
register int nspace;
|
||||
nspace = width-length;
|
||||
if( nspace>0 ){
|
||||
sqlite3AppendSpace(pAccum, nspace);
|
||||
}
|
||||
}
|
||||
width -= length;
|
||||
if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, length);
|
||||
if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
|
||||
|
||||
if( zExtra ) sqlite3_free(zExtra);
|
||||
}/* End for loop over the format string */
|
||||
} /* End of function */
|
||||
|
||||
/*
|
||||
** Append N bytes of text from z to the StrAccum object.
|
||||
** Enlarge the memory allocation on a StrAccum object so that it is
|
||||
** able to accept at least N more bytes of text.
|
||||
**
|
||||
** Return the number of bytes of text that StrAccum is able to accept
|
||||
** after the attempted enlargement. The value returned might be zero.
|
||||
*/
|
||||
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
char *zNew;
|
||||
assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
|
||||
if( p->accError ){
|
||||
testcase(p->accError==STRACCUM_TOOBIG);
|
||||
testcase(p->accError==STRACCUM_NOMEM);
|
||||
return 0;
|
||||
}
|
||||
if( !p->useMalloc ){
|
||||
N = p->nAlloc - p->nChar - 1;
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
return N;
|
||||
}else{
|
||||
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
|
||||
i64 szNew = p->nChar;
|
||||
szNew += N + 1;
|
||||
if( szNew > p->mxAlloc ){
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
return 0;
|
||||
}else{
|
||||
p->nAlloc = (int)szNew;
|
||||
}
|
||||
if( p->useMalloc==1 ){
|
||||
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
|
||||
}else{
|
||||
zNew = sqlite3_realloc(zOld, p->nAlloc);
|
||||
}
|
||||
if( zNew ){
|
||||
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
||||
p->zText = zNew;
|
||||
}else{
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return N;
|
||||
}
|
||||
|
||||
/*
|
||||
** Append N space characters to the given string buffer.
|
||||
*/
|
||||
void sqlite3AppendSpace(StrAccum *p, int N){
|
||||
if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
|
||||
while( (N--)>0 ) p->zText[p->nChar++] = ' ';
|
||||
}
|
||||
|
||||
/*
|
||||
** The StrAccum "p" is not large enough to accept N new bytes of z[].
|
||||
** So enlarge if first, then do the append.
|
||||
**
|
||||
** This is a helper routine to sqlite3StrAccumAppend() that does special-case
|
||||
** work (enlarging the buffer) using tail recursion, so that the
|
||||
** sqlite3StrAccumAppend() routine can use fast calling semantics.
|
||||
*/
|
||||
static void enlargeAndAppend(StrAccum *p, const char *z, int N){
|
||||
N = sqlite3StrAccumEnlarge(p, N);
|
||||
if( N>0 ){
|
||||
memcpy(&p->zText[p->nChar], z, N);
|
||||
p->nChar += N;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Append N bytes of text from z to the StrAccum object. Increase the
|
||||
** size of the memory allocation for StrAccum if necessary.
|
||||
*/
|
||||
void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
assert( z!=0 );
|
||||
@@ -759,43 +801,8 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
assert( N>=0 );
|
||||
assert( p->accError==0 || p->nAlloc==0 );
|
||||
if( p->nChar+N >= p->nAlloc ){
|
||||
char *zNew;
|
||||
if( p->accError ){
|
||||
testcase(p->accError==STRACCUM_TOOBIG);
|
||||
testcase(p->accError==STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
if( !p->useMalloc ){
|
||||
N = p->nAlloc - p->nChar - 1;
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
if( N<=0 ){
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
|
||||
i64 szNew = p->nChar;
|
||||
szNew += N + 1;
|
||||
if( szNew > p->mxAlloc ){
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
return;
|
||||
}else{
|
||||
p->nAlloc = (int)szNew;
|
||||
}
|
||||
if( p->useMalloc==1 ){
|
||||
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
|
||||
}else{
|
||||
zNew = sqlite3_realloc(zOld, p->nAlloc);
|
||||
}
|
||||
if( zNew ){
|
||||
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
||||
p->zText = zNew;
|
||||
}else{
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
enlargeAndAppend(p,z,N);
|
||||
return;
|
||||
}
|
||||
assert( p->zText );
|
||||
memcpy(&p->zText[p->nChar], z, N);
|
||||
|
||||
@@ -337,6 +337,8 @@ static int lookupName(
|
||||
}else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
|
||||
pExpr->iTable = 0;
|
||||
pTab = pParse->pTriggerTab;
|
||||
}else{
|
||||
pTab = 0;
|
||||
}
|
||||
|
||||
if( pTab ){
|
||||
|
||||
+9
-7
@@ -609,7 +609,7 @@ static void selectInnerLoop(
|
||||
** values returned by the SELECT are not required.
|
||||
*/
|
||||
sqlite3ExprCodeExprList(pParse, pEList, regResult,
|
||||
(eDest==SRT_Output)?SQLITE_ECEL_DUP:0);
|
||||
(eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0);
|
||||
}
|
||||
|
||||
/* If the DISTINCT keyword was present on the SELECT statement
|
||||
@@ -818,14 +818,16 @@ static void selectInnerLoop(
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
r2 = sqlite3GetTempRange(pParse, nKey+2);
|
||||
r3 = r2+nKey+1;
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3);
|
||||
if( eDest==SRT_DistQueue ){
|
||||
/* If the destination is DistQueue, then cursor (iParm+1) is open
|
||||
** on a second ephemeral index that holds all values every previously
|
||||
** added to the queue. Only add this new value if it has never before
|
||||
** been added */
|
||||
addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
|
||||
** added to the queue. */
|
||||
addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0,
|
||||
regResult, nResultCol);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3);
|
||||
if( eDest==SRT_DistQueue ){
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
}
|
||||
@@ -1520,7 +1522,7 @@ static int selectColumnsFromExprList(
|
||||
char *zNewName;
|
||||
int k;
|
||||
for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
|
||||
if( zName[k]==':' ) nName = k;
|
||||
if( k>=0 && zName[k]==':' ) nName = k;
|
||||
zName[nName] = 0;
|
||||
zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
|
||||
sqlite3DbFree(db, zName);
|
||||
@@ -4595,7 +4597,7 @@ int sqlite3Select(
|
||||
/* If the subquery is not correlated and if we are not inside of
|
||||
** a trigger, then we only need to compute the value of the subquery
|
||||
** once. */
|
||||
onceAddr = sqlite3CodeOnce(pParse);
|
||||
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}else{
|
||||
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
|
||||
+47
-10
@@ -65,7 +65,9 @@
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# include <io.h>
|
||||
#define isatty(h) _isatty(h)
|
||||
#define access(f,m) _access((f),(m))
|
||||
#ifndef access
|
||||
# define access(f,m) _access((f),(m))
|
||||
#endif
|
||||
#undef popen
|
||||
#define popen _popen
|
||||
#undef pclose
|
||||
@@ -444,6 +446,7 @@ struct previous_mode_data {
|
||||
struct callback_data {
|
||||
sqlite3 *db; /* The database */
|
||||
int echoOn; /* True to echo input commands */
|
||||
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL statement */
|
||||
int statsOn; /* True to display memory stats before each finalize */
|
||||
int cnt; /* Number of records displayed so far */
|
||||
FILE *out; /* Write results here */
|
||||
@@ -1008,7 +1011,7 @@ static int run_table_dump_query(
|
||||
int nResult;
|
||||
int i;
|
||||
const char *z;
|
||||
rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
|
||||
rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
|
||||
if( rc!=SQLITE_OK || !pSelect ){
|
||||
fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
|
||||
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
|
||||
@@ -1181,6 +1184,7 @@ static int str_in_array(const char *zStr, const char **azArray){
|
||||
** * For each "Goto", if the jump destination is earlier in the program
|
||||
** and ends on one of:
|
||||
** Yield SeekGt SeekLt RowSetRead Rewind
|
||||
** or if the P1 parameter is one instead of zero,
|
||||
** then indent all opcodes between the earlier instruction
|
||||
** and "Goto" by 2 spaces.
|
||||
*/
|
||||
@@ -1228,7 +1232,9 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
|
||||
if( str_in_array(zOp, azNext) ){
|
||||
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
}
|
||||
if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){
|
||||
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
|
||||
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
|
||||
){
|
||||
for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
}
|
||||
}
|
||||
@@ -1300,6 +1306,23 @@ static int shell_exec(
|
||||
fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
|
||||
}
|
||||
|
||||
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
|
||||
if( pArg && pArg->autoEQP ){
|
||||
sqlite3_stmt *pExplain;
|
||||
char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", sqlite3_sql(pStmt));
|
||||
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
while( sqlite3_step(pExplain)==SQLITE_ROW ){
|
||||
fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0));
|
||||
fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
|
||||
fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
|
||||
fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pExplain);
|
||||
sqlite3_free(zEQP);
|
||||
}
|
||||
|
||||
/* Output TESTCTRL_EXPLAIN text of requested */
|
||||
if( pArg && pArg->mode==MODE_Explain ){
|
||||
const char *zExplain = 0;
|
||||
@@ -1456,7 +1479,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
zTableInfo = appendText(zTableInfo, zTable, '"');
|
||||
zTableInfo = appendText(zTableInfo, ");", 0);
|
||||
|
||||
rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
|
||||
rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0);
|
||||
free(zTableInfo);
|
||||
if( rc!=SQLITE_OK || !pTableInfo ){
|
||||
return 1;
|
||||
@@ -1893,7 +1916,7 @@ static char *csv_read_one_field(CSVReader *p){
|
||||
}
|
||||
if( c=='\n' ){
|
||||
p->nLine++;
|
||||
if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--;
|
||||
if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
|
||||
}
|
||||
p->cTerm = c;
|
||||
}
|
||||
@@ -2299,6 +2322,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
p->echoOn = booleanValue(azArg[1]);
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 && nArg>1 && nArg<3 ){
|
||||
p->autoEQP = booleanValue(azArg[1]);
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
|
||||
if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
|
||||
rc = 2;
|
||||
@@ -2399,7 +2426,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
return 1;
|
||||
}
|
||||
nByte = strlen30(zSql);
|
||||
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
|
||||
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
|
||||
char cSep = '(';
|
||||
@@ -2425,7 +2452,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
xCloser(sCsv.in);
|
||||
return 1;
|
||||
}
|
||||
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
@@ -2452,7 +2479,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
}
|
||||
zSql[j++] = ')';
|
||||
zSql[j] = 0;
|
||||
rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
|
||||
@@ -2871,6 +2898,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
|
||||
int i;
|
||||
fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
|
||||
fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
|
||||
fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
|
||||
fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
|
||||
fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
|
||||
@@ -3548,11 +3576,13 @@ int main(int argc, char **argv){
|
||||
int rc = 0;
|
||||
int warnInmemoryDb = 0;
|
||||
|
||||
#if USE_SYSTEM_SQLITE+0!=1
|
||||
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
|
||||
fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
|
||||
sqlite3_sourceid(), SQLITE_SOURCE_ID);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
Argv0 = argv[0];
|
||||
main_init(&data);
|
||||
stdin_is_interactive = isatty(0);
|
||||
@@ -3645,6 +3675,11 @@ int main(int argc, char **argv){
|
||||
#else
|
||||
fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef SQLITE_SHELL_DBNAME_PROC
|
||||
{ extern void SQLITE_SHELL_DBNAME_PROC(const char**);
|
||||
SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
|
||||
warnInmemoryDb = 0; }
|
||||
#endif
|
||||
}
|
||||
data.out = stdout;
|
||||
@@ -3701,6 +3736,8 @@ int main(int argc, char **argv){
|
||||
data.showHeader = 0;
|
||||
}else if( strcmp(z,"-echo")==0 ){
|
||||
data.echoOn = 1;
|
||||
}else if( strcmp(z,"-eqp")==0 ){
|
||||
data.autoEQP = 1;
|
||||
}else if( strcmp(z,"-stats")==0 ){
|
||||
data.statsOn = 1;
|
||||
}else if( strcmp(z,"-bail")==0 ){
|
||||
@@ -3783,8 +3820,8 @@ int main(int argc, char **argv){
|
||||
);
|
||||
if( warnInmemoryDb ){
|
||||
printf("Connected to a ");
|
||||
printBold("transient in-memory database.");
|
||||
printf("\nUse \".open FILENAME\" to reopen on a "
|
||||
printBold("transient in-memory database");
|
||||
printf(".\nUse \".open FILENAME\" to reopen on a "
|
||||
"persistent database.\n");
|
||||
}
|
||||
zHome = find_home_dir();
|
||||
|
||||
+52
-11
@@ -12,7 +12,6 @@
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
*/
|
||||
#include "sqlite3.h"
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
|
||||
@@ -48,6 +47,44 @@
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For MinGW, check to see if we can include the header file containing its
|
||||
** version information, among other things. Normally, this internal MinGW
|
||||
** header file would [only] be included automatically by other MinGW header
|
||||
** files; however, the contained version information is now required by this
|
||||
** header file to work around binary compatibility issues (see below) and
|
||||
** this is the only known way to reliably obtain it. This entire #if block
|
||||
** would be completely unnecessary if there was any other way of detecting
|
||||
** MinGW via their preprocessor (e.g. if they customized their GCC to define
|
||||
** some MinGW-specific macros). When compiling for MinGW, either the
|
||||
** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be
|
||||
** defined; otherwise, detection of conditions specific to MinGW will be
|
||||
** disabled.
|
||||
*/
|
||||
#if defined(_HAVE_MINGW_H)
|
||||
# include "mingw.h"
|
||||
#elif defined(_HAVE__MINGW_H)
|
||||
# include "_mingw.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T
|
||||
** define is required to maintain binary compatibility with the MSVC runtime
|
||||
** library in use (e.g. for Windows XP).
|
||||
*/
|
||||
#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
|
||||
defined(_WIN32) && !defined(_WIN64) && \
|
||||
defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
|
||||
defined(__MSVCRT__)
|
||||
# define _USE_32BIT_TIME_T
|
||||
#endif
|
||||
|
||||
/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
|
||||
** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
|
||||
** MinGW.
|
||||
*/
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
** Include the configuration header output by 'configure' if we're using the
|
||||
** autoconf-based build
|
||||
@@ -1314,10 +1351,16 @@ struct CollSeq {
|
||||
/*
|
||||
** Additional bit values that can be ORed with an affinity without
|
||||
** changing the affinity.
|
||||
**
|
||||
** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
|
||||
** It causes an assert() to fire if either operand to a comparison
|
||||
** operator is NULL. It is added to certain comparison operators to
|
||||
** prove that the operands are always NOT NULL.
|
||||
*/
|
||||
#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */
|
||||
#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */
|
||||
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
|
||||
#define SQLITE_NOTNULL 0x88 /* Assert that operands are never NULL */
|
||||
|
||||
/*
|
||||
** An object of this type is created for each virtual table present in
|
||||
@@ -1576,19 +1619,19 @@ struct KeyInfo {
|
||||
**
|
||||
** This structure holds a record that has already been disassembled
|
||||
** into its constituent fields.
|
||||
**
|
||||
** The r1 and r2 member variables are only used by the optimized comparison
|
||||
** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
|
||||
*/
|
||||
struct UnpackedRecord {
|
||||
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
||||
u16 nField; /* Number of entries in apMem[] */
|
||||
u8 flags; /* Boolean settings. UNPACKED_... below */
|
||||
i8 default_rc; /* Comparison result if keys are equal */
|
||||
Mem *aMem; /* Values */
|
||||
int r1; /* Value to return if (lhs > rhs) */
|
||||
int r2; /* Value to return if (rhs < lhs) */
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values of UnpackedRecord.flags
|
||||
*/
|
||||
#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */
|
||||
#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */
|
||||
|
||||
/*
|
||||
** Each SQL index is represented in memory by an
|
||||
@@ -2008,8 +2051,8 @@ typedef u64 Bitmask;
|
||||
** contains more than 63 columns and the 64-th or later column is used.
|
||||
*/
|
||||
struct SrcList {
|
||||
u8 nSrc; /* Number of tables or subqueries in the FROM clause */
|
||||
u8 nAlloc; /* Number of entries allocated in a[] below */
|
||||
int nSrc; /* Number of tables or subqueries in the FROM clause */
|
||||
u32 nAlloc; /* Number of entries allocated in a[] below */
|
||||
struct SrcList_item {
|
||||
Schema *pSchema; /* Schema to which this item is fixed */
|
||||
char *zDatabase; /* Name of database holding this table */
|
||||
@@ -2348,7 +2391,6 @@ struct Parse {
|
||||
u8 checkSchema; /* Causes schema cookie check after an error */
|
||||
u8 nested; /* Number of nested calls to the parser/code generator */
|
||||
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
|
||||
u8 nTempInUse; /* Number of aTempReg[] currently checked out */
|
||||
u8 nColCache; /* Number of entries in aColCache[] */
|
||||
u8 iColCache; /* Next entry in aColCache[] to replace */
|
||||
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
|
||||
@@ -3087,7 +3129,6 @@ int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*);
|
||||
int sqlite3ExprIsInteger(Expr*, int*);
|
||||
int sqlite3ExprCanBeNull(const Expr*);
|
||||
void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
|
||||
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||
int sqlite3IsRowid(const char*);
|
||||
void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
|
||||
|
||||
@@ -76,7 +76,6 @@ static int test_value_overhead(
|
||||
|
||||
val.flags = MEM_Str|MEM_Term|MEM_Static;
|
||||
val.z = "hello world";
|
||||
val.memType = MEM_Str;
|
||||
val.enc = SQLITE_UTF8;
|
||||
|
||||
for(i=0; i<repeat_count; i++){
|
||||
|
||||
@@ -499,7 +499,6 @@ static void test_extract(
|
||||
mem.enc = ENC(db);
|
||||
pHdr += sqlite3GetVarint(pHdr, &iSerialType);
|
||||
pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
|
||||
sqlite3VdbeMemStoreType(&mem);
|
||||
|
||||
if( iCurrent==iIdx ){
|
||||
sqlite3_result_value(context, &mem);
|
||||
@@ -549,7 +548,6 @@ static void test_decode(
|
||||
pHdr += sqlite3GetVarint(pHdr, &iSerialType);
|
||||
pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
|
||||
|
||||
sqlite3VdbeMemStoreType(&mem);
|
||||
switch( sqlite3_value_type(&mem) ){
|
||||
case SQLITE_TEXT:
|
||||
pVal = Tcl_NewStringObj((const char*)sqlite3_value_text(&mem), -1);
|
||||
|
||||
@@ -91,6 +91,9 @@ static void statusFunc(
|
||||
/*
|
||||
** Extension load function.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int testloadext_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
@@ -109,6 +112,9 @@ int testloadext_init(
|
||||
/*
|
||||
** Another extension entry point. This one always fails.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int testbrokenext_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
|
||||
+48
-1
@@ -67,6 +67,11 @@
|
||||
** test_syscall list
|
||||
** Return a list of all system calls. The list is constructed using
|
||||
** the xNextSystemCall() VFS method.
|
||||
**
|
||||
** test_syscall pagesize PGSZ
|
||||
** If PGSZ is a power of two greater than 256, install a wrapper around
|
||||
** OS function getpagesize() that reports the system page size as PGSZ.
|
||||
** Or, if PGSZ is less than zero, remove any wrapper already installed.
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
@@ -89,7 +94,9 @@ static struct TestSyscallGlobal {
|
||||
int bPersist; /* 1 for persistent errors, 0 for transient */
|
||||
int nCount; /* Fail after this many more calls */
|
||||
int nFail; /* Number of failures that have occurred */
|
||||
} gSyscall = { 0, 0 };
|
||||
int pgsz;
|
||||
sqlite3_syscall_ptr orig_getpagesize;
|
||||
} gSyscall = { 0, 0, 0, 0, 0 };
|
||||
|
||||
static int ts_open(const char *, int, int);
|
||||
static int ts_close(int fd);
|
||||
@@ -650,6 +657,45 @@ static int test_syscall_defaultvfs(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int ts_getpagesize(void){
|
||||
return gSyscall.pgsz;
|
||||
}
|
||||
|
||||
static int test_syscall_pagesize(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
||||
int pgsz;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "PGSZ");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &pgsz) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( pgsz<0 ){
|
||||
if( gSyscall.orig_getpagesize ){
|
||||
pVfs->xSetSystemCall(pVfs, "getpagesize", gSyscall.orig_getpagesize);
|
||||
}
|
||||
}else{
|
||||
if( pgsz<512 || (pgsz & (pgsz-1)) ){
|
||||
Tcl_AppendResult(interp, "pgsz out of range", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
gSyscall.orig_getpagesize = pVfs->xGetSystemCall(pVfs, "getpagesize");
|
||||
gSyscall.pgsz = pgsz;
|
||||
pVfs->xSetSystemCall(
|
||||
pVfs, "getpagesize", (sqlite3_syscall_ptr)ts_getpagesize
|
||||
);
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int test_syscall(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
@@ -668,6 +714,7 @@ static int test_syscall(
|
||||
{ "exists", test_syscall_exists },
|
||||
{ "list", test_syscall_list },
|
||||
{ "defaultvfs", test_syscall_defaultvfs },
|
||||
{ "pagesize", test_syscall_pagesize },
|
||||
{ 0, 0 }
|
||||
};
|
||||
int iCmd;
|
||||
|
||||
+1
-1
@@ -566,7 +566,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
||||
assert( pTable!=0 );
|
||||
if( (v = sqlite3GetVdbe(pParse))!=0 ){
|
||||
int base;
|
||||
static const int iLn = __LINE__+2;
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList dropTrigger[] = {
|
||||
{ OP_Rewind, 0, ADDR(9), 0},
|
||||
{ OP_String8, 0, 1, 0}, /* 1 */
|
||||
|
||||
+2
-3
@@ -434,7 +434,7 @@ void sqlite3Update(
|
||||
if( aToOpen[iDataCur-iBaseCur] ){
|
||||
assert( pPk!=0 );
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageNeverTaken(v);
|
||||
}
|
||||
labelContinue = labelBreak;
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
|
||||
@@ -577,11 +577,10 @@ void sqlite3Update(
|
||||
if( bReplace || chngKey ){
|
||||
if( pPk ){
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
|
||||
VdbeCoverage(v);
|
||||
}else{
|
||||
j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
VdbeCoverageNeverTaken(v);
|
||||
}
|
||||
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
|
||||
|
||||
|
||||
@@ -317,7 +317,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
|
||||
pMem->enc = desiredEnc;
|
||||
pMem->flags |= (MEM_Term|MEM_Dyn);
|
||||
pMem->flags |= (MEM_Term);
|
||||
pMem->z = (char*)zOut;
|
||||
pMem->zMalloc = pMem->z;
|
||||
|
||||
@@ -445,7 +445,6 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
|
||||
}
|
||||
assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
|
||||
assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
|
||||
assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
|
||||
assert( m.z || db->mallocFailed );
|
||||
return m.z;
|
||||
}
|
||||
|
||||
+60
-47
@@ -28,7 +28,7 @@
|
||||
** pointer to the string or blob, not the content. If the original
|
||||
** is changed while the copy is still in use, the string or blob might
|
||||
** be changed out from under the copy. This macro verifies that nothing
|
||||
** like that every happens.
|
||||
** like that ever happens.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
|
||||
@@ -108,15 +108,31 @@ int sqlite3_found_count = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Invoke the VDBE coverage callback, if defined
|
||||
** Invoke the VDBE coverage callback, if that callback is defined. This
|
||||
** feature is used for test suite validation only and does not appear an
|
||||
** production builds.
|
||||
**
|
||||
** M is an integer, 2 or 3, that indices how many different ways the
|
||||
** branch can go. It is usually 2. "I" is the direction the branch
|
||||
** goes. 0 means falls through. 1 means branch is taken. 2 means the
|
||||
** second alternative branch is taken.
|
||||
*/
|
||||
#if !defined(SQLITE_VDBE_COVERAGE)
|
||||
# define VdbeBranchTaken(I,M)
|
||||
#else
|
||||
# define VdbeBranchTaken(I,M) \
|
||||
if( sqlite3GlobalConfig.xVdbeBranch!=0 ){ \
|
||||
sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, \
|
||||
pOp->iSrcLine,(I),(M)); }
|
||||
# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
|
||||
static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){
|
||||
if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){
|
||||
M = iSrcLine;
|
||||
/* Assert the truth of VdbeCoverageAlwaysTaken() and
|
||||
** VdbeCoverageNeverTaken() */
|
||||
assert( (M & I)==I );
|
||||
}else{
|
||||
if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
|
||||
sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
|
||||
iSrcLine,I,M);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -136,7 +152,7 @@ int sqlite3_found_count = 0;
|
||||
**
|
||||
** This routine converts an ephemeral string into a dynamically allocated
|
||||
** string that the register itself controls. In other words, it
|
||||
** converts an MEM_Ephem string into an MEM_Dyn string.
|
||||
** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
|
||||
*/
|
||||
#define Deephemeralize(P) \
|
||||
if( ((P)->flags&MEM_Ephem)!=0 \
|
||||
@@ -277,7 +293,6 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){
|
||||
if( eType==SQLITE_TEXT ){
|
||||
Mem *pMem = (Mem*)pVal;
|
||||
applyNumericAffinity(pMem);
|
||||
sqlite3VdbeMemStoreType(pMem);
|
||||
eType = sqlite3_value_type(pVal);
|
||||
}
|
||||
return eType;
|
||||
@@ -476,7 +491,6 @@ int sqlite3VdbeExec(
|
||||
i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
|
||||
#ifdef VDBE_PROFILE
|
||||
u64 start; /* CPU clock count at start of opcode */
|
||||
int origPc; /* Program counter at start of opcode */
|
||||
#endif
|
||||
/*** INSERT STACK UNION HERE ***/
|
||||
|
||||
@@ -538,7 +552,6 @@ int sqlite3VdbeExec(
|
||||
assert( pc>=0 && pc<p->nOp );
|
||||
if( db->mallocFailed ) goto no_mem;
|
||||
#ifdef VDBE_PROFILE
|
||||
origPc = pc;
|
||||
start = sqlite3Hwtime();
|
||||
#endif
|
||||
nVmStep++;
|
||||
@@ -586,18 +599,21 @@ int sqlite3VdbeExec(
|
||||
assert( pOp->p1>0 );
|
||||
assert( pOp->p1<=(p->nMem-p->nCursor) );
|
||||
assert( memIsValid(&aMem[pOp->p1]) );
|
||||
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
|
||||
REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
|
||||
}
|
||||
if( (pOp->opflags & OPFLG_IN2)!=0 ){
|
||||
assert( pOp->p2>0 );
|
||||
assert( pOp->p2<=(p->nMem-p->nCursor) );
|
||||
assert( memIsValid(&aMem[pOp->p2]) );
|
||||
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
|
||||
REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
|
||||
}
|
||||
if( (pOp->opflags & OPFLG_IN3)!=0 ){
|
||||
assert( pOp->p3>0 );
|
||||
assert( pOp->p3<=(p->nMem-p->nCursor) );
|
||||
assert( memIsValid(&aMem[pOp->p3]) );
|
||||
assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
|
||||
REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
|
||||
}
|
||||
if( (pOp->opflags & OPFLG_OUT2)!=0 ){
|
||||
@@ -655,6 +671,11 @@ int sqlite3VdbeExec(
|
||||
** The next instruction executed will be
|
||||
** the one at index P2 from the beginning of
|
||||
** the program.
|
||||
**
|
||||
** The P1 parameter is not actually used by this opcode. However, it
|
||||
** is sometimes set to 1 instead of 0 as a hint to the command-line shell
|
||||
** that this Goto is the bottom of a loop and that the lines from P2 down
|
||||
** to the current line should be indented for EXPLAIN output.
|
||||
*/
|
||||
case OP_Goto: { /* jump */
|
||||
pc = pOp->p2 - 1;
|
||||
@@ -699,7 +720,7 @@ check_for_interrupt:
|
||||
case OP_Gosub: { /* jump */
|
||||
assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( (pIn1->flags & MEM_Dyn)==0 );
|
||||
assert( VdbeMemDynamic(pIn1)==0 );
|
||||
memAboutToChange(p, pIn1);
|
||||
pIn1->flags = MEM_Int;
|
||||
pIn1->u.i = pc;
|
||||
@@ -772,7 +793,7 @@ case OP_EndCoroutine: { /* in1 */
|
||||
case OP_Yield: { /* in1, jump */
|
||||
int pcDest;
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
assert( (pIn1->flags & MEM_Dyn)==0 );
|
||||
assert( VdbeMemDynamic(pIn1)==0 );
|
||||
pIn1->flags = MEM_Int;
|
||||
pcDest = (int)pIn1->u.i;
|
||||
pIn1->u.i = pc;
|
||||
@@ -945,10 +966,9 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
|
||||
if( rc==SQLITE_TOOBIG ) goto too_big;
|
||||
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
|
||||
assert( pOut->zMalloc==pOut->z );
|
||||
assert( pOut->flags & MEM_Dyn );
|
||||
assert( VdbeMemDynamic(pOut)==0 );
|
||||
pOut->zMalloc = 0;
|
||||
pOut->flags |= MEM_Static;
|
||||
pOut->flags &= ~MEM_Dyn;
|
||||
if( pOp->p4type==P4_DYNAMIC ){
|
||||
sqlite3DbFree(db, pOp->p4.z);
|
||||
}
|
||||
@@ -1084,14 +1104,16 @@ case OP_Move: {
|
||||
assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
|
||||
assert( memIsValid(pIn1) );
|
||||
memAboutToChange(p, pOut);
|
||||
VdbeMemRelease(pOut);
|
||||
zMalloc = pOut->zMalloc;
|
||||
pOut->zMalloc = 0;
|
||||
sqlite3VdbeMemMove(pOut, pIn1);
|
||||
memcpy(pOut, pIn1, sizeof(Mem));
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
|
||||
pOut->pScopyFrom += p1 - pOp->p2;
|
||||
}
|
||||
#endif
|
||||
pIn1->flags = MEM_Undefined;
|
||||
pIn1->xDel = 0;
|
||||
pIn1->zMalloc = zMalloc;
|
||||
REGISTER_TRACE(p2++, pOut);
|
||||
pIn1++;
|
||||
@@ -1159,7 +1181,7 @@ case OP_SCopy: { /* out2 */
|
||||
** The registers P1 through P1+P2-1 contain a single row of
|
||||
** results. This opcode causes the sqlite3_step() call to terminate
|
||||
** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
|
||||
** structure to provide access to the r[P1]..r[P1+P2-1] values as
|
||||
** structure to provide access to the r(P1)..r(P1+P2-1) values as
|
||||
** the result row.
|
||||
*/
|
||||
case OP_ResultRow: {
|
||||
@@ -1225,7 +1247,6 @@ case OP_ResultRow: {
|
||||
assert( (pMem[i].flags & MEM_Ephem)==0
|
||||
|| (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
|
||||
sqlite3VdbeMemNulTerminate(&pMem[i]);
|
||||
sqlite3VdbeMemStoreType(&pMem[i]);
|
||||
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
|
||||
}
|
||||
if( db->mallocFailed ) goto no_mem;
|
||||
@@ -1268,10 +1289,10 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
|
||||
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
goto too_big;
|
||||
}
|
||||
MemSetTypeFlag(pOut, MEM_Str);
|
||||
if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
|
||||
goto no_mem;
|
||||
}
|
||||
MemSetTypeFlag(pOut, MEM_Str);
|
||||
if( pOut!=pIn2 ){
|
||||
memcpy(pOut->z, pIn2->z, pIn2->n);
|
||||
}
|
||||
@@ -1471,7 +1492,6 @@ case OP_Function: {
|
||||
assert( memIsValid(pArg) );
|
||||
apVal[i] = pArg;
|
||||
Deephemeralize(pArg);
|
||||
sqlite3VdbeMemStoreType(pArg);
|
||||
REGISTER_TRACE(pOp->p2+i, pArg);
|
||||
}
|
||||
|
||||
@@ -1891,6 +1911,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
*/
|
||||
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
|
||||
assert( (flags1 & MEM_Cleared)==0 );
|
||||
assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
|
||||
if( (flags1&MEM_Null)!=0
|
||||
&& (flags3&MEM_Null)!=0
|
||||
&& (flags3&MEM_Cleared)==0
|
||||
@@ -1909,7 +1930,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
MemSetTypeFlag(pOut, MEM_Null);
|
||||
REGISTER_TRACE(pOp->p2, pOut);
|
||||
}else{
|
||||
VdbeBranchTaken((pOp->p5 & SQLITE_JUMPIFNULL)?2:3,4);
|
||||
VdbeBranchTaken(2,3);
|
||||
if( pOp->p5 & SQLITE_JUMPIFNULL ){
|
||||
pc = pOp->p2-1;
|
||||
}
|
||||
@@ -1946,7 +1967,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
pOut->u.i = res;
|
||||
REGISTER_TRACE(pOp->p2, pOut);
|
||||
}else{
|
||||
VdbeBranchTaken(res!=0, 4);
|
||||
VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
|
||||
if( res ){
|
||||
pc = pOp->p2-1;
|
||||
}
|
||||
@@ -2150,8 +2171,8 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
|
||||
**
|
||||
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
|
||||
** set the flag and fall through to the next instruction. In other words,
|
||||
** this opcode causes all following up codes up through P2 (but not including
|
||||
** P2) to run just once and skipped on subsequent times through the loop.
|
||||
** this opcode causes all following opcodes up through P2 (but not including
|
||||
** P2) to run just once and to be skipped on subsequent times through the loop.
|
||||
*/
|
||||
case OP_Once: { /* jump */
|
||||
assert( pOp->p1<p->nOnceFlag );
|
||||
@@ -2445,6 +2466,7 @@ case OP_Column: {
|
||||
*/
|
||||
assert( p2<pC->nHdrParsed );
|
||||
assert( rc==SQLITE_OK );
|
||||
assert( sqlite3VdbeCheckMemInvariants(pDest) );
|
||||
if( pC->szRow>=aOffset[p2+1] ){
|
||||
/* This is the common case where the desired content fits on the original
|
||||
** page - where the content is not on an overflow page */
|
||||
@@ -2482,8 +2504,8 @@ case OP_Column: {
|
||||
** This prevents a memory copy. */
|
||||
if( sMem.zMalloc ){
|
||||
assert( sMem.z==sMem.zMalloc );
|
||||
assert( !(pDest->flags & MEM_Dyn) );
|
||||
assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
|
||||
assert( VdbeMemDynamic(pDest)==0 );
|
||||
assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z );
|
||||
pDest->flags &= ~(MEM_Ephem|MEM_Static);
|
||||
pDest->flags |= MEM_Term;
|
||||
pDest->z = sMem.z;
|
||||
@@ -2666,7 +2688,7 @@ case OP_MakeRecord: {
|
||||
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
pOut->n = (int)nByte;
|
||||
pOut->flags = MEM_Blob | MEM_Dyn;
|
||||
pOut->flags = MEM_Blob;
|
||||
pOut->xDel = 0;
|
||||
if( nZero ){
|
||||
pOut->u.nZero = nZero;
|
||||
@@ -3540,16 +3562,16 @@ case OP_SeekGT: { /* jump, in3 */
|
||||
|
||||
/* The next line of code computes as follows, only faster:
|
||||
** if( oc==OP_SeekGT || oc==OP_SeekLE ){
|
||||
** r.flags = UNPACKED_INCRKEY;
|
||||
** r.default_rc = -1;
|
||||
** }else{
|
||||
** r.flags = 0;
|
||||
** r.default_rc = +1;
|
||||
** }
|
||||
*/
|
||||
r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLT)));
|
||||
assert( oc!=OP_SeekGT || r.flags==UNPACKED_INCRKEY );
|
||||
assert( oc!=OP_SeekLE || r.flags==UNPACKED_INCRKEY );
|
||||
assert( oc!=OP_SeekGE || r.flags==0 );
|
||||
assert( oc!=OP_SeekLT || r.flags==0 );
|
||||
r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1);
|
||||
assert( oc!=OP_SeekGT || r.default_rc==-1 );
|
||||
assert( oc!=OP_SeekLE || r.default_rc==-1 );
|
||||
assert( oc!=OP_SeekGE || r.default_rc==+1 );
|
||||
assert( oc!=OP_SeekLT || r.default_rc==+1 );
|
||||
|
||||
r.aMem = &aMem[pOp->p3];
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -3707,7 +3729,6 @@ case OP_Found: { /* jump, in3 */
|
||||
if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
|
||||
#endif
|
||||
}
|
||||
r.flags = UNPACKED_PREFIX_MATCH;
|
||||
pIdxKey = &r;
|
||||
}else{
|
||||
pIdxKey = sqlite3VdbeAllocUnpackedRecord(
|
||||
@@ -3717,8 +3738,8 @@ case OP_Found: { /* jump, in3 */
|
||||
assert( pIn3->flags & MEM_Blob );
|
||||
assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
|
||||
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
|
||||
pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
|
||||
}
|
||||
pIdxKey->default_rc = 0;
|
||||
if( pOp->opcode==OP_NoConflict ){
|
||||
/* For the OP_NoConflict opcode, take the jump if any of the
|
||||
** input fields are NULL, since any key with a NULL will not
|
||||
@@ -4607,7 +4628,7 @@ case OP_IdxDelete: {
|
||||
assert( pOp->p5==0 );
|
||||
r.pKeyInfo = pC->pKeyInfo;
|
||||
r.nField = (u16)pOp->p3;
|
||||
r.flags = UNPACKED_PREFIX_MATCH;
|
||||
r.default_rc = 0;
|
||||
r.aMem = &aMem[pOp->p2];
|
||||
#ifdef SQLITE_DEBUG
|
||||
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
|
||||
@@ -4721,10 +4742,10 @@ case OP_IdxGE: { /* jump */
|
||||
r.nField = (u16)pOp->p4.i;
|
||||
if( pOp->opcode<OP_IdxLT ){
|
||||
assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
|
||||
r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
|
||||
r.default_rc = -1;
|
||||
}else{
|
||||
assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
|
||||
r.flags = UNPACKED_PREFIX_MATCH;
|
||||
r.default_rc = 0;
|
||||
}
|
||||
r.aMem = &aMem[pOp->p3];
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -4833,7 +4854,6 @@ case OP_Clear: {
|
||||
|
||||
nChange = 0;
|
||||
assert( p->readOnly==0 );
|
||||
assert( pOp->p1!=1 );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
|
||||
rc = sqlite3BtreeClearTable(
|
||||
db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
|
||||
@@ -5476,7 +5496,6 @@ case OP_AggStep: {
|
||||
assert( memIsValid(pRec) );
|
||||
apVal[i] = pRec;
|
||||
memAboutToChange(p, pRec);
|
||||
sqlite3VdbeMemStoreType(pRec);
|
||||
}
|
||||
ctx.pFunc = pOp->p4.pFunc;
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
@@ -5910,7 +5929,6 @@ case OP_VFilter: { /* jump */
|
||||
apArg = p->apArg;
|
||||
for(i = 0; i<nArg; i++){
|
||||
apArg[i] = &pArgc[i+1];
|
||||
sqlite3VdbeMemStoreType(apArg[i]);
|
||||
}
|
||||
|
||||
p->inVtabMethod = 1;
|
||||
@@ -6117,7 +6135,6 @@ case OP_VUpdate: {
|
||||
for(i=0; i<nArg; i++){
|
||||
assert( memIsValid(pX) );
|
||||
memAboutToChange(p, pX);
|
||||
sqlite3VdbeMemStoreType(pX);
|
||||
apArg[i] = pX;
|
||||
pX++;
|
||||
}
|
||||
@@ -6259,10 +6276,6 @@ default: { /* This is really OP_Noop and OP_Explain */
|
||||
u64 elapsed = sqlite3Hwtime() - start;
|
||||
pOp->cycles += elapsed;
|
||||
pOp->cnt++;
|
||||
#if 0
|
||||
fprintf(stdout, "%10llu ", elapsed);
|
||||
sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+33
-3
@@ -65,7 +65,7 @@ struct VdbeOp {
|
||||
char *zComment; /* Comment to improve readability */
|
||||
#endif
|
||||
#ifdef VDBE_PROFILE
|
||||
int cnt; /* Number of times this instruction was executed */
|
||||
u32 cnt; /* Number of times this instruction was executed */
|
||||
u64 cycles; /* Total time spent executing this instruction */
|
||||
#endif
|
||||
#ifdef SQLITE_VDBE_COVERAGE
|
||||
@@ -211,9 +211,12 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
|
||||
#endif
|
||||
|
||||
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int);
|
||||
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
|
||||
|
||||
typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int);
|
||||
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
|
||||
#endif
|
||||
@@ -241,14 +244,41 @@ void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
|
||||
# define VdbeModuleComment(X)
|
||||
#endif
|
||||
|
||||
/* Set the Opcode.iSrcline field of the previous opcode */
|
||||
/*
|
||||
** The VdbeCoverage macros are used to set a coverage testing point
|
||||
** for VDBE branch instructions. The coverage testing points are line
|
||||
** numbers in the sqlite3.c source file. VDBE branch coverage testing
|
||||
** only works with an amalagmation build. That's ok since a VDBE branch
|
||||
** coverage build designed for testing the test suite only. No application
|
||||
** should ever ship with VDBE branch coverage measuring turned on.
|
||||
**
|
||||
** VdbeCoverage(v) // Mark the previously coded instruction
|
||||
** // as a branch
|
||||
**
|
||||
** VdbeCoverageIf(v, conditional) // Mark previous if conditional true
|
||||
**
|
||||
** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken
|
||||
**
|
||||
** VdbeCoverageNeverTaken(v) // Previous branch is never taken
|
||||
**
|
||||
** Every VDBE branch operation must be tagged with one of the macros above.
|
||||
** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
|
||||
** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch()
|
||||
** routine in vdbe.c, alerting the developer to the missed tag.
|
||||
*/
|
||||
#ifdef SQLITE_VDBE_COVERAGE
|
||||
void sqlite3VdbeSetLineNumber(Vdbe*,int);
|
||||
# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
|
||||
# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
|
||||
# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2);
|
||||
# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1);
|
||||
# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
|
||||
#else
|
||||
# define VdbeCoverage(v)
|
||||
# define VdbeCoverageIf(v,x)
|
||||
# define VdbeCoverageAlwaysTaken(v)
|
||||
# define VdbeCoverageNeverTaken(v)
|
||||
# define VDBE_OFFSET_LINENO(x) 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+4
-5
@@ -168,7 +168,6 @@ struct Mem {
|
||||
} u;
|
||||
int n; /* Number of characters in string value, excluding '\0' */
|
||||
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
|
||||
u8 memType; /* Lower 5 bits of flags */
|
||||
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
|
||||
#ifdef SQLITE_DEBUG
|
||||
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
|
||||
@@ -195,6 +194,7 @@ struct Mem {
|
||||
#define MEM_Int 0x0004 /* Value is an integer */
|
||||
#define MEM_Real 0x0008 /* Value is a real number */
|
||||
#define MEM_Blob 0x0010 /* Value is a BLOB */
|
||||
#define MEM_AffMask 0x001f /* Mask of affinity bits */
|
||||
#define MEM_RowSet 0x0020 /* Value is a RowSet object */
|
||||
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
|
||||
#define MEM_Undefined 0x0080 /* Value is undefined */
|
||||
@@ -208,7 +208,7 @@ struct Mem {
|
||||
** string is \000 or \u0000 terminated
|
||||
*/
|
||||
#define MEM_Term 0x0200 /* String rep is nul terminated */
|
||||
#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
|
||||
#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
|
||||
#define MEM_Static 0x0800 /* Mem.z points to a static string */
|
||||
#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
|
||||
#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
|
||||
@@ -391,7 +391,7 @@ u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
||||
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
|
||||
|
||||
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
||||
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
|
||||
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*);
|
||||
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
|
||||
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
|
||||
int sqlite3VdbeExec(Vdbe*);
|
||||
@@ -434,8 +434,6 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
|
||||
int sqlite3VdbeCloseStatement(Vdbe *, int);
|
||||
void sqlite3VdbeFrameDelete(VdbeFrame*);
|
||||
int sqlite3VdbeFrameRestore(VdbeFrame *);
|
||||
#define sqlite3VdbeMemStoreType(X) (X)->memType = (u8)((X)->flags&0x1f)
|
||||
/* void sqlite3VdbeMemStoreType(Mem *pMem); */
|
||||
int sqlite3VdbeTransferError(Vdbe *p);
|
||||
|
||||
int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
|
||||
@@ -456,6 +454,7 @@ int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
|
||||
int sqlite3VdbeCheckMemInvariants(Mem*);
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||
|
||||
+26
-24
@@ -135,7 +135,6 @@ const void *sqlite3_value_blob(sqlite3_value *pVal){
|
||||
Mem *p = (Mem*)pVal;
|
||||
if( p->flags & (MEM_Blob|MEM_Str) ){
|
||||
sqlite3VdbeMemExpandBlob(p);
|
||||
p->flags &= ~MEM_Str;
|
||||
p->flags |= MEM_Blob;
|
||||
return p->n ? p->z : 0;
|
||||
}else{
|
||||
@@ -206,7 +205,7 @@ int sqlite3_value_type(sqlite3_value* pVal){
|
||||
SQLITE_INTEGER, /* 0x1e */
|
||||
SQLITE_NULL, /* 0x1f */
|
||||
};
|
||||
return aType[pVal->memType&0x1f];
|
||||
return aType[pVal->flags&MEM_AffMask];
|
||||
}
|
||||
|
||||
/**************************** sqlite3_result_ *******************************
|
||||
@@ -727,6 +726,30 @@ int sqlite3_data_count(sqlite3_stmt *pStmt){
|
||||
return pVm->nResColumn;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to static memory containing an SQL NULL value.
|
||||
*/
|
||||
static const Mem *columnNullValue(void){
|
||||
/* Even though the Mem structure contains an element
|
||||
** of type i64, on certain architectures (x86) with certain compiler
|
||||
** switches (-Os), gcc may align this Mem object on a 4-byte boundary
|
||||
** instead of an 8-byte one. This all works fine, except that when
|
||||
** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
|
||||
** that a Mem structure is located on an 8-byte boundary. To prevent
|
||||
** these assert()s from failing, when building with SQLITE_DEBUG defined
|
||||
** using gcc, we force nullMem to be 8-byte aligned using the magical
|
||||
** __attribute__((aligned(8))) macro. */
|
||||
static const Mem nullMem
|
||||
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
|
||||
__attribute__((aligned(8)))
|
||||
#endif
|
||||
= {0, "", (double)0, {0}, 0, MEM_Null, 0,
|
||||
#ifdef SQLITE_DEBUG
|
||||
0, 0, /* pScopyFrom, pFiller */
|
||||
#endif
|
||||
0, 0 };
|
||||
return &nullMem;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if column iCol of the given statement is valid. If
|
||||
@@ -743,32 +766,11 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
|
||||
sqlite3_mutex_enter(pVm->db->mutex);
|
||||
pOut = &pVm->pResultSet[i];
|
||||
}else{
|
||||
/* If the value passed as the second argument is out of range, return
|
||||
** a pointer to the following static Mem object which contains the
|
||||
** value SQL NULL. Even though the Mem structure contains an element
|
||||
** of type i64, on certain architectures (x86) with certain compiler
|
||||
** switches (-Os), gcc may align this Mem object on a 4-byte boundary
|
||||
** instead of an 8-byte one. This all works fine, except that when
|
||||
** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
|
||||
** that a Mem structure is located on an 8-byte boundary. To prevent
|
||||
** these assert()s from failing, when building with SQLITE_DEBUG defined
|
||||
** using gcc, we force nullMem to be 8-byte aligned using the magical
|
||||
** __attribute__((aligned(8))) macro. */
|
||||
static const Mem nullMem
|
||||
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
|
||||
__attribute__((aligned(8)))
|
||||
#endif
|
||||
= {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
|
||||
#ifdef SQLITE_DEBUG
|
||||
0, 0, /* pScopyFrom, pFiller */
|
||||
#endif
|
||||
0, 0 };
|
||||
|
||||
if( pVm && ALWAYS(pVm->db) ){
|
||||
sqlite3_mutex_enter(pVm->db->mutex);
|
||||
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
|
||||
}
|
||||
pOut = (Mem*)&nullMem;
|
||||
pOut = (Mem*)columnNullValue();
|
||||
}
|
||||
return pOut;
|
||||
}
|
||||
|
||||
+613
-65
@@ -1220,6 +1220,7 @@ static void releaseMemArray(Mem *p, int N){
|
||||
}
|
||||
for(pEnd=&p[N]; p<pEnd; p++){
|
||||
assert( (&p[1])==pEnd || p[0].db==p[1].db );
|
||||
assert( sqlite3VdbeCheckMemInvariants(p) );
|
||||
|
||||
/* This block is really an inlined version of sqlite3VdbeMemRelease()
|
||||
** that takes advantage of the fact that the memory cell value is
|
||||
@@ -1233,6 +1234,10 @@ static void releaseMemArray(Mem *p, int N){
|
||||
** with no indexes using a single prepared INSERT statement, bind()
|
||||
** and reset(). Inserts are grouped into a transaction.
|
||||
*/
|
||||
testcase( p->flags & MEM_Agg );
|
||||
testcase( p->flags & MEM_Dyn );
|
||||
testcase( p->flags & MEM_Frame );
|
||||
testcase( p->flags & MEM_RowSet );
|
||||
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
|
||||
sqlite3VdbeMemRelease(p);
|
||||
}else if( p->zMalloc ){
|
||||
@@ -1362,7 +1367,6 @@ int sqlite3VdbeList(
|
||||
}
|
||||
if( p->explain==1 ){
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->memType = MEM_Int;
|
||||
pMem->u.i = i; /* Program counter */
|
||||
pMem++;
|
||||
|
||||
@@ -1370,7 +1374,6 @@ int sqlite3VdbeList(
|
||||
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
|
||||
assert( pMem->z!=0 );
|
||||
pMem->n = sqlite3Strlen30(pMem->z);
|
||||
pMem->memType = MEM_Str;
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
pMem++;
|
||||
|
||||
@@ -1396,24 +1399,21 @@ int sqlite3VdbeList(
|
||||
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->u.i = pOp->p1; /* P1 */
|
||||
pMem->memType = MEM_Int;
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->u.i = pOp->p2; /* P2 */
|
||||
pMem->memType = MEM_Int;
|
||||
pMem++;
|
||||
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->u.i = pOp->p3; /* P3 */
|
||||
pMem->memType = MEM_Int;
|
||||
pMem++;
|
||||
|
||||
if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
zP4 = displayP4(pOp, pMem->z, 32);
|
||||
if( zP4!=pMem->z ){
|
||||
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
|
||||
@@ -1422,7 +1422,6 @@ int sqlite3VdbeList(
|
||||
pMem->n = sqlite3Strlen30(pMem->z);
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
}
|
||||
pMem->memType = MEM_Str;
|
||||
pMem++;
|
||||
|
||||
if( p->explain==1 ){
|
||||
@@ -1430,10 +1429,9 @@ int sqlite3VdbeList(
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
pMem->n = 2;
|
||||
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
|
||||
pMem->memType = MEM_Str;
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
pMem++;
|
||||
|
||||
@@ -1442,13 +1440,11 @@ int sqlite3VdbeList(
|
||||
assert( p->db->mallocFailed );
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
|
||||
pMem->memType = MEM_Str;
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
#else
|
||||
pMem->flags = MEM_Null; /* Comment */
|
||||
pMem->memType = MEM_Null;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2580,11 +2576,13 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
if( pc!='\n' ) fprintf(out, "\n");
|
||||
}
|
||||
for(i=0; i<p->nOp; i++){
|
||||
fprintf(out, "%6d %10lld %8lld ",
|
||||
char zHdr[100];
|
||||
sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ",
|
||||
p->aOp[i].cnt,
|
||||
p->aOp[i].cycles,
|
||||
p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
|
||||
);
|
||||
fprintf(out, "%s", zHdr);
|
||||
sqlite3VdbePrintOp(out, i, &p->aOp[i]);
|
||||
}
|
||||
fclose(out);
|
||||
@@ -2939,6 +2937,14 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Input "x" is a sequence of unsigned characters that represent a
|
||||
** big-endian integer. Return the equivalent native integer
|
||||
*/
|
||||
#define ONE_BYTE_INT(x) ((i8)(x)[0])
|
||||
#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
|
||||
#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
|
||||
#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
|
||||
|
||||
/*
|
||||
** Deserialize the data blob pointed to by buf as serial type serial_type
|
||||
** and store the result in pMem. Return the number of bytes read.
|
||||
@@ -2950,7 +2956,6 @@ u32 sqlite3VdbeSerialGet(
|
||||
){
|
||||
u64 x;
|
||||
u32 y;
|
||||
int i;
|
||||
switch( serial_type ){
|
||||
case 10: /* Reserved for future use */
|
||||
case 11: /* Reserved for future use */
|
||||
@@ -2959,34 +2964,34 @@ u32 sqlite3VdbeSerialGet(
|
||||
break;
|
||||
}
|
||||
case 1: { /* 1-byte signed integer */
|
||||
pMem->u.i = (signed char)buf[0];
|
||||
pMem->u.i = ONE_BYTE_INT(buf);
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 1;
|
||||
}
|
||||
case 2: { /* 2-byte signed integer */
|
||||
i = 256*(signed char)buf[0] | buf[1];
|
||||
pMem->u.i = (i64)i;
|
||||
pMem->u.i = TWO_BYTE_INT(buf);
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 2;
|
||||
}
|
||||
case 3: { /* 3-byte signed integer */
|
||||
i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
|
||||
pMem->u.i = (i64)i;
|
||||
pMem->u.i = THREE_BYTE_INT(buf);
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 3;
|
||||
}
|
||||
case 4: { /* 4-byte signed integer */
|
||||
y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
|
||||
y = FOUR_BYTE_UINT(buf);
|
||||
pMem->u.i = (i64)*(int*)&y;
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 4;
|
||||
}
|
||||
case 5: { /* 6-byte signed integer */
|
||||
x = 256*(signed char)buf[0] + buf[1];
|
||||
y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
|
||||
x = (x<<32) | y;
|
||||
pMem->u.i = *(i64*)&x;
|
||||
pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
return 6;
|
||||
}
|
||||
case 6: /* 8-byte signed integer */
|
||||
@@ -3003,12 +3008,13 @@ u32 sqlite3VdbeSerialGet(
|
||||
swapMixedEndianFloat(t2);
|
||||
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
|
||||
#endif
|
||||
x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
|
||||
y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
|
||||
x = FOUR_BYTE_UINT(buf);
|
||||
y = FOUR_BYTE_UINT(buf+4);
|
||||
x = (x<<32) | y;
|
||||
if( serial_type==6 ){
|
||||
pMem->u.i = *(i64*)&x;
|
||||
pMem->flags = MEM_Int;
|
||||
testcase( pMem->u.i<0 );
|
||||
}else{
|
||||
assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
|
||||
swapMixedEndianFloat(x);
|
||||
@@ -3100,7 +3106,7 @@ void sqlite3VdbeRecordUnpack(
|
||||
u32 szHdr;
|
||||
Mem *pMem = p->aMem;
|
||||
|
||||
p->flags = 0;
|
||||
p->default_rc = 0;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
||||
idx = getVarint32(aKey, szHdr);
|
||||
d = szHdr;
|
||||
@@ -3121,26 +3127,18 @@ void sqlite3VdbeRecordUnpack(
|
||||
p->nField = u;
|
||||
}
|
||||
|
||||
#if SQLITE_DEBUG
|
||||
/*
|
||||
** This function compares the two table rows or index records
|
||||
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
|
||||
** or positive integer if key1 is less than, equal to or
|
||||
** greater than key2. The {nKey1, pKey1} key must be a blob
|
||||
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
|
||||
** key must be a parsed key such as obtained from
|
||||
** sqlite3VdbeParseRecord.
|
||||
**
|
||||
** Key1 and Key2 do not have to contain the same number of fields.
|
||||
** The key with fewer fields is usually compares less than the
|
||||
** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
|
||||
** and the common prefixes are equal, then key1 is less than key2.
|
||||
** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
|
||||
** equal, then the keys are considered to be equal and
|
||||
** the parts beyond the common prefix are ignored.
|
||||
** This function compares two index or table record keys in the same way
|
||||
** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
|
||||
** this function deserializes and compares values using the
|
||||
** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
|
||||
** in assert() statements to ensure that the optimized code in
|
||||
** sqlite3VdbeRecordCompare() returns results with these two primitives.
|
||||
*/
|
||||
int sqlite3VdbeRecordCompare(
|
||||
static int vdbeRecordCompareDebug(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
UnpackedRecord *pPKey2 /* Right key */
|
||||
const UnpackedRecord *pPKey2 /* Right key */
|
||||
){
|
||||
u32 d1; /* Offset into aKey[] of next data element */
|
||||
u32 idx1; /* Offset into aKey[] of next header element */
|
||||
@@ -3214,24 +3212,576 @@ int sqlite3VdbeRecordCompare(
|
||||
assert( mem1.zMalloc==0 );
|
||||
|
||||
/* rc==0 here means that one of the keys ran out of fields and
|
||||
** all the fields up to that point were equal. If the UNPACKED_INCRKEY
|
||||
** flag is set, then break the tie by treating key2 as larger.
|
||||
** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
|
||||
** are considered to be equal. Otherwise, the longer key is the
|
||||
** larger. As it happens, the pPKey2 will always be the longer
|
||||
** if there is a difference.
|
||||
** all the fields up to that point were equal. Return the the default_rc
|
||||
** value. */
|
||||
return pPKey2->default_rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Both *pMem1 and *pMem2 contain string values. Compare the two values
|
||||
** using the collation sequence pColl. As usual, return a negative , zero
|
||||
** or positive value if *pMem1 is less than, equal to or greater than
|
||||
** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
|
||||
*/
|
||||
static int vdbeCompareMemString(
|
||||
const Mem *pMem1,
|
||||
const Mem *pMem2,
|
||||
const CollSeq *pColl
|
||||
){
|
||||
if( pMem1->enc==pColl->enc ){
|
||||
/* The strings are already in the correct encoding. Call the
|
||||
** comparison function directly */
|
||||
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
|
||||
}else{
|
||||
int rc;
|
||||
const void *v1, *v2;
|
||||
int n1, n2;
|
||||
Mem c1;
|
||||
Mem c2;
|
||||
memset(&c1, 0, sizeof(c1));
|
||||
memset(&c2, 0, sizeof(c2));
|
||||
sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
|
||||
sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
|
||||
v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
|
||||
n1 = v1==0 ? 0 : c1.n;
|
||||
v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
|
||||
n2 = v2==0 ? 0 : c2.n;
|
||||
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
|
||||
sqlite3VdbeMemRelease(&c1);
|
||||
sqlite3VdbeMemRelease(&c2);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare the values contained by the two memory cells, returning
|
||||
** negative, zero or positive if pMem1 is less than, equal to, or greater
|
||||
** than pMem2. Sorting order is NULL's first, followed by numbers (integers
|
||||
** and reals) sorted numerically, followed by text ordered by the collating
|
||||
** sequence pColl and finally blob's ordered by memcmp().
|
||||
**
|
||||
** Two NULL values are considered equal by this function.
|
||||
*/
|
||||
int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
|
||||
int rc;
|
||||
int f1, f2;
|
||||
int combined_flags;
|
||||
|
||||
f1 = pMem1->flags;
|
||||
f2 = pMem2->flags;
|
||||
combined_flags = f1|f2;
|
||||
assert( (combined_flags & MEM_RowSet)==0 );
|
||||
|
||||
/* If one value is NULL, it is less than the other. If both values
|
||||
** are NULL, return 0.
|
||||
*/
|
||||
assert( rc==0 );
|
||||
if( pPKey2->flags & UNPACKED_INCRKEY ){
|
||||
rc = -1;
|
||||
}else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
|
||||
/* Leave rc==0 */
|
||||
}else if( idx1<szHdr1 ){
|
||||
rc = 1;
|
||||
if( combined_flags&MEM_Null ){
|
||||
return (f2&MEM_Null) - (f1&MEM_Null);
|
||||
}
|
||||
|
||||
/* If one value is a number and the other is not, the number is less.
|
||||
** If both are numbers, compare as reals if one is a real, or as integers
|
||||
** if both values are integers.
|
||||
*/
|
||||
if( combined_flags&(MEM_Int|MEM_Real) ){
|
||||
double r1, r2;
|
||||
if( (f1 & f2 & MEM_Int)!=0 ){
|
||||
if( pMem1->u.i < pMem2->u.i ) return -1;
|
||||
if( pMem1->u.i > pMem2->u.i ) return 1;
|
||||
return 0;
|
||||
}
|
||||
if( (f1&MEM_Real)!=0 ){
|
||||
r1 = pMem1->r;
|
||||
}else if( (f1&MEM_Int)!=0 ){
|
||||
r1 = (double)pMem1->u.i;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
if( (f2&MEM_Real)!=0 ){
|
||||
r2 = pMem2->r;
|
||||
}else if( (f2&MEM_Int)!=0 ){
|
||||
r2 = (double)pMem2->u.i;
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
if( r1<r2 ) return -1;
|
||||
if( r1>r2 ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If one value is a string and the other is a blob, the string is less.
|
||||
** If both are strings, compare using the collating functions.
|
||||
*/
|
||||
if( combined_flags&MEM_Str ){
|
||||
if( (f1 & MEM_Str)==0 ){
|
||||
return 1;
|
||||
}
|
||||
if( (f2 & MEM_Str)==0 ){
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert( pMem1->enc==pMem2->enc );
|
||||
assert( pMem1->enc==SQLITE_UTF8 ||
|
||||
pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
|
||||
|
||||
/* The collation sequence must be defined at this point, even if
|
||||
** the user deletes the collation sequence after the vdbe program is
|
||||
** compiled (this was not always the case).
|
||||
*/
|
||||
assert( !pColl || pColl->xCmp );
|
||||
|
||||
if( pColl ){
|
||||
return vdbeCompareMemString(pMem1, pMem2, pColl);
|
||||
}
|
||||
/* If a NULL pointer was passed as the collate function, fall through
|
||||
** to the blob case and use memcmp(). */
|
||||
}
|
||||
|
||||
/* Both values must be blobs. Compare using memcmp(). */
|
||||
rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
|
||||
if( rc==0 ){
|
||||
rc = pMem1->n - pMem2->n;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** The first argument passed to this function is a serial-type that
|
||||
** corresponds to an integer - all values between 1 and 9 inclusive
|
||||
** except 7. The second points to a buffer containing an integer value
|
||||
** serialized according to serial_type. This function deserializes
|
||||
** and returns the value.
|
||||
*/
|
||||
static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
|
||||
u32 y;
|
||||
assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
|
||||
switch( serial_type ){
|
||||
case 0:
|
||||
case 1:
|
||||
testcase( aKey[0]&0x80 );
|
||||
return ONE_BYTE_INT(aKey);
|
||||
case 2:
|
||||
testcase( aKey[0]&0x80 );
|
||||
return TWO_BYTE_INT(aKey);
|
||||
case 3:
|
||||
testcase( aKey[0]&0x80 );
|
||||
return THREE_BYTE_INT(aKey);
|
||||
case 4: {
|
||||
testcase( aKey[0]&0x80 );
|
||||
y = FOUR_BYTE_UINT(aKey);
|
||||
return (i64)*(int*)&y;
|
||||
}
|
||||
case 5: {
|
||||
testcase( aKey[0]&0x80 );
|
||||
return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
|
||||
}
|
||||
case 6: {
|
||||
u64 x = FOUR_BYTE_UINT(aKey);
|
||||
testcase( aKey[0]&0x80 );
|
||||
x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
|
||||
return (i64)*(i64*)&x;
|
||||
}
|
||||
}
|
||||
|
||||
return (serial_type - 8);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function compares the two table rows or index records
|
||||
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
|
||||
** or positive integer if key1 is less than, equal to or
|
||||
** greater than key2. The {nKey1, pKey1} key must be a blob
|
||||
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
|
||||
** key must be a parsed key such as obtained from
|
||||
** sqlite3VdbeParseRecord.
|
||||
**
|
||||
** If argument bSkip is non-zero, it is assumed that the caller has already
|
||||
** determined that the first fields of the keys are equal.
|
||||
**
|
||||
** Key1 and Key2 do not have to contain the same number of fields. If all
|
||||
** fields that appear in both keys are equal, then pPKey2->default_rc is
|
||||
** returned.
|
||||
*/
|
||||
int sqlite3VdbeRecordCompare(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
const UnpackedRecord *pPKey2, /* Right key */
|
||||
int bSkip /* If true, skip the first field */
|
||||
){
|
||||
u32 d1; /* Offset into aKey[] of next data element */
|
||||
int i; /* Index of next field to compare */
|
||||
u32 szHdr1; /* Size of record header in bytes */
|
||||
u32 idx1; /* Offset of first type in header */
|
||||
int rc = 0; /* Return value */
|
||||
Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
|
||||
KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
|
||||
const unsigned char *aKey1 = (const unsigned char *)pKey1;
|
||||
Mem mem1;
|
||||
|
||||
/* If bSkip is true, then the caller has already determined that the first
|
||||
** two elements in the keys are equal. Fix the various stack variables so
|
||||
** that this routine begins comparing at the second field. */
|
||||
if( bSkip ){
|
||||
u32 s1;
|
||||
idx1 = 1 + getVarint32(&aKey1[1], s1);
|
||||
szHdr1 = aKey1[0];
|
||||
d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
|
||||
i = 1;
|
||||
pRhs++;
|
||||
}else{
|
||||
idx1 = getVarint32(aKey1, szHdr1);
|
||||
d1 = szHdr1;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
|
||||
assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
|
||||
|| CORRUPT_DB );
|
||||
assert( pPKey2->pKeyInfo->aSortOrder!=0 );
|
||||
assert( pPKey2->pKeyInfo->nField>0 );
|
||||
assert( idx1<=szHdr1 || CORRUPT_DB );
|
||||
do{
|
||||
u32 serial_type;
|
||||
|
||||
/* RHS is an integer */
|
||||
if( pRhs->flags & MEM_Int ){
|
||||
serial_type = aKey1[idx1];
|
||||
testcase( serial_type==12 );
|
||||
if( serial_type>=12 ){
|
||||
rc = +1;
|
||||
}else if( serial_type==0 ){
|
||||
rc = -1;
|
||||
}else if( serial_type==7 ){
|
||||
double rhs = (double)pRhs->u.i;
|
||||
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
|
||||
if( mem1.r<rhs ){
|
||||
rc = -1;
|
||||
}else if( mem1.r>rhs ){
|
||||
rc = +1;
|
||||
}
|
||||
}else{
|
||||
i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
|
||||
i64 rhs = pRhs->u.i;
|
||||
if( lhs<rhs ){
|
||||
rc = -1;
|
||||
}else if( lhs>rhs ){
|
||||
rc = +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RHS is real */
|
||||
else if( pRhs->flags & MEM_Real ){
|
||||
serial_type = aKey1[idx1];
|
||||
if( serial_type>=12 ){
|
||||
rc = +1;
|
||||
}else if( serial_type==0 ){
|
||||
rc = -1;
|
||||
}else{
|
||||
double rhs = pRhs->r;
|
||||
double lhs;
|
||||
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
|
||||
if( serial_type==7 ){
|
||||
lhs = mem1.r;
|
||||
}else{
|
||||
lhs = (double)mem1.u.i;
|
||||
}
|
||||
if( lhs<rhs ){
|
||||
rc = -1;
|
||||
}else if( lhs>rhs ){
|
||||
rc = +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RHS is a string */
|
||||
else if( pRhs->flags & MEM_Str ){
|
||||
getVarint32(&aKey1[idx1], serial_type);
|
||||
testcase( serial_type==12 );
|
||||
if( serial_type<12 ){
|
||||
rc = -1;
|
||||
}else if( !(serial_type & 0x01) ){
|
||||
rc = +1;
|
||||
}else{
|
||||
mem1.n = (serial_type - 12) / 2;
|
||||
testcase( (d1+mem1.n)==(unsigned)nKey1 );
|
||||
testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
|
||||
if( (d1+mem1.n) > (unsigned)nKey1 ){
|
||||
rc = 1; /* Corruption */
|
||||
}else if( pKeyInfo->aColl[i] ){
|
||||
mem1.enc = pKeyInfo->enc;
|
||||
mem1.db = pKeyInfo->db;
|
||||
mem1.flags = MEM_Str;
|
||||
mem1.z = (char*)&aKey1[d1];
|
||||
rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
|
||||
}else{
|
||||
int nCmp = MIN(mem1.n, pRhs->n);
|
||||
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
|
||||
if( rc==0 ) rc = mem1.n - pRhs->n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RHS is a blob */
|
||||
else if( pRhs->flags & MEM_Blob ){
|
||||
getVarint32(&aKey1[idx1], serial_type);
|
||||
testcase( serial_type==12 );
|
||||
if( serial_type<12 || (serial_type & 0x01) ){
|
||||
rc = -1;
|
||||
}else{
|
||||
int nStr = (serial_type - 12) / 2;
|
||||
testcase( (d1+nStr)==(unsigned)nKey1 );
|
||||
testcase( (d1+nStr+1)==(unsigned)nKey1 );
|
||||
if( (d1+nStr) > (unsigned)nKey1 ){
|
||||
rc = 1; /* Corruption */
|
||||
}else{
|
||||
int nCmp = MIN(nStr, pRhs->n);
|
||||
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
|
||||
if( rc==0 ) rc = nStr - pRhs->n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RHS is null */
|
||||
else{
|
||||
serial_type = aKey1[idx1];
|
||||
rc = (serial_type!=0);
|
||||
}
|
||||
|
||||
if( rc!=0 ){
|
||||
if( pKeyInfo->aSortOrder[i] ){
|
||||
rc = -rc;
|
||||
}
|
||||
assert( CORRUPT_DB
|
||||
|| (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|
||||
|| (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|
||||
|| pKeyInfo->db->mallocFailed
|
||||
);
|
||||
assert( mem1.zMalloc==0 ); /* See comment below */
|
||||
return rc;
|
||||
}
|
||||
|
||||
i++;
|
||||
pRhs++;
|
||||
d1 += sqlite3VdbeSerialTypeLen(serial_type);
|
||||
idx1 += sqlite3VarintLen(serial_type);
|
||||
}while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
|
||||
|
||||
/* No memory allocation is ever used on mem1. Prove this using
|
||||
** the following assert(). If the assert() fails, it indicates a
|
||||
** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */
|
||||
assert( mem1.zMalloc==0 );
|
||||
|
||||
/* rc==0 here means that one or both of the keys ran out of fields and
|
||||
** all the fields up to that point were equal. Return the the default_rc
|
||||
** value. */
|
||||
assert( CORRUPT_DB
|
||||
|| pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)
|
||||
);
|
||||
return pPKey2->default_rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is an optimized version of sqlite3VdbeRecordCompare()
|
||||
** that (a) the first field of pPKey2 is an integer, and (b) the
|
||||
** size-of-header varint at the start of (pKey1/nKey1) fits in a single
|
||||
** byte (i.e. is less than 128).
|
||||
*/
|
||||
static int vdbeRecordCompareInt(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
const UnpackedRecord *pPKey2, /* Right key */
|
||||
int bSkip /* Ignored */
|
||||
){
|
||||
const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
|
||||
int serial_type = ((const u8*)pKey1)[1];
|
||||
int res;
|
||||
u32 y;
|
||||
u64 x;
|
||||
i64 v = pPKey2->aMem[0].u.i;
|
||||
i64 lhs;
|
||||
UNUSED_PARAMETER(bSkip);
|
||||
|
||||
assert( bSkip==0 );
|
||||
switch( serial_type ){
|
||||
case 1: { /* 1-byte signed integer */
|
||||
lhs = ONE_BYTE_INT(aKey);
|
||||
testcase( lhs<0 );
|
||||
break;
|
||||
}
|
||||
case 2: { /* 2-byte signed integer */
|
||||
lhs = TWO_BYTE_INT(aKey);
|
||||
testcase( lhs<0 );
|
||||
break;
|
||||
}
|
||||
case 3: { /* 3-byte signed integer */
|
||||
lhs = THREE_BYTE_INT(aKey);
|
||||
testcase( lhs<0 );
|
||||
break;
|
||||
}
|
||||
case 4: { /* 4-byte signed integer */
|
||||
y = FOUR_BYTE_UINT(aKey);
|
||||
lhs = (i64)*(int*)&y;
|
||||
testcase( lhs<0 );
|
||||
break;
|
||||
}
|
||||
case 5: { /* 6-byte signed integer */
|
||||
lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
|
||||
testcase( lhs<0 );
|
||||
break;
|
||||
}
|
||||
case 6: { /* 8-byte signed integer */
|
||||
x = FOUR_BYTE_UINT(aKey);
|
||||
x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
|
||||
lhs = *(i64*)&x;
|
||||
testcase( lhs<0 );
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
lhs = 0;
|
||||
break;
|
||||
case 9:
|
||||
lhs = 1;
|
||||
break;
|
||||
|
||||
/* This case could be removed without changing the results of running
|
||||
** this code. Including it causes gcc to generate a faster switch
|
||||
** statement (since the range of switch targets now starts at zero and
|
||||
** is contiguous) but does not cause any duplicate code to be generated
|
||||
** (as gcc is clever enough to combine the two like cases). Other
|
||||
** compilers might be similar. */
|
||||
case 0: case 7:
|
||||
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
|
||||
|
||||
default:
|
||||
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
|
||||
}
|
||||
|
||||
if( v>lhs ){
|
||||
res = pPKey2->r1;
|
||||
}else if( v<lhs ){
|
||||
res = pPKey2->r2;
|
||||
}else if( pPKey2->nField>1 ){
|
||||
/* The first fields of the two keys are equal. Compare the trailing
|
||||
** fields. */
|
||||
res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
|
||||
}else{
|
||||
/* The first fields of the two keys are equal and there are no trailing
|
||||
** fields. Return pPKey2->default_rc in this case. */
|
||||
res = pPKey2->default_rc;
|
||||
}
|
||||
|
||||
assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
|
||||
|| (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|
||||
|| (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|
||||
|| CORRUPT_DB
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is an optimized version of sqlite3VdbeRecordCompare()
|
||||
** that (a) the first field of pPKey2 is a string, that (b) the first field
|
||||
** uses the collation sequence BINARY and (c) that the size-of-header varint
|
||||
** at the start of (pKey1/nKey1) fits in a single byte.
|
||||
*/
|
||||
static int vdbeRecordCompareString(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
const UnpackedRecord *pPKey2, /* Right key */
|
||||
int bSkip
|
||||
){
|
||||
const u8 *aKey1 = (const u8*)pKey1;
|
||||
int serial_type;
|
||||
int res;
|
||||
UNUSED_PARAMETER(bSkip);
|
||||
|
||||
assert( bSkip==0 );
|
||||
getVarint32(&aKey1[1], serial_type);
|
||||
|
||||
if( serial_type<12 ){
|
||||
res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
|
||||
}else if( !(serial_type & 0x01) ){
|
||||
res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
|
||||
}else{
|
||||
int nCmp;
|
||||
int nStr;
|
||||
int szHdr = aKey1[0];
|
||||
|
||||
nStr = (serial_type-12) / 2;
|
||||
if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */
|
||||
nCmp = MIN( pPKey2->aMem[0].n, nStr );
|
||||
res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
|
||||
|
||||
if( res==0 ){
|
||||
res = nStr - pPKey2->aMem[0].n;
|
||||
if( res==0 ){
|
||||
if( pPKey2->nField>1 ){
|
||||
res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
|
||||
}else{
|
||||
res = pPKey2->default_rc;
|
||||
}
|
||||
}else if( res>0 ){
|
||||
res = pPKey2->r2;
|
||||
}else{
|
||||
res = pPKey2->r1;
|
||||
}
|
||||
}else if( res>0 ){
|
||||
res = pPKey2->r2;
|
||||
}else{
|
||||
res = pPKey2->r1;
|
||||
}
|
||||
}
|
||||
|
||||
assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
|
||||
|| (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|
||||
|| (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|
||||
|| CORRUPT_DB
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to an sqlite3VdbeRecordCompare() compatible function
|
||||
** suitable for comparing serialized records to the unpacked record passed
|
||||
** as the only argument.
|
||||
*/
|
||||
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
|
||||
/* varintRecordCompareInt() and varintRecordCompareString() both assume
|
||||
** that the size-of-header varint that occurs at the start of each record
|
||||
** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
|
||||
** also assumes that it is safe to overread a buffer by at least the
|
||||
** maximum possible legal header size plus 8 bytes. Because there is
|
||||
** guaranteed to be at least 74 (but not 136) bytes of padding following each
|
||||
** buffer passed to varintRecordCompareInt() this makes it convenient to
|
||||
** limit the size of the header to 64 bytes in cases where the first field
|
||||
** is an integer.
|
||||
**
|
||||
** The easiest way to enforce this limit is to consider only records with
|
||||
** 13 fields or less. If the first field is an integer, the maximum legal
|
||||
** header size is (12*5 + 1 + 1) bytes. */
|
||||
if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
|
||||
int flags = p->aMem[0].flags;
|
||||
if( p->pKeyInfo->aSortOrder[0] ){
|
||||
p->r1 = 1;
|
||||
p->r2 = -1;
|
||||
}else{
|
||||
p->r1 = -1;
|
||||
p->r2 = 1;
|
||||
}
|
||||
if( (flags & MEM_Int) ){
|
||||
return vdbeRecordCompareInt;
|
||||
}
|
||||
testcase( flags & MEM_Real );
|
||||
testcase( flags & MEM_Null );
|
||||
testcase( flags & MEM_Blob );
|
||||
if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){
|
||||
assert( flags & MEM_Str );
|
||||
return vdbeRecordCompareString;
|
||||
}
|
||||
}
|
||||
|
||||
return sqlite3VdbeRecordCompare;
|
||||
}
|
||||
|
||||
/*
|
||||
** pCur points at an index entry created using the OP_MakeRecord opcode.
|
||||
@@ -3322,9 +3872,9 @@ idx_rowid_corruption:
|
||||
** of the keys prior to the final rowid, not the entire key.
|
||||
*/
|
||||
int sqlite3VdbeIdxKeyCompare(
|
||||
VdbeCursor *pC, /* The cursor to compare against */
|
||||
UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */
|
||||
int *res /* Write the comparison result here */
|
||||
VdbeCursor *pC, /* The cursor to compare against */
|
||||
const UnpackedRecord *pUnpacked, /* Unpacked version of key */
|
||||
int *res /* Write the comparison result here */
|
||||
){
|
||||
i64 nCellKey = 0;
|
||||
int rc;
|
||||
@@ -3334,7 +3884,7 @@ int sqlite3VdbeIdxKeyCompare(
|
||||
assert( sqlite3BtreeCursorIsValid(pCur) );
|
||||
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
|
||||
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
|
||||
/* nCellKey will always be between 0 and 0xffffffff because of the say
|
||||
/* nCellKey will always be between 0 and 0xffffffff because of the way
|
||||
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
|
||||
if( nCellKey<=0 || nCellKey>0x7fffffff ){
|
||||
*res = 0;
|
||||
@@ -3345,8 +3895,7 @@ int sqlite3VdbeIdxKeyCompare(
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH );
|
||||
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
|
||||
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
|
||||
sqlite3VdbeMemRelease(&m);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -3410,7 +3959,6 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
|
||||
if( pRet ){
|
||||
sqlite3VdbeMemCopy((Mem *)pRet, pMem);
|
||||
sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
|
||||
sqlite3VdbeMemStoreType((Mem *)pRet);
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ int sqlite3_blob_open(
|
||||
** which closes the b-tree cursor and (possibly) commits the
|
||||
** transaction.
|
||||
*/
|
||||
static const int iLn = __LINE__+4;
|
||||
static const int iLn = VDBE_OFFSET_LINENO(4);
|
||||
static const VdbeOpList openBlob[] = {
|
||||
/* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */
|
||||
{OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */
|
||||
|
||||
+56
-148
@@ -18,6 +18,42 @@
|
||||
#include "sqliteInt.h"
|
||||
#include "vdbeInt.h"
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Check invariants on a Mem object.
|
||||
**
|
||||
** This routine is intended for use inside of assert() statements, like
|
||||
** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
|
||||
*/
|
||||
int sqlite3VdbeCheckMemInvariants(Mem *p){
|
||||
/* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor
|
||||
** function for Mem.z
|
||||
*/
|
||||
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
|
||||
assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 );
|
||||
|
||||
/* If p holds a string or blob, the Mem.z must point to exactly
|
||||
** one of the following:
|
||||
**
|
||||
** (1) Memory in Mem.zMalloc and managed by the Mem object
|
||||
** (2) Memory to be freed using Mem.xDel
|
||||
** (3) An ephermal string or blob
|
||||
** (4) A static string or blob
|
||||
*/
|
||||
if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){
|
||||
assert(
|
||||
((p->z==p->zMalloc)? 1 : 0) +
|
||||
((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
|
||||
((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
|
||||
((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** If pMem is an object with a valid string representation, this routine
|
||||
** ensures the internal encoding for the string representation is
|
||||
@@ -67,12 +103,7 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
|
||||
** in pMem->z is discarded.
|
||||
*/
|
||||
int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
|
||||
assert( 1 >=
|
||||
((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
|
||||
(((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
|
||||
((pMem->flags&MEM_Ephem) ? 1 : 0) +
|
||||
((pMem->flags&MEM_Static) ? 1 : 0)
|
||||
);
|
||||
assert( sqlite3VdbeCheckMemInvariants(pMem) );
|
||||
assert( (pMem->flags&MEM_RowSet)==0 );
|
||||
|
||||
/* If the bPreserve flag is set to true, then the memory cell must already
|
||||
@@ -90,7 +121,8 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
|
||||
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
|
||||
}
|
||||
if( pMem->zMalloc==0 ){
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
VdbeMemRelease(pMem);
|
||||
pMem->z = 0;
|
||||
pMem->flags = MEM_Null;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -99,13 +131,13 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
|
||||
if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
|
||||
memcpy(pMem->zMalloc, pMem->z, pMem->n);
|
||||
}
|
||||
if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){
|
||||
assert( pMem->xDel!=SQLITE_DYNAMIC );
|
||||
if( (pMem->flags&MEM_Dyn)!=0 ){
|
||||
assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
|
||||
pMem->xDel((void *)(pMem->z));
|
||||
}
|
||||
|
||||
pMem->z = pMem->zMalloc;
|
||||
pMem->flags &= ~(MEM_Ephem|MEM_Static);
|
||||
pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
|
||||
pMem->xDel = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -274,9 +306,9 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
|
||||
sqlite3VdbeMemFinalize(p, p->u.pDef);
|
||||
assert( (p->flags & MEM_Agg)==0 );
|
||||
sqlite3VdbeMemRelease(p);
|
||||
}else if( p->flags&MEM_Dyn && p->xDel ){
|
||||
}else if( p->flags&MEM_Dyn ){
|
||||
assert( (p->flags&MEM_RowSet)==0 );
|
||||
assert( p->xDel!=SQLITE_DYNAMIC );
|
||||
assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
|
||||
p->xDel((void *)p->z);
|
||||
p->xDel = 0;
|
||||
}else if( p->flags&MEM_RowSet ){
|
||||
@@ -289,9 +321,10 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
|
||||
/*
|
||||
** Release any memory held by the Mem. This may leave the Mem in an
|
||||
** inconsistent state, for example with (Mem.z==0) and
|
||||
** (Mem.memType==MEM_Str).
|
||||
** (Mem.flags==MEM_Str).
|
||||
*/
|
||||
void sqlite3VdbeMemRelease(Mem *p){
|
||||
assert( sqlite3VdbeCheckMemInvariants(p) );
|
||||
VdbeMemRelease(p);
|
||||
if( p->zMalloc ){
|
||||
sqlite3DbFree(p->db, p->zMalloc);
|
||||
@@ -480,7 +513,6 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
|
||||
sqlite3RowSetClear(pMem->u.pRowSet);
|
||||
}
|
||||
MemSetTypeFlag(pMem, MEM_Null);
|
||||
pMem->memType = MEM_Null;
|
||||
}
|
||||
void sqlite3ValueSetNull(sqlite3_value *p){
|
||||
sqlite3VdbeMemSetNull((Mem*)p);
|
||||
@@ -493,7 +525,6 @@ void sqlite3ValueSetNull(sqlite3_value *p){
|
||||
void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
pMem->flags = MEM_Blob|MEM_Zero;
|
||||
pMem->memType = MEM_Blob;
|
||||
pMem->n = 0;
|
||||
if( n<0 ) n = 0;
|
||||
pMem->u.nZero = n;
|
||||
@@ -516,7 +547,6 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
pMem->u.i = val;
|
||||
pMem->flags = MEM_Int;
|
||||
pMem->memType = MEM_Int;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
@@ -531,7 +561,6 @@ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
pMem->r = val;
|
||||
pMem->flags = MEM_Real;
|
||||
pMem->memType = MEM_Real;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -629,6 +658,7 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
|
||||
VdbeMemRelease(pTo);
|
||||
memcpy(pTo, pFrom, MEMCELLSIZE);
|
||||
pTo->flags &= ~MEM_Dyn;
|
||||
pTo->xDel = 0;
|
||||
|
||||
if( pTo->flags&(MEM_Str|MEM_Blob) ){
|
||||
if( 0==(pFrom->flags&MEM_Static) ){
|
||||
@@ -739,7 +769,6 @@ int sqlite3VdbeMemSetStr(
|
||||
pMem->n = nByte;
|
||||
pMem->flags = flags;
|
||||
pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
|
||||
pMem->memType = flags&0x1f;
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
|
||||
@@ -754,119 +783,6 @@ int sqlite3VdbeMemSetStr(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare the values contained by the two memory cells, returning
|
||||
** negative, zero or positive if pMem1 is less than, equal to, or greater
|
||||
** than pMem2. Sorting order is NULL's first, followed by numbers (integers
|
||||
** and reals) sorted numerically, followed by text ordered by the collating
|
||||
** sequence pColl and finally blob's ordered by memcmp().
|
||||
**
|
||||
** Two NULL values are considered equal by this function.
|
||||
*/
|
||||
int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
|
||||
int rc;
|
||||
int f1, f2;
|
||||
int combined_flags;
|
||||
|
||||
f1 = pMem1->flags;
|
||||
f2 = pMem2->flags;
|
||||
combined_flags = f1|f2;
|
||||
assert( (combined_flags & MEM_RowSet)==0 );
|
||||
|
||||
/* If one value is NULL, it is less than the other. If both values
|
||||
** are NULL, return 0.
|
||||
*/
|
||||
if( combined_flags&MEM_Null ){
|
||||
return (f2&MEM_Null) - (f1&MEM_Null);
|
||||
}
|
||||
|
||||
/* If one value is a number and the other is not, the number is less.
|
||||
** If both are numbers, compare as reals if one is a real, or as integers
|
||||
** if both values are integers.
|
||||
*/
|
||||
if( combined_flags&(MEM_Int|MEM_Real) ){
|
||||
double r1, r2;
|
||||
if( (f1 & f2 & MEM_Int)!=0 ){
|
||||
if( pMem1->u.i < pMem2->u.i ) return -1;
|
||||
if( pMem1->u.i > pMem2->u.i ) return 1;
|
||||
return 0;
|
||||
}
|
||||
if( (f1&MEM_Real)!=0 ){
|
||||
r1 = pMem1->r;
|
||||
}else if( (f1&MEM_Int)!=0 ){
|
||||
r1 = (double)pMem1->u.i;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
if( (f2&MEM_Real)!=0 ){
|
||||
r2 = pMem2->r;
|
||||
}else if( (f2&MEM_Int)!=0 ){
|
||||
r2 = (double)pMem2->u.i;
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
if( r1<r2 ) return -1;
|
||||
if( r1>r2 ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If one value is a string and the other is a blob, the string is less.
|
||||
** If both are strings, compare using the collating functions.
|
||||
*/
|
||||
if( combined_flags&MEM_Str ){
|
||||
if( (f1 & MEM_Str)==0 ){
|
||||
return 1;
|
||||
}
|
||||
if( (f2 & MEM_Str)==0 ){
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert( pMem1->enc==pMem2->enc );
|
||||
assert( pMem1->enc==SQLITE_UTF8 ||
|
||||
pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
|
||||
|
||||
/* The collation sequence must be defined at this point, even if
|
||||
** the user deletes the collation sequence after the vdbe program is
|
||||
** compiled (this was not always the case).
|
||||
*/
|
||||
assert( !pColl || pColl->xCmp );
|
||||
|
||||
if( pColl ){
|
||||
if( pMem1->enc==pColl->enc ){
|
||||
/* The strings are already in the correct encoding. Call the
|
||||
** comparison function directly */
|
||||
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
|
||||
}else{
|
||||
const void *v1, *v2;
|
||||
int n1, n2;
|
||||
Mem c1;
|
||||
Mem c2;
|
||||
memset(&c1, 0, sizeof(c1));
|
||||
memset(&c2, 0, sizeof(c2));
|
||||
sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
|
||||
sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
|
||||
v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
|
||||
n1 = v1==0 ? 0 : c1.n;
|
||||
v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
|
||||
n2 = v2==0 ? 0 : c2.n;
|
||||
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
|
||||
sqlite3VdbeMemRelease(&c1);
|
||||
sqlite3VdbeMemRelease(&c2);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
/* If a NULL pointer was passed as the collate function, fall through
|
||||
** to the blob case and use memcmp(). */
|
||||
}
|
||||
|
||||
/* Both values must be blobs. Compare using memcmp(). */
|
||||
rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
|
||||
if( rc==0 ){
|
||||
rc = pMem1->n - pMem2->n;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Move data out of a btree key or data field and into a Mem structure.
|
||||
** The data or key is taken from the entry that pCur is currently pointing
|
||||
@@ -907,22 +823,22 @@ int sqlite3VdbeMemFromBtree(
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
pMem->z = &zData[offset];
|
||||
pMem->flags = MEM_Blob|MEM_Ephem;
|
||||
pMem->n = (int)amt;
|
||||
}else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
|
||||
pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
|
||||
pMem->enc = 0;
|
||||
pMem->memType = MEM_Blob;
|
||||
if( key ){
|
||||
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
|
||||
}else{
|
||||
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
|
||||
}
|
||||
pMem->z[amt] = 0;
|
||||
pMem->z[amt+1] = 0;
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_OK ){
|
||||
pMem->z[amt] = 0;
|
||||
pMem->z[amt+1] = 0;
|
||||
pMem->flags = MEM_Blob|MEM_Term;
|
||||
pMem->n = (int)amt;
|
||||
}else{
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
}
|
||||
}
|
||||
pMem->n = (int)amt;
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -980,7 +896,6 @@ sqlite3_value *sqlite3ValueNew(sqlite3 *db){
|
||||
Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
|
||||
if( p ){
|
||||
p->flags = MEM_Null;
|
||||
p->memType = MEM_Null;
|
||||
p->db = db;
|
||||
}
|
||||
return p;
|
||||
@@ -1026,11 +941,9 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
|
||||
if( pRec->pKeyInfo ){
|
||||
assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
|
||||
assert( pRec->pKeyInfo->enc==ENC(db) );
|
||||
pRec->flags = UNPACKED_PREFIX_MATCH;
|
||||
pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
|
||||
for(i=0; i<nCol; i++){
|
||||
pRec->aMem[i].flags = MEM_Null;
|
||||
pRec->aMem[i].memType = MEM_Null;
|
||||
pRec->aMem[i].db = db;
|
||||
}
|
||||
}else{
|
||||
@@ -1103,7 +1016,6 @@ static int valueFromExpr(
|
||||
zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
|
||||
if( zVal==0 ) goto no_mem;
|
||||
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
|
||||
if( op==TK_FLOAT ) pVal->memType = MEM_Real;
|
||||
}
|
||||
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
|
||||
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
|
||||
@@ -1121,9 +1033,9 @@ static int valueFromExpr(
|
||||
){
|
||||
sqlite3VdbeMemNumerify(pVal);
|
||||
if( pVal->u.i==SMALLEST_INT64 ){
|
||||
pVal->flags &= MEM_Int;
|
||||
pVal->flags &= ~MEM_Int;
|
||||
pVal->flags |= MEM_Real;
|
||||
pVal->r = (double)LARGEST_INT64;
|
||||
pVal->r = (double)SMALLEST_INT64;
|
||||
}else{
|
||||
pVal->u.i = -pVal->u.i;
|
||||
}
|
||||
@@ -1149,9 +1061,6 @@ static int valueFromExpr(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( pVal ){
|
||||
sqlite3VdbeMemStoreType(pVal);
|
||||
}
|
||||
*ppVal = pVal;
|
||||
return rc;
|
||||
|
||||
@@ -1315,7 +1224,6 @@ int sqlite3Stat4ProbeSetValue(
|
||||
sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
|
||||
}
|
||||
pVal->db = pParse->db;
|
||||
sqlite3VdbeMemStoreType((Mem*)pVal);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
+49
-8
@@ -409,10 +409,10 @@ static void vdbeSorterCompare(
|
||||
return;
|
||||
}
|
||||
}
|
||||
r2->flags |= UNPACKED_PREFIX_MATCH;
|
||||
assert( r2->default_rc==0 );
|
||||
}
|
||||
|
||||
*pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
|
||||
*pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -956,14 +956,55 @@ int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
|
||||
|
||||
if( pSorter->aTree ){
|
||||
int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
|
||||
int i; /* Index of aTree[] to recalculate */
|
||||
|
||||
rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
|
||||
for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
|
||||
rc = vdbeSorterDoCompare(pCsr, i);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int i; /* Index of aTree[] to recalculate */
|
||||
VdbeSorterIter *pIter1; /* First iterator to compare */
|
||||
VdbeSorterIter *pIter2; /* Second iterator to compare */
|
||||
u8 *pKey2; /* To pIter2->aKey, or 0 if record cached */
|
||||
|
||||
*pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
|
||||
/* Find the first two iterators to compare. The one that was just
|
||||
** advanced (iPrev) and the one next to it in the array. */
|
||||
pIter1 = &pSorter->aIter[(iPrev & 0xFFFE)];
|
||||
pIter2 = &pSorter->aIter[(iPrev | 0x0001)];
|
||||
pKey2 = pIter2->aKey;
|
||||
|
||||
for(i=(pSorter->nTree+iPrev)/2; i>0; i=i/2){
|
||||
/* Compare pIter1 and pIter2. Store the result in variable iRes. */
|
||||
int iRes;
|
||||
if( pIter1->pFile==0 ){
|
||||
iRes = +1;
|
||||
}else if( pIter2->pFile==0 ){
|
||||
iRes = -1;
|
||||
}else{
|
||||
vdbeSorterCompare(pCsr, 0,
|
||||
pIter1->aKey, pIter1->nKey, pKey2, pIter2->nKey, &iRes
|
||||
);
|
||||
}
|
||||
|
||||
/* If pIter1 contained the smaller value, set aTree[i] to its index.
|
||||
** Then set pIter2 to the next iterator to compare to pIter1. In this
|
||||
** case there is no cache of pIter2 in pSorter->pUnpacked, so set
|
||||
** pKey2 to point to the record belonging to pIter2.
|
||||
**
|
||||
** Alternatively, if pIter2 contains the smaller of the two values,
|
||||
** set aTree[i] to its index and update pIter1. If vdbeSorterCompare()
|
||||
** was actually called above, then pSorter->pUnpacked now contains
|
||||
** a value equivalent to pIter2. So set pKey2 to NULL to prevent
|
||||
** vdbeSorterCompare() from decoding pIter2 again. */
|
||||
if( iRes<=0 ){
|
||||
pSorter->aTree[i] = (pIter1 - pSorter->aIter);
|
||||
pIter2 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ];
|
||||
pKey2 = pIter2->aKey;
|
||||
}else{
|
||||
if( pIter1->pFile ) pKey2 = 0;
|
||||
pSorter->aTree[i] = (pIter2 - pSorter->aIter);
|
||||
pIter1 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ];
|
||||
}
|
||||
|
||||
}
|
||||
*pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
|
||||
}
|
||||
}else{
|
||||
SorterRecord *pFree = pSorter->pRecord;
|
||||
pSorter->pRecord = pFree->pNext;
|
||||
|
||||
+69
-58
@@ -1601,7 +1601,7 @@ static void constructAutomaticIndex(
|
||||
** transient index on 2nd and subsequent iterations of the loop. */
|
||||
v = pParse->pVdbe;
|
||||
assert( v!=0 );
|
||||
addrInit = sqlite3CodeOnce(pParse);
|
||||
addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
|
||||
/* Count the number of columns that will be added to the index
|
||||
** and used to match WHERE clause constraints */
|
||||
@@ -1913,7 +1913,7 @@ static void whereKeyStats(
|
||||
assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
|
||||
do{
|
||||
iTest = (iMin+i)/2;
|
||||
res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
|
||||
res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0);
|
||||
if( res<0 ){
|
||||
iMin = iTest+1;
|
||||
}else{
|
||||
@@ -1928,16 +1928,16 @@ static void whereKeyStats(
|
||||
if( res==0 ){
|
||||
/* If (res==0) is true, then sample $i must be equal to pRec */
|
||||
assert( i<pIdx->nSample );
|
||||
assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
|
||||
assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)
|
||||
|| pParse->db->mallocFailed );
|
||||
}else{
|
||||
/* Otherwise, pRec must be smaller than sample $i and larger than
|
||||
** sample ($i-1). */
|
||||
assert( i==pIdx->nSample
|
||||
|| sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
|
||||
|| sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0
|
||||
|| pParse->db->mallocFailed );
|
||||
assert( i==0
|
||||
|| sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
|
||||
|| sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0
|
||||
|| pParse->db->mallocFailed );
|
||||
}
|
||||
#endif /* ifdef SQLITE_DEBUG */
|
||||
@@ -2388,7 +2388,9 @@ static int codeEqualityTerm(
|
||||
bRev = !bRev;
|
||||
}
|
||||
iTab = pX->iTable;
|
||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
|
||||
VdbeCoverageIf(v, bRev);
|
||||
VdbeCoverageIf(v, !bRev);
|
||||
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
|
||||
pLoop->wsFlags |= WHERE_IN_ABLE;
|
||||
if( pLevel->u.in.nIn==0 ){
|
||||
@@ -2502,11 +2504,15 @@ static int codeAllEqualityTerms(
|
||||
|
||||
if( nSkip ){
|
||||
int iIdxCur = pLevel->iIdxCur;
|
||||
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
|
||||
VdbeCoverageIf(v, bRev==0);
|
||||
VdbeCoverageIf(v, bRev!=0);
|
||||
VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
|
||||
j = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
|
||||
iIdxCur, 0, regBase, nSkip); VdbeCoverage(v);
|
||||
iIdxCur, 0, regBase, nSkip);
|
||||
VdbeCoverageIf(v, bRev==0);
|
||||
VdbeCoverageIf(v, bRev!=0);
|
||||
sqlite3VdbeJumpHere(v, j);
|
||||
for(j=0; j<nSkip; j++){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
|
||||
@@ -2539,7 +2545,10 @@ static int codeAllEqualityTerms(
|
||||
testcase( pTerm->eOperator & WO_IN );
|
||||
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk);
|
||||
if( sqlite3ExprCanBeNull(pRight) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( zAff ){
|
||||
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
|
||||
zAff[j] = SQLITE_AFF_NONE;
|
||||
@@ -2844,13 +2853,14 @@ static Bitmask codeOneLoopStart(
|
||||
** construct.
|
||||
*/
|
||||
assert( pLoop->u.btree.nEq==1 );
|
||||
iReleaseReg = sqlite3GetTempReg(pParse);
|
||||
pTerm = pLoop->aLTerm[0];
|
||||
assert( pTerm!=0 );
|
||||
assert( pTerm->pExpr!=0 );
|
||||
assert( omitTable==0 );
|
||||
testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
||||
iReleaseReg = ++pParse->nMem;
|
||||
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
|
||||
if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
|
||||
addrNxt = pLevel->addrNxt;
|
||||
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
|
||||
@@ -2904,13 +2914,18 @@ static Bitmask codeOneLoopStart(
|
||||
testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
|
||||
sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
|
||||
VdbeComment((v, "pk")); VdbeCoverage(v);
|
||||
VdbeComment((v, "pk"));
|
||||
VdbeCoverageIf(v, pX->op==TK_GT);
|
||||
VdbeCoverageIf(v, pX->op==TK_LE);
|
||||
VdbeCoverageIf(v, pX->op==TK_LT);
|
||||
VdbeCoverageIf(v, pX->op==TK_GE);
|
||||
sqlite3ExprCacheAffinityChange(pParse, r1, 1);
|
||||
sqlite3ReleaseTempReg(pParse, rTemp);
|
||||
disableTerm(pLevel, pStart);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, bRev==0);
|
||||
VdbeCoverageIf(v, bRev!=0);
|
||||
}
|
||||
if( pEnd ){
|
||||
Expr *pX;
|
||||
@@ -2934,11 +2949,14 @@ static Bitmask codeOneLoopStart(
|
||||
pLevel->p2 = start;
|
||||
assert( pLevel->p5==0 );
|
||||
if( testOp!=OP_Noop ){
|
||||
iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
|
||||
iRowidReg = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
|
||||
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
|
||||
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, testOp==OP_Le);
|
||||
VdbeCoverageIf(v, testOp==OP_Lt);
|
||||
VdbeCoverageIf(v, testOp==OP_Ge);
|
||||
VdbeCoverageIf(v, testOp==OP_Gt);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
|
||||
}
|
||||
}else if( pLoop->wsFlags & WHERE_INDEXED ){
|
||||
@@ -3039,13 +3057,13 @@ static Bitmask codeOneLoopStart(
|
||||
pRangeEnd = pLoop->aLTerm[j++];
|
||||
nExtraReg = 1;
|
||||
if( pRangeStart==0
|
||||
&& (pRangeEnd->wtFlags & TERM_VNULL)==0
|
||||
&& (j = pIdx->aiColumn[nEq])>=0
|
||||
&& pIdx->pTable->aCol[j].notNull==0
|
||||
){
|
||||
bSeekPastNull = 1;
|
||||
}
|
||||
}
|
||||
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
|
||||
|
||||
/* Generate code to evaluate all constraint terms using == or IN
|
||||
** and store the values of those terms in an array of registers
|
||||
@@ -3080,8 +3098,11 @@ static Bitmask codeOneLoopStart(
|
||||
if( pRangeStart ){
|
||||
Expr *pRight = pRangeStart->pExpr->pRight;
|
||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||
if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){
|
||||
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
|
||||
if( (pRangeStart->wtFlags & TERM_VNULL)==0
|
||||
&& sqlite3ExprCanBeNull(pRight)
|
||||
){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( zStartAff ){
|
||||
if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){
|
||||
@@ -3105,20 +3126,14 @@ static Bitmask codeOneLoopStart(
|
||||
codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
|
||||
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
||||
assert( op!=0 );
|
||||
testcase( op==OP_Rewind );
|
||||
testcase( op==OP_Last );
|
||||
testcase( op==OP_SeekGT );
|
||||
testcase( op==OP_SeekGE );
|
||||
testcase( op==OP_SeekLE );
|
||||
testcase( op==OP_SeekLT );
|
||||
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, op==OP_Rewind);
|
||||
VdbeCoverageIf(v, op==OP_Last);
|
||||
VdbeCoverageIf(v, op==OP_SeekGT);
|
||||
VdbeCoverageIf(v, op==OP_SeekGE);
|
||||
VdbeCoverageIf(v, op==OP_SeekLE);
|
||||
VdbeCoverageIf(v, op==OP_SeekLT);
|
||||
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
|
||||
VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last );
|
||||
VdbeCoverageIf(v, op==OP_SeekGT); testcase( op==OP_SeekGT );
|
||||
VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
|
||||
VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
|
||||
VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT );
|
||||
|
||||
/* Load the value for the inequality constraint at the end of the
|
||||
** range (if any).
|
||||
@@ -3128,8 +3143,11 @@ static Bitmask codeOneLoopStart(
|
||||
Expr *pRight = pRangeEnd->pExpr->pRight;
|
||||
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
|
||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||
if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){
|
||||
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
|
||||
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
|
||||
&& sqlite3ExprCanBeNull(pRight)
|
||||
){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE
|
||||
&& !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff)
|
||||
@@ -3151,12 +3169,11 @@ static Bitmask codeOneLoopStart(
|
||||
/* Check if the index cursor is past the end of the range. */
|
||||
if( nConstraint ){
|
||||
op = aEndOp[bRev*2 + endEq];
|
||||
testcase( op==OP_IdxGT );
|
||||
testcase( op==OP_IdxGE );
|
||||
testcase( op==OP_IdxLT );
|
||||
testcase( op==OP_IdxLE );
|
||||
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
||||
VdbeCoverage(v);
|
||||
testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
|
||||
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
|
||||
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
|
||||
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
|
||||
}
|
||||
|
||||
/* Seek the table cursor, if required */
|
||||
@@ -3165,7 +3182,7 @@ static Bitmask codeOneLoopStart(
|
||||
if( omitTable ){
|
||||
/* pIdx is a covering index. No need to access the main table. */
|
||||
}else if( HasRowid(pIdx->pTable) ){
|
||||
iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
|
||||
iRowidReg = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
|
||||
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
|
||||
sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
|
||||
@@ -3430,8 +3447,8 @@ static Bitmask codeOneLoopStart(
|
||||
pLevel->op = aStep[bRev];
|
||||
pLevel->p1 = iCur;
|
||||
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
|
||||
VdbeCoverageIf(v, bRev);
|
||||
VdbeCoverageIf(v, !bRev);
|
||||
VdbeCoverageIf(v, bRev==0);
|
||||
VdbeCoverageIf(v, bRev!=0);
|
||||
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
|
||||
}
|
||||
}
|
||||
@@ -3513,7 +3530,6 @@ static Bitmask codeOneLoopStart(
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
}
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, iReleaseReg);
|
||||
|
||||
return pLevel->notReady;
|
||||
}
|
||||
@@ -3958,7 +3974,10 @@ static int whereLoopAddBtreeIndex(
|
||||
pNew->aLTerm[pNew->nLTerm++] = 0;
|
||||
pNew->wsFlags |= WHERE_SKIPSCAN;
|
||||
nIter = sqlite3LogEst(pProbe->aiRowEst[0]/pProbe->aiRowEst[saved_nEq+1]);
|
||||
pNew->rRun = rLogSize + nIter;
|
||||
pNew->nOut += nIter;
|
||||
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter);
|
||||
pNew->nOut = saved_nOut;
|
||||
}
|
||||
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
|
||||
int nIn = 0;
|
||||
@@ -4885,9 +4904,12 @@ static int wherePathSatisfiesOrderBy(
|
||||
orderDistinctMask |= pLoop->maskSelf;
|
||||
for(i=0; i<nOrderBy; i++){
|
||||
Expr *p;
|
||||
Bitmask mTerm;
|
||||
if( MASKBIT(i) & obSat ) continue;
|
||||
p = pOrderBy->a[i].pExpr;
|
||||
if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){
|
||||
mTerm = exprTableUsage(&pWInfo->sMaskSet,p);
|
||||
if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue;
|
||||
if( (mTerm&~orderDistinctMask)==0 ){
|
||||
obSat |= MASKBIT(i);
|
||||
}
|
||||
}
|
||||
@@ -5510,22 +5532,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
goto whereBeginError;
|
||||
}
|
||||
|
||||
/* If the ORDER BY (or GROUP BY) clause contains references to general
|
||||
** expressions, then we won't be able to satisfy it using indices, so
|
||||
** go ahead and disable it now.
|
||||
*/
|
||||
if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){
|
||||
for(ii=0; ii<pOrderBy->nExpr; ii++){
|
||||
Expr *pExpr = sqlite3ExprSkipCollate(pOrderBy->a[ii].pExpr);
|
||||
if( pExpr->op!=TK_COLUMN ){
|
||||
pWInfo->pOrderBy = pOrderBy = 0;
|
||||
break;
|
||||
}else if( pExpr->iColumn<0 ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
|
||||
/* The DISTINCT marking is pointless. Ignore it. */
|
||||
@@ -5802,6 +5808,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
|
||||
sqlite3VdbeChangeP5(v, pLevel->p5);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, pLevel->op==OP_Next);
|
||||
VdbeCoverageIf(v, pLevel->op==OP_Prev);
|
||||
VdbeCoverageIf(v, pLevel->op==OP_VNext);
|
||||
}
|
||||
if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
|
||||
struct InLoop *pIn;
|
||||
@@ -5811,6 +5820,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
|
||||
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
|
||||
VdbeCoverage(v);
|
||||
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
|
||||
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
|
||||
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
|
||||
}
|
||||
sqlite3DbFree(db, pLevel->u.in.aInLoop);
|
||||
@@ -5862,7 +5873,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
** the co-routine into OP_SCopy of result contained in a register.
|
||||
** OP_Rowid becomes OP_Null.
|
||||
*/
|
||||
if( pTabItem->viaCoroutine ){
|
||||
if( pTabItem->viaCoroutine && !db->mallocFailed ){
|
||||
last = sqlite3VdbeCurrentAddr(v);
|
||||
k = pLevel->addrBody;
|
||||
pOp = sqlite3VdbeGetOp(v, k);
|
||||
|
||||
@@ -334,4 +334,25 @@ do_test alter4-8.2 {
|
||||
}
|
||||
} [list $::sql]
|
||||
|
||||
|
||||
# Test that a default value equal to -1 multipied by the smallest possible
|
||||
# 64-bit integer is correctly converted to a real.
|
||||
do_execsql_test alter4-9.1 {
|
||||
CREATE TABLE t5(
|
||||
a INTEGER DEFAULT -9223372036854775808,
|
||||
b INTEGER DEFAULT (-(-9223372036854775808))
|
||||
);
|
||||
INSERT INTO t5 DEFAULT VALUES;
|
||||
}
|
||||
|
||||
do_execsql_test alter4-9.2 { SELECT typeof(a), a, typeof(b), b FROM t5; } {
|
||||
integer -9223372036854775808
|
||||
real 9.22337203685478e+18
|
||||
}
|
||||
|
||||
do_execsql_test alter4-9.3 {
|
||||
ALTER TABLE t5 ADD COLUMN c INTEGER DEFAULT (-(-9223372036854775808));
|
||||
SELECT typeof(c), c FROM t5;
|
||||
} {real 9.22337203685478e+18}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -326,6 +326,7 @@ do_execsql_test 6.2 {
|
||||
reset_db
|
||||
sqlite3_db_config_lookaside db 0 0 0
|
||||
|
||||
database_may_be_corrupt
|
||||
do_execsql_test 7.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
@@ -366,6 +367,8 @@ do_execsql_test 7.5 {
|
||||
SELECT * FROM t1 WHERE a = 5;
|
||||
} {5 5}
|
||||
|
||||
database_never_corrupt
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix capi3
|
||||
|
||||
# Do not use a codec for tests in this file, as the database file is
|
||||
# manipulated directly using tcl scripts (using the [hexio_write] command).
|
||||
@@ -1221,6 +1222,23 @@ do_test capi3-19.1 {
|
||||
sqlite3_prepare_tkt3134 db
|
||||
} {}
|
||||
|
||||
# Test that calling sqlite3_column_blob() on a TEXT value does not change
|
||||
# the return type of subsequent calls to sqlite3_column_type().
|
||||
#
|
||||
do_execsql_test 20.1 {
|
||||
CREATE TABLE t4(x);
|
||||
INSERT INTO t4 VALUES('abcdefghij');
|
||||
}
|
||||
do_test 20.2 {
|
||||
set stmt [sqlite3_prepare db "SELECT * FROM t4" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_ROW}
|
||||
do_test 20.3 { sqlite3_column_type $stmt 0 } {TEXT}
|
||||
do_test 20.4 { sqlite3_column_blob $stmt 0 } {abcdefghij}
|
||||
do_test 20.5 { sqlite3_column_type $stmt 0 } {TEXT}
|
||||
do_test 20.6 { sqlite3_finalize $stmt } SQLITE_OK
|
||||
|
||||
|
||||
# Tests of the interface when no VFS is registered.
|
||||
#
|
||||
if {![info exists tester_do_binarylog]} {
|
||||
|
||||
+1
-1
@@ -76,6 +76,6 @@ do_test 2.1 {
|
||||
# incorrect answer from a corrupt database file, that is OK. If the
|
||||
# result below changes, that just means that "undefined behavior" has
|
||||
# changed.
|
||||
} {0 52}
|
||||
} {/0 .*/}
|
||||
|
||||
finish_test
|
||||
|
||||
+13
-11
@@ -20,6 +20,18 @@ set testprefix corruptH
|
||||
do_not_use_codec
|
||||
database_may_be_corrupt
|
||||
|
||||
# The corruption migrations tested by the code in this file are not detected
|
||||
# mmap mode.
|
||||
#
|
||||
# The reason is that in mmap mode, the different queries may use different
|
||||
# PgHdr objects for the same page (same data, but different PgHdr container
|
||||
# objects). And so the corruption is not detected.
|
||||
#
|
||||
if {[permutation]=="mmap"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Initialize the database.
|
||||
#
|
||||
do_execsql_test 1.1 {
|
||||
@@ -52,6 +64,7 @@ do_test 1.2 {
|
||||
} {}
|
||||
|
||||
do_test 1.3 {
|
||||
breakpoint
|
||||
db eval { PRAGMA secure_delete=1 }
|
||||
list [catch {
|
||||
db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
|
||||
@@ -97,9 +110,6 @@ do_test 2.2 {
|
||||
} {}
|
||||
|
||||
|
||||
# The corruption migration caused by the test case below does not
|
||||
# cause corruption to be detected in mmap mode.
|
||||
#
|
||||
# The trick here is that the root page of the tree scanned by the outer
|
||||
# query is also currently on the free-list. So while the first seek on
|
||||
# the table (for a==1) works, by the time the second is attempted The
|
||||
@@ -109,15 +119,7 @@ do_test 2.2 {
|
||||
# the cursor (as it is now marked with PgHdr.intKey==0) and returns
|
||||
# SQLITE_CORRUPT.
|
||||
#
|
||||
# However, in mmap mode, the outer query and the inner queries use
|
||||
# different PgHdr objects (same data, but different PgHdr container
|
||||
# objects). And so the corruption is not detected. Instead, the second
|
||||
# seek fails to find anything and only a single row is returned.
|
||||
#
|
||||
set res23 {1 {database disk image is malformed}}
|
||||
if {[permutation]=="mmap"} {
|
||||
set res23 {0 one}
|
||||
}
|
||||
do_test 2.3 {
|
||||
list [catch {
|
||||
set res [list]
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# 2014-01-20
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix corruptI
|
||||
|
||||
if {[permutation]=="mmap"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Do not use a codec for tests in this file, as the database file is
|
||||
# manipulated directly using tcl scripts (using the [hexio_write] command).
|
||||
#
|
||||
do_not_use_codec
|
||||
database_may_be_corrupt
|
||||
|
||||
# Initialize the database.
|
||||
#
|
||||
do_execsql_test 1.1 {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=0;
|
||||
CREATE TABLE t1(a);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
INSERT INTO t1 VALUES('a');
|
||||
} {}
|
||||
db close
|
||||
|
||||
do_test 1.2 {
|
||||
set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]]
|
||||
set off [expr 2*1024 + $offset + 1]
|
||||
hexio_write test.db $off FF06
|
||||
|
||||
breakpoint
|
||||
|
||||
sqlite3 db test.db
|
||||
catchsql { SELECT * FROM t1 WHERE a = 10 }
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -219,4 +219,32 @@ do_execsql_test 5.2 {
|
||||
SELECT count(*) FROM sqlite_master WHERE name LIKE 't8%';
|
||||
} {0 6}
|
||||
|
||||
# At one point this was causing a memory leak.
|
||||
#
|
||||
foreach {tn sql} {
|
||||
1 {}
|
||||
2 { INSERT INTO ft(ft) VALUES('merge=2,2'); }
|
||||
} {
|
||||
reset_db
|
||||
do_execsql_test 6.$tn.1 "
|
||||
CREATE TABLE t1(x);
|
||||
CREATE VIRTUAL TABLE ft USING fts3;
|
||||
INSERT INTO ft VALUES('hello world');
|
||||
$sql
|
||||
"
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 6.$tn.2 { SELECT * FROM t1 } {}
|
||||
|
||||
do_test 6.$tn.3 {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval { DROP TABLE t1 }
|
||||
db2 close
|
||||
set stmt [sqlite3_prepare db { SELECT * FROM ft } -1 dummy]
|
||||
sqlite3_finalize $stmt
|
||||
} {SQLITE_OK}
|
||||
db close
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -354,6 +354,17 @@ do_test fts3d-6.5 {
|
||||
SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
|
||||
}
|
||||
} {xyz_content xyz_segdir xyz_segments}
|
||||
|
||||
# ALTER TABLE RENAME on an FTS3 table following an incr-merge op.
|
||||
#
|
||||
do_test fts3d-6.6 {
|
||||
execsql { INSERT INTO xyz(xyz) VALUES('merge=2,2') }
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
ALTER TABLE xyz RENAME TO ott;
|
||||
SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
|
||||
}
|
||||
} {ott_content ott_segdir ott_segments ott_stat}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1361,4 +1361,9 @@ for {set i 65536} {$i<=0x10ffff} {incr i 139} {
|
||||
do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
|
||||
}
|
||||
|
||||
# Test char().
|
||||
#
|
||||
do_execsql_test func-31.1 {
|
||||
SELECT char(), length(char()), typeof(char())
|
||||
} {{} 0 text}
|
||||
finish_test
|
||||
|
||||
@@ -641,4 +641,39 @@ do_test join-11.10 {
|
||||
execsql { SELECT * FROM t2 NATURAL JOIN t1 }
|
||||
} {1 one 2 two}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that at most 64 tables are allowed in a join.
|
||||
#
|
||||
do_execsql_test join-12.1 {
|
||||
CREATE TABLE t14(x);
|
||||
INSERT INTO t14 VALUES('abcdefghij');
|
||||
}
|
||||
|
||||
proc jointest {tn nTbl res} {
|
||||
set sql "SELECT 1 FROM [string repeat t14, [expr $nTbl-1]] t14;"
|
||||
uplevel [list do_catchsql_test $tn $sql $res]
|
||||
}
|
||||
|
||||
jointest join-12.2 30 {0 1}
|
||||
jointest join-12.3 63 {0 1}
|
||||
jointest join-12.4 64 {0 1}
|
||||
jointest join-12.5 65 {1 {at most 64 tables in a join}}
|
||||
jointest join-12.6 66 {1 {at most 64 tables in a join}}
|
||||
jointest join-12.7 127 {1 {at most 64 tables in a join}}
|
||||
jointest join-12.8 128 {1 {at most 64 tables in a join}}
|
||||
jointest join-12.9 1000 {1 {at most 64 tables in a join}}
|
||||
|
||||
# If SQLite is built with SQLITE_MEMDEBUG, then the huge number of realloc()
|
||||
# calls made by the following test cases are too time consuming to run.
|
||||
# Without SQLITE_MEMDEBUG, realloc() is fast enough that these are not
|
||||
# a problem.
|
||||
ifcapable pragma&&compileoption_diags {
|
||||
if {[lsearch [db eval {PRAGMA compile_options}] MEMDEBUG]<0} {
|
||||
jointest join-12.10 65534 {1 {at most 64 tables in a join}}
|
||||
jointest join-12.11 65535 {1 {too many references to "t14": max 65535}}
|
||||
jointest join-12.12 65536 {1 {too many references to "t14": max 65535}}
|
||||
jointest join-12.13 65537 {1 {too many references to "t14": max 65535}}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+17
-4
@@ -66,6 +66,12 @@ if {$::tcl_platform(os) eq "Darwin"} {
|
||||
set dlerror_nosymbol {dlsym(XXX, %2$s): symbol not found}
|
||||
}
|
||||
|
||||
if {$::tcl_platform(platform) eq "windows"} {
|
||||
set dlerror_nosuchfile {The specified module could not be found.*}
|
||||
set dlerror_notadll {%%1 is not a valid Win32 application.*}
|
||||
set dlerror_nosymbol {The specified procedure could not be found.*}
|
||||
}
|
||||
|
||||
# Make sure the test extension actually exists. If it does not
|
||||
# exist, try to create it. If unable to create it, then skip this
|
||||
# test file.
|
||||
@@ -167,7 +173,7 @@ do_test loadext-2.3 {
|
||||
regsub {0x[1234567890abcdefABCDEF]*} $msg XXX msg
|
||||
}
|
||||
list $rc $msg
|
||||
} [list 1 [format $dlerror_nosymbol $testextension icecream]]
|
||||
} /[list 1 [format $dlerror_nosymbol $testextension icecream]]/
|
||||
|
||||
# Try to load an extension for which the entry point fails (returns non-zero)
|
||||
#
|
||||
@@ -267,10 +273,17 @@ do_malloc_test loadext-5 -tclprep {
|
||||
} -tclbody {
|
||||
if {[autoinstall_test_functions]==7} {error "out of memory"}
|
||||
}
|
||||
do_malloc_test loadext-6 -tclbody {
|
||||
db enable_load_extension 1
|
||||
sqlite3_load_extension db $::testextension testloadext_init
|
||||
|
||||
# On Windows, this malloc test must be skipped because the winDlOpen
|
||||
# function itself can fail due to "out of memory" conditions.
|
||||
#
|
||||
if {$::tcl_platform(platform) ne "windows"} {
|
||||
do_malloc_test loadext-6 -tclbody {
|
||||
db enable_load_extension 1
|
||||
sqlite3_load_extension db $::testextension testloadext_init
|
||||
}
|
||||
}
|
||||
|
||||
autoinstall_test_functions
|
||||
|
||||
finish_test
|
||||
|
||||
+13
-5
@@ -1575,6 +1575,8 @@ do_test pragma-20.8 {
|
||||
forcedelete data_dir
|
||||
} ;# endif windows
|
||||
|
||||
database_may_be_corrupt
|
||||
|
||||
do_test 21.1 {
|
||||
# Create a corrupt database in testerr.db. And a non-corrupt at test.db.
|
||||
#
|
||||
@@ -1600,11 +1602,16 @@ Multiple uses for byte 672 of page 15}
|
||||
set auxerr {*** in database aux ***
|
||||
Multiple uses for byte 672 of page 15}
|
||||
|
||||
set mainerr {/{\*\*\* in database main \*\*\*
|
||||
Multiple uses for byte 672 of page 15}.*/}
|
||||
set auxerr {/{\*\*\* in database aux \*\*\*
|
||||
Multiple uses for byte 672 of page 15}.*/}
|
||||
|
||||
do_test 22.2 {
|
||||
catch { db close }
|
||||
sqlite3 db testerr.db
|
||||
execsql { PRAGMA integrity_check }
|
||||
} [list $mainerr]
|
||||
} $mainerr
|
||||
|
||||
do_test 22.3.1 {
|
||||
catch { db close }
|
||||
@@ -1613,13 +1620,13 @@ do_test 22.3.1 {
|
||||
ATTACH 'testerr.db' AS 'aux';
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} [list $auxerr]
|
||||
} $auxerr
|
||||
do_test 22.3.2 {
|
||||
execsql { PRAGMA main.integrity_check; }
|
||||
} {ok}
|
||||
do_test 22.3.3 {
|
||||
execsql { PRAGMA aux.integrity_check; }
|
||||
} [list $auxerr]
|
||||
} $auxerr
|
||||
|
||||
do_test 22.4.1 {
|
||||
catch { db close }
|
||||
@@ -1628,10 +1635,10 @@ do_test 22.4.1 {
|
||||
ATTACH 'test.db' AS 'aux';
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} [list $mainerr]
|
||||
} $mainerr
|
||||
do_test 22.4.2 {
|
||||
execsql { PRAGMA main.integrity_check; }
|
||||
} [list $mainerr]
|
||||
} $mainerr
|
||||
do_test 22.4.3 {
|
||||
execsql { PRAGMA aux.integrity_check; }
|
||||
} {ok}
|
||||
@@ -1680,4 +1687,5 @@ do_test 23.5 {
|
||||
}
|
||||
} {0 0 t1 y {} {NO ACTION} {NO ACTION} NONE}
|
||||
|
||||
database_never_corrupt
|
||||
finish_test
|
||||
|
||||
@@ -824,4 +824,40 @@ do_test select4-13.1 {
|
||||
}
|
||||
} {1 2}
|
||||
|
||||
# 2014-02-18: Make sure compound SELECTs work with VALUES clauses
|
||||
#
|
||||
do_execsql_test select4-14.1 {
|
||||
CREATE TABLE t14(a,b,c);
|
||||
INSERT INTO t14 VALUES(1,2,3),(4,5,6);
|
||||
SELECT * FROM t14 INTERSECT VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3);
|
||||
} {1 2 3}
|
||||
do_execsql_test select4-14.2 {
|
||||
SELECT * FROM t14 INTERSECT VALUES(1,2,3);
|
||||
} {1 2 3}
|
||||
do_execsql_test select4-14.3 {
|
||||
SELECT * FROM t14
|
||||
UNION VALUES(3,2,1),(2,3,1),(1,2,3),(7,8,9),(4,5,6)
|
||||
UNION SELECT * FROM t14 ORDER BY 1, 2, 3
|
||||
} {1 2 3 2 3 1 3 2 1 4 5 6 7 8 9}
|
||||
do_execsql_test select4-14.4 {
|
||||
SELECT * FROM t14
|
||||
UNION VALUES(3,2,1)
|
||||
UNION SELECT * FROM t14 ORDER BY 1, 2, 3
|
||||
} {1 2 3 3 2 1 4 5 6}
|
||||
do_execsql_test select4-14.5 {
|
||||
SELECT * FROM t14 EXCEPT VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3);
|
||||
} {4 5 6}
|
||||
do_execsql_test select4-14.6 {
|
||||
SELECT * FROM t14 EXCEPT VALUES(1,2,3)
|
||||
} {4 5 6}
|
||||
do_execsql_test select4-14.7 {
|
||||
SELECT * FROM t14 EXCEPT VALUES(1,2,3) EXCEPT VALUES(4,5,6)
|
||||
} {}
|
||||
do_execsql_test select4-14.8 {
|
||||
SELECT * FROM t14 EXCEPT VALUES('a','b','c') EXCEPT VALUES(4,5,6)
|
||||
} {1 2 3}
|
||||
do_execsql_test select4-14.9 {
|
||||
SELECT * FROM t14 UNION ALL VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3);
|
||||
} {1 2 3 4 5 6 3 2 1 2 3 1 1 2 3 2 1 3}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# 2014-03-03
|
||||
#
|
||||
# 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 verifies that an OP_Copy operation is used instead of OP_SCopy
|
||||
# in a compound select in a case where the source register might be changed
|
||||
# before the copy is used.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix selectF
|
||||
|
||||
do_execsql_test 1 {
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE t1(a, b, c);
|
||||
INSERT INTO "t1" VALUES(1,'one','I');
|
||||
CREATE TABLE t2(d, e, f);
|
||||
INSERT INTO "t2" VALUES(5,'ten','XX');
|
||||
INSERT INTO "t2" VALUES(6,NULL,NULL);
|
||||
|
||||
CREATE INDEX i1 ON t1(b, a);
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
#explain_i {
|
||||
# SELECT * FROM t2
|
||||
# UNION ALL
|
||||
# SELECT * FROM t1 WHERE a<5
|
||||
# ORDER BY 2, 1
|
||||
#}
|
||||
|
||||
do_execsql_test 2 {
|
||||
SELECT * FROM t2
|
||||
UNION ALL
|
||||
SELECT * FROM t1 WHERE a<5
|
||||
ORDER BY 2, 1
|
||||
} {6 {} {} 1 one I 5 ten XX}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -285,6 +285,25 @@ do_test shell5-1.10 {
|
||||
db eval {SELECT hex(c) FROM t1 ORDER BY rowid}
|
||||
} {636F6C756D6E33 783320220D0A64617461222033 783320220A64617461222033}
|
||||
|
||||
# Blank last column with \r\n line endings.
|
||||
do_test shell5-1.11 {
|
||||
set out [open shell5.csv w]
|
||||
fconfigure $out -translation binary
|
||||
puts $out "column1,column2,column3\r"
|
||||
puts $out "a,b, \r"
|
||||
puts $out "x,y,\r"
|
||||
puts $out "p,q,r\r"
|
||||
close $out
|
||||
catch {db close}
|
||||
forcedelete test.db
|
||||
catchcmd test.db {.mode csv
|
||||
.import shell5.csv t1
|
||||
}
|
||||
sqlite3 db test.db
|
||||
db eval {SELECT *, '|' FROM t1}
|
||||
} {a b { } | x y {} | p q r |}
|
||||
|
||||
|
||||
db close
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -209,4 +209,42 @@ do_execsql_test skipscan1-4.1 {
|
||||
SELECT i FROM t4 WHERE h=8;
|
||||
} {9 9 9 9 9 9 9 9}
|
||||
|
||||
# Make sure skip-scan cost computation in the query planner takes into
|
||||
# account the fact that the seek must occur multiple times.
|
||||
#
|
||||
# Prior to 2014-03-10, the costs were computed incorrectly which would
|
||||
# cause index t5i2 to be used instead of t5i1 on the skipscan1-5.3.
|
||||
#
|
||||
do_execsql_test skipscan1-5.1 {
|
||||
CREATE TABLE t5(
|
||||
id INTEGER PRIMARY KEY,
|
||||
loc TEXT,
|
||||
lang INTEGER,
|
||||
utype INTEGER,
|
||||
xa INTEGER,
|
||||
xd INTEGER,
|
||||
xh INTEGER
|
||||
);
|
||||
CREATE INDEX t5i1 on t5(loc, xh, xa, utype, lang);
|
||||
CREATE INDEX t5i2 ON t5(xd,loc,utype,lang);
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT xh, loc FROM t5 WHERE loc >= 'M' AND loc < 'N';
|
||||
} {/.*COVERING INDEX t5i1 .*/}
|
||||
do_execsql_test skipscan1-5.2 {
|
||||
ANALYZE;
|
||||
DELETE FROM sqlite_stat1;
|
||||
DROP TABLE IF EXISTS sqlite_stat4;
|
||||
DROP TABLE IF EXISTS sqlite_stat3;
|
||||
INSERT INTO sqlite_stat1 VALUES('t5','t5i1','2702931 3 2 2 2 2');
|
||||
INSERT INTO sqlite_stat1 VALUES('t5','t5i2','2702931 686 2 2 2');
|
||||
ANALYZE sqlite_master;
|
||||
} {}
|
||||
db cache flush
|
||||
do_execsql_test skipscan1-5.3 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT xh, loc FROM t5 WHERE loc >= 'M' AND loc < 'N';
|
||||
} {/.*COVERING INDEX t5i1 .*/}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -61,6 +61,7 @@ foreach s {
|
||||
fcntl read pread write pwrite fchmod fallocate
|
||||
pread64 pwrite64 unlink openDirectory mkdir rmdir
|
||||
statvfs fchown umask mmap munmap mremap
|
||||
getpagesize
|
||||
} {
|
||||
if {[test_syscall exists $s]} {lappend syscall_list $s}
|
||||
}
|
||||
|
||||
+11
-4
@@ -1062,10 +1062,17 @@ proc explain_i {sql {db db}} {
|
||||
# Blue: Opcodes that reposition or seek a cursor.
|
||||
# Green: The ResultRow opcode.
|
||||
#
|
||||
set R "\033\[31;1m" ;# Red fg
|
||||
set G "\033\[32;1m" ;# Green fg
|
||||
set B "\033\[34;1m" ;# Red fg
|
||||
set D "\033\[39;0m" ;# Default fg
|
||||
if { [catch {fconfigure stdout -mode}]==0 } {
|
||||
set R "\033\[31;1m" ;# Red fg
|
||||
set G "\033\[32;1m" ;# Green fg
|
||||
set B "\033\[34;1m" ;# Red fg
|
||||
set D "\033\[39;0m" ;# Default fg
|
||||
} else {
|
||||
set R ""
|
||||
set G ""
|
||||
set B ""
|
||||
set D ""
|
||||
}
|
||||
foreach opcode {
|
||||
Seek SeekGe SeekGt SeekLe SeekLt NotFound Last Rewind
|
||||
NoConflict Next Prev VNext VPrev VFilter
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# 2014-03-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 tests to verify that ticket [4ef7e3cfca] has been
|
||||
# fixed.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix tkt-4ef7e3cfca
|
||||
|
||||
do_catchsql_test 1.1 {
|
||||
CREATE TABLE x(a);
|
||||
CREATE TRIGGER t AFTER INSERT ON x BEGIN
|
||||
SELECT * FROM x WHERE abc.a = 1;
|
||||
END;
|
||||
INSERT INTO x VALUES('assert');
|
||||
} {1 {no such column: abc.a}}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TABLE w(a);
|
||||
CREATE TABLE x(a);
|
||||
CREATE TABLE y(a);
|
||||
CREATE TABLE z(a);
|
||||
|
||||
INSERT INTO x(a) VALUES(5);
|
||||
INSERT INTO y(a) VALUES(10);
|
||||
|
||||
CREATE TRIGGER t AFTER INSERT ON w BEGIN
|
||||
INSERT INTO z
|
||||
SELECT (SELECT x.a + y.a FROM y) FROM x;
|
||||
END;
|
||||
INSERT INTO w VALUES('incorrect');
|
||||
}
|
||||
do_execsql_test 2.2 {
|
||||
SELECT * FROM z;
|
||||
} {15}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 3.1 {
|
||||
CREATE TABLE w(a);
|
||||
CREATE TABLE x(b);
|
||||
CREATE TABLE y(a);
|
||||
CREATE TABLE z(a);
|
||||
|
||||
INSERT INTO x(b) VALUES(5);
|
||||
INSERT INTO y(a) VALUES(10);
|
||||
|
||||
CREATE TRIGGER t AFTER INSERT ON w BEGIN
|
||||
INSERT INTO z
|
||||
SELECT (SELECT x.b + y.a FROM y) FROM x;
|
||||
END;
|
||||
INSERT INTO w VALUES('assert');
|
||||
}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM z;
|
||||
} {15}
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,48 @@
|
||||
# 2014-02-25
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Test cases to show that ticket [8c63ff0eca81a9132d8d67b31cd6ae9712a2cc6f]
|
||||
# "Incorrect query result on a UNION ALL" which was caused by using the same
|
||||
# temporary register in concurrent co-routines, as been fixed.
|
||||
#
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix tkt-8c63ff0ec
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e);
|
||||
INSERT INTO t1 VALUES(1,20,30,40,50),(3,60,70,80,90);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY);
|
||||
INSERT INTO t2 VALUES(2);
|
||||
CREATE TABLE t3(z);
|
||||
INSERT INTO t3 VALUES(2),(2),(2),(2);
|
||||
|
||||
SELECT a, b+c FROM t1
|
||||
UNION ALL
|
||||
SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2
|
||||
ORDER BY a;
|
||||
} {1 50 2 5 2 5 2 5 2 5 3 130}
|
||||
do_execsql_test 1.2 {
|
||||
SELECT a, b+c+d FROM t1
|
||||
UNION ALL
|
||||
SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2
|
||||
ORDER BY a;
|
||||
} {1 90 2 5 2 5 2 5 2 5 3 210}
|
||||
do_execsql_test 1.3 {
|
||||
SELECT a, b+c+d+e FROM t1
|
||||
UNION ALL
|
||||
SELECT x, 5 FROM t2 JOIN t3 ON z=x WHERE x=2
|
||||
ORDER BY a;
|
||||
} {1 140 2 5 2 5 2 5 2 5 3 300}
|
||||
|
||||
finish_test
|
||||
@@ -238,12 +238,14 @@ ifcapable wal {
|
||||
tvfs1 script tvfs1_callback
|
||||
proc tvfs1_callback {method filename args} {
|
||||
set ::T1([file tail $filename]) 1
|
||||
return SQLITE_OK
|
||||
}
|
||||
testvfs tvfs2
|
||||
tvfs2 filter {xOpen xDelete xAccess xFullPathname}
|
||||
tvfs2 script tvfs2_callback
|
||||
proc tvfs2_callback {method filename args} {
|
||||
set ::T2([file tail $filename]) 1
|
||||
return SQLITE_OK
|
||||
}
|
||||
|
||||
catch {db close}
|
||||
|
||||
@@ -611,4 +611,17 @@ ifcapable progress {
|
||||
} {1 interrupted}
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test view-22.1 {
|
||||
CREATE VIEW x1 AS SELECT 123 AS '', 234 AS '', 345 AS '';
|
||||
SELECT * FROM x1;
|
||||
} {123 234 345}
|
||||
do_test view-22.2 {
|
||||
unset -nocomplain x
|
||||
db eval {SELECT * FROM x1} x break
|
||||
lsort [array names x]
|
||||
} {{} * :1 :2}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix vtab_shared
|
||||
|
||||
ifcapable !vtab||!shared_cache {
|
||||
finish_test
|
||||
@@ -228,5 +229,51 @@ do_test vtab_shared_1.15.3 {
|
||||
|
||||
db close
|
||||
db2 close
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Test calling sqlite3_close() with vtabs on the disconnect list.
|
||||
#
|
||||
ifcapable rtree {
|
||||
reset_db
|
||||
do_test 2.1.1 {
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
|
||||
# Create a virtual table using [db].
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
|
||||
INSERT INTO rt VALUES(1, 2 ,3);
|
||||
SELECT * FROM rt;
|
||||
}
|
||||
|
||||
# Drop the virtual table using [db2]. The sqlite3_vtab object belonging
|
||||
# to [db] is moved to the sqlite3.pDisconnect list.
|
||||
execsql { DROP TABLE rt } db2
|
||||
|
||||
# Immediately close [db]. At one point this would fail due to the
|
||||
# unfinalized statements held by the un-xDisconnect()ed sqlite3_vtab.
|
||||
db close
|
||||
} {}
|
||||
db2 close
|
||||
}
|
||||
|
||||
ifcapable fts3 {
|
||||
# Same test as above, except using fts3 instead of rtree.
|
||||
reset_db
|
||||
do_test 2.2.1 {
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE ft USING fts3;
|
||||
INSERT INTO ft VALUES('hello world');
|
||||
SELECT * FROM ft;
|
||||
}
|
||||
execsql { DROP TABLE ft } db2
|
||||
db close
|
||||
} {}
|
||||
db2 close
|
||||
}
|
||||
|
||||
sqlite3_enable_shared_cache 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# 2010 April 13
|
||||
#
|
||||
# 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 file is testing the operation of the library in
|
||||
# "PRAGMA journal_mode=WAL" mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix wal64k
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
db close
|
||||
test_syscall pagesize 65536
|
||||
sqlite3 db test.db
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE t1(x);
|
||||
CREATE INDEX i1 ON t1(x);
|
||||
} {wal}
|
||||
do_test 1.1 { file size test.db-shm } {65536}
|
||||
|
||||
do_test 1.2 {
|
||||
execsql BEGIN
|
||||
while {[file size test.db-shm]==65536} {
|
||||
execsql { INSERT INTO t1 VALUES( randstr(900,1100) ) }
|
||||
}
|
||||
execsql COMMIT
|
||||
file size test.db-shm
|
||||
} {131072}
|
||||
|
||||
integrity_check 1.3
|
||||
|
||||
db close
|
||||
test_syscall pagesize -1
|
||||
finish_test
|
||||
|
||||
+8
-6
@@ -32,9 +32,6 @@ ifcapable !wal {
|
||||
}
|
||||
|
||||
do_multiclient_test tn {
|
||||
# Do not run tests with the connections in the same process.
|
||||
#
|
||||
if {$tn==2} continue
|
||||
|
||||
# Close all connections and delete the database.
|
||||
#
|
||||
@@ -43,6 +40,10 @@ do_multiclient_test tn {
|
||||
code3 { db3 close }
|
||||
forcedelete test.db
|
||||
forcedelete walro
|
||||
|
||||
# Do not run tests with the connections in the same process.
|
||||
#
|
||||
if {$tn==2} continue
|
||||
|
||||
foreach c {code1 code2 code3} {
|
||||
$c {
|
||||
@@ -232,9 +233,6 @@ forcedelete test.db
|
||||
# database file while a checkpoint operation is ongoing.
|
||||
#
|
||||
do_multiclient_test tn {
|
||||
# Do not run tests with the connections in the same process.
|
||||
#
|
||||
if {$tn==2} continue
|
||||
|
||||
# Close all connections and delete the database.
|
||||
#
|
||||
@@ -243,6 +241,10 @@ do_multiclient_test tn {
|
||||
code3 { db3 close }
|
||||
forcedelete test.db
|
||||
forcedelete walro
|
||||
|
||||
# Do not run tests with the connections in the same process.
|
||||
#
|
||||
if {$tn==2} continue
|
||||
|
||||
foreach c {code1 code2 code3} {
|
||||
$c {
|
||||
|
||||
@@ -121,6 +121,42 @@ do_test where2-2.3 {
|
||||
}
|
||||
} {85 6 7396 7402 nosort t1 *}
|
||||
|
||||
# Ticket [65bdeb9739605cc22966f49208452996ff29a640] 2014-02-26
|
||||
# Make sure "ORDER BY random" does not gets optimized out.
|
||||
#
|
||||
do_test where2-2.4 {
|
||||
db eval {
|
||||
CREATE TABLE x1(a INTEGER PRIMARY KEY, b DEFAULT 1);
|
||||
WITH RECURSIVE
|
||||
cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<50)
|
||||
INSERT INTO x1 SELECT x, 1 FROM cnt;
|
||||
CREATE TABLE x2(x INTEGER PRIMARY KEY);
|
||||
INSERT INTO x2 VALUES(1);
|
||||
}
|
||||
set sql {SELECT * FROM x1, x2 WHERE x=1 ORDER BY random()}
|
||||
set out1 [db eval $sql]
|
||||
set out2 [db eval $sql]
|
||||
set out3 [db eval $sql]
|
||||
expr {$out1!=$out2 && $out2!=$out3}
|
||||
} {1}
|
||||
do_execsql_test where2-2.5 {
|
||||
-- random() is not optimized out
|
||||
EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random();
|
||||
} {/ random/}
|
||||
do_execsql_test where2-2.5b {
|
||||
-- random() is not optimized out
|
||||
EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random();
|
||||
} {/ SorterOpen /}
|
||||
do_execsql_test where2-2.6 {
|
||||
-- other constant functions are optimized out
|
||||
EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5);
|
||||
} {~/ abs/}
|
||||
do_execsql_test where2-2.6b {
|
||||
-- other constant functions are optimized out
|
||||
EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5);
|
||||
} {~/ SorterOpen /}
|
||||
|
||||
|
||||
|
||||
# Efficient handling of forward and reverse table scans.
|
||||
#
|
||||
|
||||
@@ -121,7 +121,6 @@ foreach hdr {
|
||||
set available_hdr($hdr) 1
|
||||
}
|
||||
set available_hdr(sqliteInt.h) 0
|
||||
set available_hdr(sqlite3.h) 0
|
||||
|
||||
# 78 stars used for comment formatting.
|
||||
set s78 \
|
||||
@@ -229,7 +228,6 @@ proc copy_file {filename} {
|
||||
# inlining opportunities.
|
||||
#
|
||||
foreach file {
|
||||
sqlite3.h
|
||||
sqliteInt.h
|
||||
|
||||
global.c
|
||||
|
||||
Reference in New Issue
Block a user