Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cafc3647a9 |
@@ -394,7 +394,6 @@ TESTSRC = \
|
||||
TESTSRC += \
|
||||
$(TOP)/ext/misc/amatch.c \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
$(TOP)/ext/misc/eval.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/fuzzer.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
|
||||
@@ -863,7 +863,6 @@ TESTSRC = \
|
||||
TESTEXT = \
|
||||
$(TOP)\ext\misc\amatch.c \
|
||||
$(TOP)\ext\misc\closure.c \
|
||||
$(TOP)\ext\misc\eval.c \
|
||||
$(TOP)\ext\misc\fileio.c \
|
||||
$(TOP)\ext\misc\fuzzer.c \
|
||||
$(TOP)\ext\misc\ieee754.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.8.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.7.
|
||||
#
|
||||
# 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.8'
|
||||
PACKAGE_STRING='sqlite 3.8.8'
|
||||
PACKAGE_VERSION='3.8.7'
|
||||
PACKAGE_STRING='sqlite 3.8.7'
|
||||
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.8 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.8.7 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.8:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.7:";;
|
||||
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.8
|
||||
sqlite configure 3.8.7
|
||||
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.8, which was
|
||||
It was created by sqlite $as_me 3.8.7, 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.8, which was
|
||||
This file was extended by sqlite $as_me 3.8.7, 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.8
|
||||
sqlite config.status 3.8.7
|
||||
configured by $0, generated by GNU Autoconf 2.62,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
** 2014-11-10
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This SQLite extension implements SQL function eval() which runs
|
||||
** SQL statements recursively.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** Structure used to accumulate the output
|
||||
*/
|
||||
struct EvalResult {
|
||||
char *z; /* Accumulated output */
|
||||
const char *zSep; /* Separator */
|
||||
int szSep; /* Size of the separator string */
|
||||
int nAlloc; /* Number of bytes allocated for z[] */
|
||||
int nUsed; /* Number of bytes of z[] actually used */
|
||||
};
|
||||
|
||||
/*
|
||||
** Callback from sqlite_exec() for the eval() function.
|
||||
*/
|
||||
static int callback(void *pCtx, int argc, char **argv, char **colnames){
|
||||
struct EvalResult *p = (struct EvalResult*)pCtx;
|
||||
int i;
|
||||
for(i=0; i<argc; i++){
|
||||
const char *z = argv[i] ? argv[i] : "";
|
||||
size_t sz = strlen(z);
|
||||
if( sz+p->nUsed+p->szSep+1 > p->nAlloc ){
|
||||
char *zNew;
|
||||
p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
|
||||
zNew = sqlite3_realloc(p->z, p->nAlloc);
|
||||
if( zNew==0 ){
|
||||
sqlite3_free(p->z);
|
||||
memset(p, 0, sizeof(*p));
|
||||
return 1;
|
||||
}
|
||||
p->z = zNew;
|
||||
}
|
||||
if( p->nUsed>0 ){
|
||||
memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
|
||||
p->nUsed += p->szSep;
|
||||
}
|
||||
memcpy(&p->z[p->nUsed], z, sz);
|
||||
p->nUsed += sz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the eval(X) and eval(X,Y) SQL functions.
|
||||
**
|
||||
** Evaluate the SQL text in X. Return the results, using string
|
||||
** Y as the separator. If Y is omitted, use a single space character.
|
||||
*/
|
||||
static void sqlEvalFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zSql;
|
||||
sqlite3 *db;
|
||||
char *zErr = 0;
|
||||
int rc;
|
||||
struct EvalResult x;
|
||||
|
||||
memset(&x, 0, sizeof(x));
|
||||
x.zSep = " ";
|
||||
zSql = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zSql==0 ) return;
|
||||
if( argc>1 ){
|
||||
x.zSep = (const char*)sqlite3_value_text(argv[1]);
|
||||
if( x.zSep==0 ) return;
|
||||
}
|
||||
x.szSep = (int)strlen(x.zSep);
|
||||
db = sqlite3_context_db_handle(context);
|
||||
rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}else if( x.zSep==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
sqlite3_free(x.z);
|
||||
}else{
|
||||
sqlite3_result_text(context, x.z, x.nUsed, sqlite3_free);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_eval_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
rc = sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0,
|
||||
sqlEvalFunc, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0,
|
||||
sqlEvalFunc, 0, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ do_eqp_test rtree6.2.4.2 {
|
||||
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1}
|
||||
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)}
|
||||
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)}
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.5 {
|
||||
|
||||
@@ -246,7 +246,6 @@ TESTSRC = \
|
||||
$(TOP)/src/test_autoext.c \
|
||||
$(TOP)/src/test_async.c \
|
||||
$(TOP)/src/test_backup.c \
|
||||
$(TOP)/src/test_blob.c \
|
||||
$(TOP)/src/test_btree.c \
|
||||
$(TOP)/src/test_config.c \
|
||||
$(TOP)/src/test_demovfs.c \
|
||||
@@ -281,7 +280,6 @@ TESTSRC = \
|
||||
TESTSRC += \
|
||||
$(TOP)/ext/misc/amatch.c \
|
||||
$(TOP)/ext/misc/closure.c \
|
||||
$(TOP)/ext/misc/eval.c \
|
||||
$(TOP)/ext/misc/fileio.c \
|
||||
$(TOP)/ext/misc/fuzzer.c \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
C Adding\sthe\s"noskipscan"\stoken\sto\san\ssqlite_stat1.stat\sfield\sprevents\san\nindex\sfor\sbeing\sused\swith\sthe\sskip-scan\salgorithm.
|
||||
D 2014-11-15T19:08:13.305
|
||||
C The\s_beginthreadex()\s/\s_endthreadex()\sfunctions\sshould\sonly\sbe\sused\swhen\scompiling\swith\sMSVC.
|
||||
D 2014-10-22T16:25:09.852
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb
|
||||
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 788f1288633a0c3c3cbbe0f3e4827d033f7ba530
|
||||
F Makefile.msc e31dee24038965fb6269d6d61073fd6b7e331dec
|
||||
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
|
||||
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
|
||||
F VERSION d846487aff892625eb8e75960234e7285f0462fe
|
||||
F VERSION 53a0b870e7f16d3b06623c31d233a304c163a6af
|
||||
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 4343c810cc772571210af75d1a8f7c2eb711d75a x
|
||||
F configure ad59a5f48b3c59a92b5506040a22fbe3f733a9d8 x
|
||||
F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
@@ -109,7 +109,6 @@ F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/misc/amatch.c 678056a4bfcd83c4e82dea81d37543cd1d6dbee1
|
||||
F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012
|
||||
F ext/misc/compress.c 76e45655f4046e756064ab10c62e18f2eb846b9f
|
||||
F ext/misc/eval.c 04e630bde869aa1fec6b993d40591f963be2f868
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 136533c53cfce0957f0b48fa11dba27e21c5c01d
|
||||
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
|
||||
@@ -131,7 +130,7 @@ F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc
|
||||
F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0
|
||||
F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
|
||||
F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
|
||||
F ext/rtree/rtree6.test 0cfbdf27ee086bf16a3da2c6f2d5b3d6473cb27e
|
||||
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
|
||||
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
|
||||
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34
|
||||
@@ -152,7 +151,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 084976077a4aa3bd985154b5423e7aed88e4a2e9
|
||||
F main.mk bbc8b6000ed143a1a8d31d3b4995c359a3188fa1
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
@@ -164,29 +163,29 @@ F mptest/mptest.c 499a74af4be293b7c1c7c3d40f332b67227dd739
|
||||
F mptest/multiwrite01.test 499ad0310da8dff8e8f98d2e272fc2a8aa741b2e
|
||||
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
|
||||
F src/analyze.c 951fd859852dfbced4a58b73954f168eeb9d0772
|
||||
F src/analyze.c 567c94b763b67f7abda06dbf0ba34b0343ed9447
|
||||
F src/attach.c f4e94df2d1826feda65eb0939f7f6f5f923a0ad9
|
||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea
|
||||
F src/auth.c d8abcde53426275dab6243b441256fcd8ccbebb2
|
||||
F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
|
||||
F src/btree.c d5d991b518fa5bebc64037dfeb98a48051d864d7
|
||||
F src/btree.h e31a3a3ebdedb1caf9bda3ad5dbab3db9b780f6e
|
||||
F src/btree.c 1b1123cba0c65caa0baa51e71b8c089e3167c3ed
|
||||
F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8
|
||||
F src/btreeInt.h 026d0129724e8f265fdc60d44ec240cf5a4e6179
|
||||
F src/build.c 67bb05b1077e0cdaccb2e36bfcbe7a5df9ed31e8
|
||||
F src/build.c 9dc2bd94347b878c89627000c92b0c8d97ec2919
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c c4ba6e0626bb94bc77a0861735f3382fcf7cc818
|
||||
F src/ctime.c df19848891c8a553c80e6f5a035e768280952d1a
|
||||
F src/date.c 93594514aae68de117ca4a2a0d6cc63eddf26744
|
||||
F src/delete.c 0750b1eb4d96cd3fb2c798599a3a7c85e92f1417
|
||||
F src/expr.c a3ff05db5709d628c23890db862e30f3dd9dc428
|
||||
F src/complete.c 535183afb3c75628b78ce82612931ac7cdf26f14
|
||||
F src/ctime.c cc296efb42c55f03e439bf4b99d5eb37d4429db9
|
||||
F src/date.c 57a7f9ba9f6b4d5268f5e411739066a611f99036
|
||||
F src/delete.c fae81cc2eb14b75267d4f47d3cfc9ae02aae726f
|
||||
F src/expr.c fc204d08af06437ddaffe5a1b1f1f6f9e1a55d6d
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c da985ae673efef2c712caef825a5d2edb087ead7
|
||||
F src/func.c ba47c1671ab3cfdafa6e9d6ee490939ea578adee
|
||||
F src/global.c 6ded36dda9466fc1c9a3c5492ded81d79bf3977d
|
||||
F src/global.c 01c1f36ecfcf10770db648422a8852c222308bb9
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
@@ -195,50 +194,50 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||
F src/loadext.c de741e66e5ddc1598d904d7289239696e40ed994
|
||||
F src/main.c d3310d5ed56e246bf1589e47eeaca8be582bd4b8
|
||||
F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
|
||||
F src/main.c bbe872b0ac0007bed0ebe1936fc493b039ad4f51
|
||||
F src/malloc.c 3c3ac67969612493d435e14b6832793209afd2ec
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c faf615aafd8be74a71494dfa027c113ea5c6615f
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
|
||||
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
|
||||
F src/mutex.c 19bf9acba69ca2f367c3761080f8a9f0cf4670a8
|
||||
F src/mutex.c 84a073c9a23a8d7bdd2ea832522d1730df18812c
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c f3f09fd7a2eb4287cfc799753ffc30380e7b71a1
|
||||
F src/mutex_unix.c 551e2f25f0fa0ee8fd7a43f50fc3d8be00e95dde
|
||||
F src/mutex_unix.c 1b10d5413dfc794364a8adf3eb3a192926b43fa3
|
||||
F src/mutex_w32.c 06bfff9a3a83b53389a51a967643db3967032e1e
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
|
||||
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
|
||||
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c fb587121840f690101336879adfa6d0b2cd0e8c7
|
||||
F src/os_win.c a9e500dd963fb1f67d7860e58b5772abe6123862
|
||||
F src/os_win.c a019caaae2bcbbc0cc4c39af6e7d7e43d8426053
|
||||
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
|
||||
F src/pager.c 8d97b3633f098fef817656dcbf167ca904511d78
|
||||
F src/pager.h d1eee3c3f741be247ce6d82752a178515fc8578b
|
||||
F src/pager.c a98547ad9b1b5dbbc5e7d1c520be041b5d2c0926
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
F src/parse.y 5dfead8aed90cb0c7c1115898ee2266804daff45
|
||||
F src/pcache.c ace1b67632deeaa84859b4c16c27711dfb7db3d4
|
||||
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
|
||||
F src/pcache1.c facbdd3ecc09c8f750089d941305694301328e98
|
||||
F src/pcache.c 4121a0571c18581ee9f82f086d5e2030051ebd6a
|
||||
F src/pcache.h 9b559127b83f84ff76d735c8262f04853be0c59a
|
||||
F src/pcache1.c e412cb585f777c840ddce0500eddc5c6043c2bb5
|
||||
F src/pragma.c 3f3e959390a10c0131676f0e307acce372777e0f
|
||||
F src/prepare.c b7b7bf020bd4c962f7c8aed5a3c542c7dfe9f9c7
|
||||
F src/printf.c 9e75a6a0b55bf61cfff7d7e19d89834a1b938236
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952
|
||||
F src/prepare.c 6ef0cf2f9274982988ed6b7cab1be23147e94196
|
||||
F src/printf.c 6b79bbd063dcbadca4cf617a4cde255bcc13ea64
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c a3466128b52a86c466e47ac1a19e2174f7b5cf89
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 428165951748151e87a15295b7357221433e311b
|
||||
F src/shell.c bc28d5992109717c87804e2eb1a08a7c8cc7a2fd
|
||||
F src/sqlite.h.in 0c5c0df7e4e436dfc5592511325bf4a96f6a638d
|
||||
F src/shell.c 282f8f5278e0c78eb442217531172ec9e1538796
|
||||
F src/sqlite.h.in 4a5e5158c189d2bcd45c7c4607c2c0eb6d25c153
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
F src/sqliteInt.h c9e95b8fa9aee30d46387735c5be73fa58886e38
|
||||
F src/sqliteInt.h d6d423b0f62846eb441236bc15417aeede2ebbdc
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 81712116e826b0089bb221b018929536b2b5406f
|
||||
F src/table.c f142bba7903e93ca8d113a5b8877a108ad1a27dc
|
||||
F src/tclsqlite.c 0a874655dd39a9875e39c5d3c464db662171d228
|
||||
F src/test1.c 6b0469b8e06c77b1de1d3e4a3834cf26edea9cc7
|
||||
F src/status.c 961d5926e5a8fda611d385ec22c226b8635cd1cb
|
||||
F src/table.c 2e99ef7ef16187e17033d9398dc962ce22dab5cb
|
||||
F src/tclsqlite.c c67d310c833046cccc192125d64ad422ab882684
|
||||
F src/test1.c 518db4305d76b29dd9da3f022ca899c8fcdf9fc7
|
||||
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
|
||||
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
|
||||
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
|
||||
@@ -250,9 +249,8 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
|
||||
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
|
||||
F src/test_blob.c 1f2e3e25255b731c4fcf15ee7990d06347cb6c09
|
||||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c 035c17a173937d019b8dfc1d524f9d3fc8123504
|
||||
F src/test_config.c a4cdebe093474c02eecc5e4008b1a22198edf975
|
||||
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
@@ -284,28 +282,28 @@ F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
|
||||
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 6de09362b657f19ba83e5fa521ee715787ce9fee
|
||||
F src/threads.c 2fa8433e5f766d272d25f722b2a18b1c3e123b7e
|
||||
F src/tokenize.c cc9016e5007fc5e76789079616d2f26741bcc689
|
||||
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
|
||||
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
|
||||
F src/update.c 729f6f18fc27740591d085e1172cebe311144bf0
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c 3b627daa45c7308c1e36e3dbaa3f9ce7e5c7fa73
|
||||
F src/vacuum.c 9b30ec729337dd012ed88d4c292922c8ef9cf00c
|
||||
F src/vdbe.c 5e47308836e9bb5fdb4835fdf88eeab071848d3f
|
||||
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
|
||||
F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78
|
||||
F src/vdbeapi.c 07acb615d1e4170e71fc1b0d087f3c53a1ad8e83
|
||||
F src/vdbeaux.c 9b0a251b6dfab349dd6c6efb40062eb7386b26f5
|
||||
F src/vdbeblob.c 4af4bfb71f6df7778397b4a0ebc1879793276778
|
||||
F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8
|
||||
F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a
|
||||
F src/vdbe.c 5ee15a66ce07e0482b92aa29e4dd0c5827a22d79
|
||||
F src/vdbe.h 09f5b4e3719fa454f252322b1cdab5cf1f361327
|
||||
F src/vdbeInt.h e2a060a55ee18a6ab973353a5e2ec7ee569bf787
|
||||
F src/vdbeapi.c 37a6c6ae284a97bcace365f2f0a225680c0499d9
|
||||
F src/vdbeaux.c edbb7a9c8b2a8f7a68ac75c2475edd4040266b76
|
||||
F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4
|
||||
F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f
|
||||
F src/vdbesort.c 87f3923483113d1c95d84640becb4e4946f27d9a
|
||||
F src/vdbesort.c 975aeffa99acb0991b2f288d30294756bff41438
|
||||
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
|
||||
F src/vtab.c 2a30791bbd7926b589401bd09c3abb33de563793
|
||||
F src/wal.c fa090966140602f03a621f87d82ee69e66ca63b5
|
||||
F src/vtab.c cb0c194303fea276b48d7d4b6d970b5a96bde8de
|
||||
F src/wal.c 10e7de7ce90865a68153f001a61f1d985cd17983
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c cb89128d24ddb5fe3ca290166d66968f2dc0c3c8
|
||||
F src/whereInt.h d3633e9b592103241b74b0ec76185f3e5b8b62e0
|
||||
F src/where.c 5099c42e24c63969b3cf3b52e18c1a36cb841a34
|
||||
F src/whereInt.h 4b459cdbfc9b01f5f27673a35f9967e4dea917e8
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
|
||||
@@ -323,7 +321,7 @@ F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82
|
||||
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
|
||||
F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a
|
||||
F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a
|
||||
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
||||
@@ -348,15 +346,13 @@ F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
|
||||
F test/autoindex1.test 6ff78b94f43a59616c06c11c55b12935173506d7
|
||||
F test/autoindex2.test 60d2fc6f38364308ce73a9beb01b47ded38697de
|
||||
F test/autoindex3.test 8254f689c3241081fad52b7bea18ba53e07e14a2
|
||||
F test/autoindex4.test fc807f9efd158bec60f5dfdf34ebe46fb274612d
|
||||
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
F test/backcompat.test 19a1f337c68419b020a7481dd272a472c4ad8ef4
|
||||
F test/backup.test b79299a536a4c6d919094786595b95be56d02014
|
||||
F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
|
||||
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
|
||||
F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4
|
||||
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
|
||||
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
|
||||
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
|
||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
@@ -382,10 +378,10 @@ F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
|
||||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
|
||||
F test/capi3.test f0718f4f90d0efdc980119bfbdf1d7f1541ee5ef
|
||||
F test/capi3.test 71bcf2fbd36a9732f617766dfd752552c8e491b5
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test fdc0d67a2cb8e8fc400d5b7735e330161ea057a2
|
||||
F test/capi3d.test a82b6321c50a1cfc848e386fa2c851893606f68c
|
||||
F test/capi3c.test a21869e4d50d5dbb7e566e328fc0bc7c2efa6a32
|
||||
F test/capi3d.test c84af0c49267f9c3fbf4c1c46aa647646023811e
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
|
||||
@@ -424,7 +420,7 @@ F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
|
||||
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
|
||||
F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
|
||||
F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb
|
||||
F test/corruptI.test 221ad8b7f0a9ac6b80fc577e73b5ad8cdea31243
|
||||
F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318
|
||||
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
|
||||
@@ -454,11 +450,6 @@ F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
||||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77
|
||||
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
||||
F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f
|
||||
F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716
|
||||
F test/e_blobopen.test 234f960d90235a9b51ec3ca1e062e8541dd558d8
|
||||
F test/e_blobwrite.test 615b405f29feb2cfb5a1f03dab7933258294fa26
|
||||
F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
|
||||
F test/e_createtable.test c7e67b49e6cf92473c8fb30ab26143e9e2128cf7
|
||||
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
|
||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||
@@ -471,11 +462,9 @@ F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
|
||||
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
||||
F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
|
||||
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
|
||||
F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
|
||||
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
|
||||
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
|
||||
F test/e_wal.test 0967f0b8f1dfda871dc7b9b5574198f1f4f7d69a
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
|
||||
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
|
||||
@@ -498,7 +487,7 @@ F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
F test/fkey5.test 8a1fde4e7721ae00b05b3178888833726ca2df8d
|
||||
F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48
|
||||
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
|
||||
F test/fkey7.test e31d0e71a41c1d29349a16448d6c420e2c53a8fc
|
||||
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
|
||||
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
|
||||
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
|
||||
@@ -627,7 +616,7 @@ F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
|
||||
F test/in5.test 1de657472fa9ac2924be25c2c959ac5ca1aae554
|
||||
F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3
|
||||
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
|
||||
F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
@@ -734,9 +723,8 @@ F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
|
||||
F test/misc8.test e838ec20c9c988bc94812fdb89af26409c20931b
|
||||
F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912
|
||||
F test/mmap1.test 1bfd611b9841eafb44f7d83c0788e146d84a33c9
|
||||
F test/mmap1.test 93d167b328255cbe6679fe1e1a23be1b1197d07b
|
||||
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
|
||||
F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e
|
||||
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
|
||||
@@ -780,7 +768,7 @@ F test/permutations.test cef25f5e8499a15846eccd06785f17f4180407ab
|
||||
F test/pragma.test 19d0241a007bcdd77fc2606ec60fc60357e7fc8b
|
||||
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/printf2.test b4acd4bf8734243257f01ddefa17c4fb090acc8a
|
||||
F test/printf2.test bed79b4c3e5da08ba88ad637c0bf62586843cfb1
|
||||
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
@@ -797,21 +785,18 @@ F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
|
||||
F test/releasetest.tcl a4279c890698584feb2ffc86735857a4e4474180
|
||||
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
|
||||
F test/rollbackfault.test 6a004f71087cc399296cffbb5429ea6da655ae65
|
||||
F test/rollback.test e9504a009a202c3ed711da2e6879ff60c5a4669c
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test 742b5741584a8a44fd83e856cc2896688401d645
|
||||
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
|
||||
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
|
||||
F test/savepoint.test c671fdbd34cd3bfe1518a777526ada595180cf8d
|
||||
F test/savepoint.test 51d3900dc071a7c2ad4248578a5925631b476313
|
||||
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
|
||||
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
|
||||
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
|
||||
F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
|
||||
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
|
||||
F test/savepoint7.test 1c8f26b1e2a4221b0214e222ce12a97a59918eb2
|
||||
F test/scanstatus.test a6dd739bc4d9638e8f5c2493b518057f2b681655
|
||||
F test/savepoint7.test fbf319a7b2dda089ec5be30a424a0e95f121d423
|
||||
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
|
||||
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
|
||||
@@ -855,15 +840,15 @@ F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test 2ddfe5d168462170c4487f534e2a99fb006b2076
|
||||
F test/skipscan1.test 7e15e1cc524524e7b2c4595ec85c75501d22f4ff
|
||||
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
|
||||
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
|
||||
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
|
||||
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
|
||||
F test/skipscan6.test 3a891b45d6df266ced861a2ad9d03fca2bc7fcc5
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
F test/sort.test c4400e7533748f6bd7413851ff148645e82b9e2d
|
||||
F test/sort2.test 84a92eebf697feee9c6697746918c7d67373eea1
|
||||
F test/sort2.test 269f4f50c6e468cc32b302ae7ff0add8338ec6de
|
||||
F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2
|
||||
F test/sort4.test 6c37d85f7cd28d50cce222fcab84ccd771e105cb
|
||||
F test/sort5.test a448240a42b49239edc00f85d6d7ac7a1b261e1f
|
||||
@@ -889,7 +874,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/table.test 06271d61eb13871490d38168433c1ef3dd82bb2a
|
||||
F test/table.test 2a1d2fa52c531de5915f28023747d9a8c27b6f31
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
||||
@@ -959,7 +944,7 @@ F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
|
||||
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
|
||||
F test/tkt-f3e5abed55.test d5a0126118142d13e27f6ce9f4c47096e9321c00
|
||||
F test/tkt-f67b41381a.test a23bc124c981662db712167bacd0ed8ad11abac9
|
||||
F test/tkt-f777251dc7a.test d1a8fc3eefb7a9e64d19ff24d5c8c94c34a632fb
|
||||
F test/tkt-f777251dc7a.test af6531446c64bfd268416f07b4df7be7f9c749d2
|
||||
F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
|
||||
F test/tkt-f973c7ac31.test 28ef85c7f015477916795246d8286aeda39d4ead
|
||||
F test/tkt-fa7bf5ec.test 9102dfea58aa371d78969da735f9392c57e2e035
|
||||
@@ -1054,7 +1039,7 @@ F test/trace.test 73a5508100f7fccfbc3f8018d5f6963ed478eea0
|
||||
F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382
|
||||
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
F test/trans3.test 373ac5183cc56be69f48ae44090e7f672939f732
|
||||
F test/transitive1.test 03f532954f46cdf5608f7766bff0b0c52bf2a7cd
|
||||
F test/trigger1.test dc47573ac79ffe0ee3eecaa517d70d8dacbccd03
|
||||
F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
|
||||
@@ -1064,7 +1049,7 @@ F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
|
||||
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
|
||||
F test/trigger7.test b39e6dee1debe0ff9c2ef66326668f149f07c9c4
|
||||
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
||||
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
|
||||
F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
|
||||
F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
|
||||
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
|
||||
F test/triggerC.test a68980c5955d62ee24be6f97129d824f199f9a4c
|
||||
@@ -1078,7 +1063,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
|
||||
F test/unique2.test 41e7f83c6827605991160a31380148a9fc5f1339
|
||||
F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
|
||||
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
|
||||
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
|
||||
F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb
|
||||
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
@@ -1165,7 +1150,7 @@ F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
F test/without_rowid3.test 1081aabf60a1e1123b7f9a8f6ae19954351843b0
|
||||
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
||||
F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862
|
||||
F test/without_rowid5.test b4a639a367f04d382d20e8f44fc1be4f2d57d107
|
||||
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
|
||||
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
|
||||
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
@@ -1200,7 +1185,7 @@ F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/showdb.c bd073a78bce714a0e42d92ea474b3eb8cb53be5d
|
||||
F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5
|
||||
F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
|
||||
F tool/showstat4.c c39279d6bd37cb999b634f0064f6f86ad7af008f
|
||||
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
|
||||
@@ -1215,16 +1200,15 @@ F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
|
||||
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
|
||||
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
|
||||
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 55e453aadbb676dda07f0fa537d39ce184ef636c
|
||||
R 59717354988087765927b6c6b6246253
|
||||
T *branch * noskipscan-token
|
||||
T *sym-noskipscan-token *
|
||||
P 3c933bf95f291f7957580d823dce92c981375a5c
|
||||
R af2834bb71df32c5023a7384a0a52a6c
|
||||
T *branch * msvcThreads
|
||||
T *sym-msvcThreads *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 9d226c4fa6bf82a1f1a22a271191f33c
|
||||
U mistachkin
|
||||
Z fb1887a94bcdc5356b2224d0baf2a2e1
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
00fe09505792cd0d104b2da9d040f023e30fa871
|
||||
1a5a5da3315e6fe768b8527e46c4d24c6d0e71fb
|
||||
@@ -2,7 +2,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH SQLITE3 1 "Fri Oct 31 10:41:31 EDT 2014"
|
||||
.TH SQLITE3 1 "Mon Jan 31 11:14:00 2014"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
@@ -49,7 +49,7 @@ a table named "memos" and insert a couple of records into that table:
|
||||
$
|
||||
.B sqlite3 mydata.db
|
||||
.br
|
||||
SQLite version 3.8.8
|
||||
SQLite version 3.8.3
|
||||
.br
|
||||
Enter ".help" for instructions
|
||||
.br
|
||||
@@ -107,29 +107,26 @@ the '.help' command. For example:
|
||||
sqlite>
|
||||
.B .help
|
||||
.nf
|
||||
.tr %.
|
||||
%backup ?DB? FILE Backup DB (default "main") to FILE
|
||||
%bail on|off Stop after hitting an error. Default OFF
|
||||
%clone NEWDB Clone data into NEWDB from the existing database
|
||||
%databases List names and files of attached databases
|
||||
%dump ?TABLE? ... Dump the database in an SQL text format
|
||||
.cc |
|
||||
.backup ?DB? FILE Backup DB (default "main") to FILE
|
||||
.bail ON|OFF Stop after hitting an error. Default OFF
|
||||
.databases List names and files of attached databases
|
||||
.dump ?TABLE? ... Dump the database in an SQL text format
|
||||
If TABLE specified, only dump tables matching
|
||||
LIKE pattern TABLE.
|
||||
%echo on|off Turn command echo on or off
|
||||
%eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN
|
||||
%exit Exit this program
|
||||
%explain ?on|off? Turn output mode suitable for EXPLAIN on or off.
|
||||
.echo ON|OFF Turn command echo on or off
|
||||
.exit Exit this program
|
||||
.explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.
|
||||
With no args, it turns EXPLAIN on.
|
||||
%fullschema Show schema and the content of sqlite_stat tables
|
||||
%headers on|off Turn display of headers on or off
|
||||
%help Show this message
|
||||
%import FILE TABLE Import data from FILE into TABLE
|
||||
%indices ?TABLE? Show names of all indices
|
||||
.header(s) ON|OFF Turn display of headers on or off
|
||||
.help Show this message
|
||||
.import FILE TABLE Import data from FILE into TABLE
|
||||
.indices ?TABLE? Show names of all indices
|
||||
If TABLE specified, only show indices for tables
|
||||
matching LIKE pattern TABLE.
|
||||
%load FILE ?ENTRY? Load an extension library
|
||||
%log FILE|off Turn logging on or off. FILE can be stderr/stdout
|
||||
%mode MODE ?TABLE? Set output mode where MODE is one of:
|
||||
.load FILE ?ENTRY? Load an extension library
|
||||
.log FILE|off Turn logging on or off. FILE can be stderr/stdout
|
||||
.mode MODE ?TABLE? Set output mode where MODE is one of:
|
||||
csv Comma-separated values
|
||||
column Left-aligned columns. (See .width)
|
||||
html HTML <table> code
|
||||
@@ -138,35 +135,31 @@ sqlite>
|
||||
list Values delimited by .separator string
|
||||
tabs Tab-separated values
|
||||
tcl TCL list elements
|
||||
%nullvalue STRING Use STRING in place of NULL values
|
||||
%once FILENAME Output for the next SQL command only to FILENAME
|
||||
%open ?FILENAME? Close existing database and reopen FILENAME
|
||||
%output ?FILENAME? Send output to FILENAME or stdout
|
||||
%print STRING... Print literal STRING
|
||||
%prompt MAIN CONTINUE Replace the standard prompts
|
||||
%quit Exit this program
|
||||
%read FILENAME Execute SQL in FILENAME
|
||||
%restore ?DB? FILE Restore content of DB (default "main") from FILE
|
||||
%save FILE Write in-memory database into FILE
|
||||
%schema ?TABLE? Show the CREATE statements
|
||||
.nullvalue STRING Use STRING in place of NULL values
|
||||
.open ?FILENAME? Close existing database and reopen FILENAME
|
||||
.output FILENAME Send output to FILENAME
|
||||
.output stdout Send output to the screen
|
||||
.print STRING... Print literal STRING
|
||||
.prompt MAIN CONTINUE Replace the standard prompts
|
||||
.quit Exit this program
|
||||
.read FILENAME Execute SQL in FILENAME
|
||||
.restore ?DB? FILE Restore content of DB (default "main") from FILE
|
||||
.schema ?TABLE? Show the CREATE statements
|
||||
If TABLE specified, only show tables matching
|
||||
LIKE pattern TABLE.
|
||||
%separator STRING ?NL? Change separator used by output mode and .import
|
||||
NL is the end-of-line mark for CSV
|
||||
%shell CMD ARGS... Run CMD ARGS... in a system shell
|
||||
%show Show the current values for various settings
|
||||
%stats on|off Turn stats on or off
|
||||
%system CMD ARGS... Run CMD ARGS... in a system shell
|
||||
%tables ?TABLE? List names of tables
|
||||
.separator STRING Change separator used by output mode and .import
|
||||
.show Show the current values for various settings
|
||||
.stats ON|OFF Turn stats on or off
|
||||
.tables ?TABLE? List names of tables
|
||||
If TABLE specified, only list tables matching
|
||||
LIKE pattern TABLE.
|
||||
%timeout MS Try opening locked tables for MS milliseconds
|
||||
%timer on|off Turn SQL timer on or off
|
||||
%trace FILE|off Output each SQL statement as it is run
|
||||
%vfsname ?AUX? Print the name of the VFS stack
|
||||
%width NUM1 NUM2 ... Set column widths for "column" mode
|
||||
Negative values right-justify
|
||||
.timeout MS Try opening locked tables for MS milliseconds
|
||||
.trace FILE|off Output each SQL statement as it is run
|
||||
.vfsname ?AUX? Print the name of the VFS stack
|
||||
.width NUM1 NUM2 ... Set column widths for "column" mode
|
||||
.timer ON|OFF Turn the CPU timer measurement on or off
|
||||
sqlite>
|
||||
|cc .
|
||||
.sp
|
||||
.fi
|
||||
.SH OPTIONS
|
||||
@@ -276,7 +269,7 @@ o If the -init option is present, the specified file is processed.
|
||||
o All other command line options are processed.
|
||||
|
||||
.SH SEE ALSO
|
||||
http://www.sqlite.org/cli.html
|
||||
http://www.sqlite.org/
|
||||
.br
|
||||
The sqlite3-doc package.
|
||||
.SH AUTHOR
|
||||
|
||||
+1
-3
@@ -1466,8 +1466,6 @@ static void decodeIntArray(
|
||||
pIndex->bUnordered = 1;
|
||||
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
|
||||
pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
|
||||
}else if( sqlite3_strglob("noskipscan*", z)==0 ){
|
||||
pIndex->noSkipScan = 1;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_COSTMULT
|
||||
else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
|
||||
@@ -1863,7 +1861,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
||||
|
||||
/* Load the statistics from the sqlite_stat4 table. */
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){
|
||||
if( rc==SQLITE_OK ){
|
||||
int lookasideEnabled = db->lookaside.bEnabled;
|
||||
db->lookaside.bEnabled = 0;
|
||||
rc = loadStat4(db, sInfo.zDatabase);
|
||||
|
||||
@@ -72,9 +72,6 @@ int sqlite3_set_authorizer(
|
||||
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
|
||||
void *pArg
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->xAuth = (sqlite3_xauth)xAuth;
|
||||
db->pAuthArg = pArg;
|
||||
|
||||
+6
-45
@@ -122,20 +122,6 @@ static int setDestPgsz(sqlite3_backup *p){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check that there is no open read-transaction on the b-tree passed as the
|
||||
** second argument. If there is not, return SQLITE_OK. Otherwise, if there
|
||||
** is an open read-transaction, return SQLITE_ERROR and leave an error
|
||||
** message in database handle db.
|
||||
*/
|
||||
static int checkReadTransaction(sqlite3 *db, Btree *p){
|
||||
if( sqlite3BtreeIsInReadTrans(p) ){
|
||||
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create an sqlite3_backup process to copy the contents of zSrcDb from
|
||||
** connection handle pSrcDb to zDestDb in pDestDb. If successful, return
|
||||
@@ -152,13 +138,6 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
){
|
||||
sqlite3_backup *p; /* Value to return */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Lock the source database handle. The destination database
|
||||
** handle is not locked in this routine, but it is locked in
|
||||
** sqlite3_backup_step(). The user is required to ensure that no
|
||||
@@ -195,15 +174,12 @@ sqlite3_backup *sqlite3_backup_init(
|
||||
p->iNext = 1;
|
||||
p->isAttached = 0;
|
||||
|
||||
if( 0==p->pSrc || 0==p->pDest
|
||||
|| setDestPgsz(p)==SQLITE_NOMEM
|
||||
|| checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
|
||||
){
|
||||
if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM ){
|
||||
/* One (or both) of the named databases did not exist or an OOM
|
||||
** error was hit. Or there is a transaction open on the destination
|
||||
** database. The error has already been written into the pDestDb
|
||||
** handle. All that is left to do here is free the sqlite3_backup
|
||||
** structure. */
|
||||
** error was hit. The error has already been written into the
|
||||
** pDestDb handle. All that is left to do here is free the
|
||||
** sqlite3_backup structure.
|
||||
*/
|
||||
sqlite3_free(p);
|
||||
p = 0;
|
||||
}
|
||||
@@ -358,9 +334,6 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
int pgszSrc = 0; /* Source page size */
|
||||
int pgszDest = 0; /* Destination page size */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(p->pSrcDb->mutex);
|
||||
sqlite3BtreeEnter(p->pSrc);
|
||||
if( p->pDestDb ){
|
||||
@@ -624,7 +597,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
}
|
||||
|
||||
/* If a transaction is still open on the Btree, roll it back. */
|
||||
sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
|
||||
sqlite3BtreeRollback(p->pDest, SQLITE_OK);
|
||||
|
||||
/* Set the error code of the destination database handle. */
|
||||
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
|
||||
@@ -650,12 +623,6 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
** call to sqlite3_backup_step().
|
||||
*/
|
||||
int sqlite3_backup_remaining(sqlite3_backup *p){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return p->nRemaining;
|
||||
}
|
||||
|
||||
@@ -664,12 +631,6 @@ int sqlite3_backup_remaining(sqlite3_backup *p){
|
||||
** recent call to sqlite3_backup_step().
|
||||
*/
|
||||
int sqlite3_backup_pagecount(sqlite3_backup *p){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( p==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return p->nPagecount;
|
||||
}
|
||||
|
||||
|
||||
+351
-678
File diff suppressed because it is too large
Load Diff
+2
-3
@@ -83,7 +83,7 @@ int sqlite3BtreeBeginTrans(Btree*,int);
|
||||
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
|
||||
int sqlite3BtreeCommitPhaseTwo(Btree*, int);
|
||||
int sqlite3BtreeCommit(Btree*);
|
||||
int sqlite3BtreeRollback(Btree*,int,int);
|
||||
int sqlite3BtreeRollback(Btree*,int);
|
||||
int sqlite3BtreeBeginStmt(Btree*,int);
|
||||
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
|
||||
int sqlite3BtreeIsInTrans(Btree*);
|
||||
@@ -116,7 +116,7 @@ int sqlite3BtreeIncrVacuum(Btree *);
|
||||
int sqlite3BtreeDropTable(Btree*, int, int*);
|
||||
int sqlite3BtreeClearTable(Btree*, int, int*);
|
||||
int sqlite3BtreeClearTableOfCursor(BtCursor*);
|
||||
int sqlite3BtreeTripAllCursors(Btree*, int, int);
|
||||
void sqlite3BtreeTripAllCursors(Btree*, int);
|
||||
|
||||
void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
|
||||
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
||||
@@ -196,7 +196,6 @@ void sqlite3BtreeClearCursor(BtCursor *);
|
||||
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
|
||||
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
|
||||
int sqlite3BtreeIsReadonly(Btree *pBt);
|
||||
int sqlite3HeaderSizeBtree(void);
|
||||
|
||||
#ifndef NDEBUG
|
||||
int sqlite3BtreeCursorIsValid(BtCursor*);
|
||||
|
||||
+1
-5
@@ -307,11 +307,7 @@ int sqlite3UserAuthTable(const char *zTable){
|
||||
Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
|
||||
Table *p = 0;
|
||||
int i;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 ) return 0;
|
||||
#endif
|
||||
|
||||
assert( zName!=0 );
|
||||
/* All mutexes are required for schema access. Make sure we hold them. */
|
||||
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
|
||||
@@ -105,13 +105,6 @@ int sqlite3_complete(const char *zSql){
|
||||
u8 state = 0; /* Current state, using numbers defined in header comment */
|
||||
u8 token; /* Value of the next token */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( zSql==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
/* A complex statement machine used to detect the end of a CREATE TRIGGER
|
||||
** statement. This is the normal case.
|
||||
|
||||
+3
-10
@@ -63,9 +63,6 @@ static const char * const azCompileOpt[] = {
|
||||
#ifdef SQLITE_DISABLE_LFS
|
||||
"DISABLE_LFS",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
"ENABLE_API_ARMOR",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
"ENABLE_ATOMIC_WRITE",
|
||||
#endif
|
||||
@@ -158,6 +155,9 @@ static const char * const azCompileOpt[] = {
|
||||
#ifdef SQLITE_MAX_SCHEMA_RETRY
|
||||
"MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_WORKER_THREADS
|
||||
"MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
|
||||
#endif
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
"MEMDEBUG",
|
||||
#endif
|
||||
@@ -391,13 +391,6 @@ static const char * const azCompileOpt[] = {
|
||||
*/
|
||||
int sqlite3_compileoption_used(const char *zOptName){
|
||||
int i, n;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( zOptName==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
|
||||
n = sqlite3Strlen30(zOptName);
|
||||
|
||||
|
||||
+4
-4
@@ -16,7 +16,7 @@
|
||||
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** SQLite processes all times and dates as julian day numbers. The
|
||||
** SQLite processes all times and dates as Julian Day numbers. The
|
||||
** dates and times are stored as the number of days since noon
|
||||
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
|
||||
** calendar system.
|
||||
@@ -31,7 +31,7 @@
|
||||
**
|
||||
** The Gregorian calendar system is used for all dates and times,
|
||||
** even those that predate the Gregorian calendar. Historians usually
|
||||
** use the julian calendar for dates prior to 1582-10-15 and for some
|
||||
** use the Julian calendar for dates prior to 1582-10-15 and for some
|
||||
** dates afterwards, depending on locale. Beware of this difference.
|
||||
**
|
||||
** The conversion algorithms are implemented based on descriptions
|
||||
@@ -304,7 +304,7 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to parse the given string into a julian day number. Return
|
||||
** Attempt to parse the given string into a Julian Day Number. Return
|
||||
** the number of errors.
|
||||
**
|
||||
** The following are acceptable forms for the input string:
|
||||
@@ -875,7 +875,7 @@ static void dateFunc(
|
||||
** %f ** fractional seconds SS.SSS
|
||||
** %H hour 00-24
|
||||
** %j day of year 000-366
|
||||
** %J ** julian day number
|
||||
** %J ** Julian day number
|
||||
** %m month 01-12
|
||||
** %M minute 00-59
|
||||
** %s seconds since 1970-01-01
|
||||
|
||||
+1
-1
@@ -481,7 +481,7 @@ void sqlite3DeleteFrom(
|
||||
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
|
||||
assert( !IsVirtual(pTab) );
|
||||
if( aToOpen[iDataCur-iTabCur] ){
|
||||
assert( pPk!=0 || pTab->pSelect!=0 );
|
||||
assert( pPk!=0 );
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
|
||||
+33
-53
@@ -1210,24 +1210,20 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
|
||||
}
|
||||
|
||||
/*
|
||||
** These routines are Walker callbacks used to check expressions to
|
||||
** see if they are "constant" for some definition of constant. The
|
||||
** Walker.eCode value determines the type of "constant" we are looking
|
||||
** for.
|
||||
** These routines are Walker callbacks. Walker.u.pi is a pointer
|
||||
** to an integer. These routines are checking an expression to see
|
||||
** if it is a constant. Set *Walker.u.i to 0 if the expression is
|
||||
** not constant.
|
||||
**
|
||||
** These callback routines are used to implement the following:
|
||||
**
|
||||
** sqlite3ExprIsConstant() pWalker->eCode==1
|
||||
** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
|
||||
** sqlite3ExprRefOneTableOnly() pWalker->eCode==3
|
||||
** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
|
||||
**
|
||||
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
|
||||
** is found to not be a constant.
|
||||
** sqlite3ExprIsConstant() pWalker->u.i==1
|
||||
** sqlite3ExprIsConstantNotJoin() pWalker->u.i==2
|
||||
** sqlite3ExprIsConstantOrFunction() pWalker->u.i==3 or 4
|
||||
**
|
||||
** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
|
||||
** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing
|
||||
** an existing schema and 4 when processing a new statement. A bound
|
||||
** in a CREATE TABLE statement. The Walker.u.i value is 4 when parsing
|
||||
** an existing schema and 3 when processing a new statement. A bound
|
||||
** parameter raises an error for new statements, but is silently converted
|
||||
** to NULL for existing schemas. This allows sqlite_master tables that
|
||||
** contain a bound parameter because they were generated by older versions
|
||||
@@ -1236,25 +1232,23 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
|
||||
*/
|
||||
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
|
||||
/* If pWalker->eCode is 2 then any term of the expression that comes from
|
||||
** the ON or USING clauses of a left join disqualifies the expression
|
||||
/* If pWalker->u.i is 2 then any term of the expression that comes from
|
||||
** the ON or USING clauses of a join disqualifies the expression
|
||||
** from being considered constant. */
|
||||
if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
pWalker->eCode = 0;
|
||||
if( pWalker->u.i==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
pWalker->u.i = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
switch( pExpr->op ){
|
||||
/* Consider functions to be constant if all their arguments are constant
|
||||
** and either pWalker->eCode==4 or 5 or the function has the
|
||||
** SQLITE_FUNC_CONST flag. */
|
||||
** and either pWalker->u.i==3 or 4 or the function as the SQLITE_FUNC_CONST
|
||||
** flag. */
|
||||
case TK_FUNCTION:
|
||||
if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_Constant) ){
|
||||
if( pWalker->u.i>=3 || ExprHasProperty(pExpr,EP_Constant) ){
|
||||
return WRC_Continue;
|
||||
}else{
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
/* Fall through */
|
||||
case TK_ID:
|
||||
case TK_COLUMN:
|
||||
case TK_AGG_FUNCTION:
|
||||
@@ -1263,22 +1257,18 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pExpr->op==TK_COLUMN );
|
||||
testcase( pExpr->op==TK_AGG_FUNCTION );
|
||||
testcase( pExpr->op==TK_AGG_COLUMN );
|
||||
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
|
||||
return WRC_Continue;
|
||||
}else{
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
pWalker->u.i = 0;
|
||||
return WRC_Abort;
|
||||
case TK_VARIABLE:
|
||||
if( pWalker->eCode==5 ){
|
||||
if( pWalker->u.i==4 ){
|
||||
/* Silently convert bound parameters that appear inside of CREATE
|
||||
** statements into a NULL when parsing the CREATE statement text out
|
||||
** of the sqlite_master table */
|
||||
pExpr->op = TK_NULL;
|
||||
}else if( pWalker->eCode==4 ){
|
||||
}else if( pWalker->u.i==3 ){
|
||||
/* A bound parameter in a CREATE statement that originates from
|
||||
** sqlite3_prepare() causes an error */
|
||||
pWalker->eCode = 0;
|
||||
pWalker->u.i = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
/* Fall through */
|
||||
@@ -1290,22 +1280,21 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
pWalker->eCode = 0;
|
||||
pWalker->u.i = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
static int exprIsConst(Expr *p, int initFlag, int iCur){
|
||||
static int exprIsConst(Expr *p, int initFlag){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.eCode = initFlag;
|
||||
w.u.i = initFlag;
|
||||
w.xExprCallback = exprNodeIsConstant;
|
||||
w.xSelectCallback = selectNodeIsConstant;
|
||||
w.u.iCur = iCur;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode;
|
||||
return w.u.i;
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Return non-zero if the expression is constant
|
||||
** Walk an expression tree. Return 1 if the expression is constant
|
||||
** and 0 if it involves variables or function calls.
|
||||
**
|
||||
** For the purposes of this function, a double-quoted string (ex: "abc")
|
||||
@@ -1313,31 +1302,21 @@ static int exprIsConst(Expr *p, int initFlag, int iCur){
|
||||
** a constant.
|
||||
*/
|
||||
int sqlite3ExprIsConstant(Expr *p){
|
||||
return exprIsConst(p, 1, 0);
|
||||
return exprIsConst(p, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Return non-zero if the expression is constant
|
||||
** Walk an expression tree. Return 1 if the expression is constant
|
||||
** that does no originate from the ON or USING clauses of a join.
|
||||
** Return 0 if it involves variables or function calls or terms from
|
||||
** an ON or USING clause.
|
||||
*/
|
||||
int sqlite3ExprIsConstantNotJoin(Expr *p){
|
||||
return exprIsConst(p, 2, 0);
|
||||
return exprIsConst(p, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Return non-zero if the expression constant
|
||||
** for any single row of the table with cursor iCur. In other words, the
|
||||
** expression must not refer to any non-deterministic function nor any
|
||||
** table other than iCur.
|
||||
*/
|
||||
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
return exprIsConst(p, 3, iCur);
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Return non-zero if the expression is constant
|
||||
** Walk an expression tree. Return 1 if the expression is constant
|
||||
** or a function call with constant arguments. Return and 0 if there
|
||||
** are any variables.
|
||||
**
|
||||
@@ -1347,7 +1326,7 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
||||
*/
|
||||
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
||||
assert( isInit==0 || isInit==1 );
|
||||
return exprIsConst(p, 4+isInit, 0);
|
||||
return exprIsConst(p, 3+isInit);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1857,6 +1836,7 @@ int sqlite3CodeSubselect(
|
||||
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
|
||||
pSelect->iLimit = 0;
|
||||
testcase( pSelect->selFlags & SF_Distinct );
|
||||
pSelect->selFlags &= ~SF_Distinct;
|
||||
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
|
||||
if( sqlite3Select(pParse, pSelect, &dest) ){
|
||||
sqlite3KeyInfoUnref(pKeyInfo);
|
||||
|
||||
+2
-10
@@ -135,19 +135,11 @@ const unsigned char sqlite3CtypeMap[256] = {
|
||||
**
|
||||
** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled
|
||||
** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options.
|
||||
**
|
||||
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
|
||||
** disabled. The default value may be changed by compiling with the
|
||||
** SQLITE_USE_URI symbol defined.
|
||||
*/
|
||||
#ifndef SQLITE_USE_URI
|
||||
# define SQLITE_USE_URI 0
|
||||
#endif
|
||||
|
||||
/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
|
||||
** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
|
||||
** that compile-time option is omitted.
|
||||
*/
|
||||
#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
|
||||
# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
|
||||
#endif
|
||||
@@ -237,8 +229,8 @@ const Token sqlite3IntTokens[] = {
|
||||
**
|
||||
** IMPORTANT: Changing the pending byte to any value other than
|
||||
** 0x40000000 results in an incompatible database file format!
|
||||
** Changing the pending byte during operation will result in undefined
|
||||
** and incorrect behavior.
|
||||
** Changing the pending byte during operating results in undefined
|
||||
** and dileterious behavior.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_WSD
|
||||
int sqlite3PendingByte = 0x40000000;
|
||||
|
||||
+37
-261
@@ -329,17 +329,15 @@ int sqlite3_config(int op, ...){
|
||||
switch( op ){
|
||||
|
||||
/* Mutex configuration options are only available in a threadsafe
|
||||
** compile.
|
||||
** compile.
|
||||
*/
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0
|
||||
case SQLITE_CONFIG_SINGLETHREAD: {
|
||||
/* Disable all mutexing */
|
||||
sqlite3GlobalConfig.bCoreMutex = 0;
|
||||
sqlite3GlobalConfig.bFullMutex = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */
|
||||
case SQLITE_CONFIG_MULTITHREAD: {
|
||||
/* Disable mutexing of database connections */
|
||||
/* Enable mutexing of core data structures */
|
||||
@@ -347,23 +345,17 @@ int sqlite3_config(int op, ...){
|
||||
sqlite3GlobalConfig.bFullMutex = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */
|
||||
case SQLITE_CONFIG_SERIALIZED: {
|
||||
/* Enable all mutexing */
|
||||
sqlite3GlobalConfig.bCoreMutex = 1;
|
||||
sqlite3GlobalConfig.bFullMutex = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */
|
||||
case SQLITE_CONFIG_MUTEX: {
|
||||
/* Specify an alternative mutex implementation */
|
||||
sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-14450-37597 */
|
||||
case SQLITE_CONFIG_GETMUTEX: {
|
||||
/* Retrieve the current mutex implementation */
|
||||
*va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex;
|
||||
@@ -371,61 +363,37 @@ int sqlite3_config(int op, ...){
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
case SQLITE_CONFIG_MALLOC: {
|
||||
/* EVIDENCE-OF: R-55594-21030 The SQLITE_CONFIG_MALLOC option takes a
|
||||
** single argument which is a pointer to an instance of the
|
||||
** sqlite3_mem_methods structure. The argument specifies alternative
|
||||
** low-level memory allocation routines to be used in place of the memory
|
||||
** allocation routines built into SQLite. */
|
||||
/* Specify an alternative malloc implementation */
|
||||
sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*);
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_GETMALLOC: {
|
||||
/* EVIDENCE-OF: R-51213-46414 The SQLITE_CONFIG_GETMALLOC option takes a
|
||||
** single argument which is a pointer to an instance of the
|
||||
** sqlite3_mem_methods structure. The sqlite3_mem_methods structure is
|
||||
** filled with the currently defined memory allocation routines. */
|
||||
/* Retrieve the current malloc() implementation */
|
||||
if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
|
||||
*va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m;
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_MEMSTATUS: {
|
||||
/* EVIDENCE-OF: R-61275-35157 The SQLITE_CONFIG_MEMSTATUS option takes
|
||||
** single argument of type int, interpreted as a boolean, which enables
|
||||
** or disables the collection of memory allocation statistics. */
|
||||
/* Enable or disable the malloc status collection */
|
||||
sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_SCRATCH: {
|
||||
/* EVIDENCE-OF: R-08404-60887 There are three arguments to
|
||||
** SQLITE_CONFIG_SCRATCH: A pointer an 8-byte aligned memory buffer from
|
||||
** which the scratch allocations will be drawn, the size of each scratch
|
||||
** allocation (sz), and the maximum number of scratch allocations (N). */
|
||||
/* Designate a buffer for scratch memory space */
|
||||
sqlite3GlobalConfig.pScratch = va_arg(ap, void*);
|
||||
sqlite3GlobalConfig.szScratch = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.nScratch = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_PAGECACHE: {
|
||||
/* EVIDENCE-OF: R-31408-40510 There are three arguments to
|
||||
** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory, the size
|
||||
** of each page buffer (sz), and the number of pages (N). */
|
||||
/* Designate a buffer for page cache memory space */
|
||||
sqlite3GlobalConfig.pPage = va_arg(ap, void*);
|
||||
sqlite3GlobalConfig.szPage = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.nPage = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_PCACHE_HDRSZ: {
|
||||
/* EVIDENCE-OF: R-39100-27317 The SQLITE_CONFIG_PCACHE_HDRSZ option takes
|
||||
** a single parameter which is a pointer to an integer and writes into
|
||||
** that integer the number of extra bytes per page required for each page
|
||||
** in SQLITE_CONFIG_PAGECACHE. */
|
||||
*va_arg(ap, int*) =
|
||||
sqlite3HeaderSizeBtree() +
|
||||
sqlite3HeaderSizePcache() +
|
||||
sqlite3HeaderSizePcache1();
|
||||
break;
|
||||
}
|
||||
|
||||
case SQLITE_CONFIG_PCACHE: {
|
||||
/* no-op */
|
||||
@@ -438,18 +406,11 @@ int sqlite3_config(int op, ...){
|
||||
}
|
||||
|
||||
case SQLITE_CONFIG_PCACHE2: {
|
||||
/* EVIDENCE-OF: R-63325-48378 The SQLITE_CONFIG_PCACHE2 option takes a
|
||||
** single argument which is a pointer to an sqlite3_pcache_methods2
|
||||
** object. This object specifies the interface to a custom page cache
|
||||
** implementation. */
|
||||
/* Specify an alternative page cache implementation */
|
||||
sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*);
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_GETPCACHE2: {
|
||||
/* EVIDENCE-OF: R-22035-46182 The SQLITE_CONFIG_GETPCACHE2 option takes a
|
||||
** single argument which is a pointer to an sqlite3_pcache_methods2
|
||||
** object. SQLite copies of the current page cache implementation into
|
||||
** that object. */
|
||||
if( sqlite3GlobalConfig.pcache2.xInit==0 ){
|
||||
sqlite3PCacheSetDefault();
|
||||
}
|
||||
@@ -457,14 +418,9 @@ int sqlite3_config(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* EVIDENCE-OF: R-06626-12911 The SQLITE_CONFIG_HEAP option is only
|
||||
** available if SQLite is compiled with either SQLITE_ENABLE_MEMSYS3 or
|
||||
** SQLITE_ENABLE_MEMSYS5 and returns SQLITE_ERROR if invoked otherwise. */
|
||||
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
|
||||
case SQLITE_CONFIG_HEAP: {
|
||||
/* EVIDENCE-OF: R-19854-42126 There are three arguments to
|
||||
** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the
|
||||
** number of bytes in the memory buffer, and the minimum allocation size. */
|
||||
/* Designate a buffer for heap memory space */
|
||||
sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
|
||||
sqlite3GlobalConfig.nHeap = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.mnReq = va_arg(ap, int);
|
||||
@@ -477,19 +433,17 @@ int sqlite3_config(int op, ...){
|
||||
}
|
||||
|
||||
if( sqlite3GlobalConfig.pHeap==0 ){
|
||||
/* EVIDENCE-OF: R-49920-60189 If the first pointer (the memory pointer)
|
||||
** is NULL, then SQLite reverts to using its default memory allocator
|
||||
** (the system malloc() implementation), undoing any prior invocation of
|
||||
** SQLITE_CONFIG_MALLOC.
|
||||
**
|
||||
** Setting sqlite3GlobalConfig.m to all zeros will cause malloc to
|
||||
** revert to its default implementation when sqlite3_initialize() is run
|
||||
/* If the heap pointer is NULL, then restore the malloc implementation
|
||||
** back to NULL pointers too. This will cause the malloc to go
|
||||
** back to its default implementation when sqlite3_initialize() is
|
||||
** run.
|
||||
*/
|
||||
memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
|
||||
}else{
|
||||
/* EVIDENCE-OF: R-61006-08918 If the memory pointer is not NULL then the
|
||||
** alternative memory allocator is engaged to handle all of SQLites
|
||||
** memory allocation needs. */
|
||||
/* The heap pointer is not NULL, then install one of the
|
||||
** mem5.c/mem3.c methods. The enclosing #if guarantees at
|
||||
** least one of these methods is currently enabled.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
|
||||
#endif
|
||||
@@ -528,19 +482,11 @@ int sqlite3_config(int op, ...){
|
||||
** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls.
|
||||
*/
|
||||
case SQLITE_CONFIG_URI: {
|
||||
/* EVIDENCE-OF: R-25451-61125 The SQLITE_CONFIG_URI option takes a single
|
||||
** argument of type int. If non-zero, then URI handling is globally
|
||||
** enabled. If the parameter is zero, then URI handling is globally
|
||||
** disabled. */
|
||||
sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
|
||||
case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
|
||||
/* EVIDENCE-OF: R-36592-02772 The SQLITE_CONFIG_COVERING_INDEX_SCAN
|
||||
** option takes a single integer argument which is interpreted as a
|
||||
** boolean in order to enable or disable the use of covering indices for
|
||||
** full table scans in the query optimizer. */
|
||||
sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
@@ -555,33 +501,20 @@ int sqlite3_config(int op, ...){
|
||||
#endif
|
||||
|
||||
case SQLITE_CONFIG_MMAP_SIZE: {
|
||||
/* EVIDENCE-OF: R-58063-38258 SQLITE_CONFIG_MMAP_SIZE takes two 64-bit
|
||||
** integer (sqlite3_int64) values that are the default mmap size limit
|
||||
** (the default setting for PRAGMA mmap_size) and the maximum allowed
|
||||
** mmap size limit. */
|
||||
sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64);
|
||||
sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64);
|
||||
/* EVIDENCE-OF: R-53367-43190 If either argument to this option is
|
||||
** negative, then that argument is changed to its compile-time default.
|
||||
**
|
||||
** EVIDENCE-OF: R-34993-45031 The maximum allowed mmap size will be
|
||||
** silently truncated if necessary so that it does not exceed the
|
||||
** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE
|
||||
** compile-time option.
|
||||
*/
|
||||
if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ) mxMmap = SQLITE_MAX_MMAP_SIZE;
|
||||
if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
|
||||
mxMmap = SQLITE_MAX_MMAP_SIZE;
|
||||
}
|
||||
sqlite3GlobalConfig.mxMmap = mxMmap;
|
||||
if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
|
||||
if( szMmap>mxMmap) szMmap = mxMmap;
|
||||
sqlite3GlobalConfig.mxMmap = mxMmap;
|
||||
sqlite3GlobalConfig.szMmap = szMmap;
|
||||
break;
|
||||
}
|
||||
|
||||
#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC) /* IMP: R-04780-55815 */
|
||||
#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC)
|
||||
case SQLITE_CONFIG_WIN32_HEAPSIZE: {
|
||||
/* EVIDENCE-OF: R-34926-03360 SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit
|
||||
** unsigned integer value that specifies the maximum size of the created
|
||||
** heap. */
|
||||
sqlite3GlobalConfig.nHeap = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
@@ -665,12 +598,6 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
||||
** Return the mutex associated with a database connection.
|
||||
*/
|
||||
sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return db->mutex;
|
||||
}
|
||||
|
||||
@@ -680,10 +607,6 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){
|
||||
*/
|
||||
int sqlite3_db_release_memory(sqlite3 *db){
|
||||
int i;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
@@ -814,12 +737,6 @@ static int nocaseCollatingFunc(
|
||||
** Return the ROWID of the most recent insert
|
||||
*/
|
||||
sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return db->lastRowid;
|
||||
}
|
||||
|
||||
@@ -827,12 +744,6 @@ sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
|
||||
** Return the number of changes in the most recent call to sqlite3_exec().
|
||||
*/
|
||||
int sqlite3_changes(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return db->nChange;
|
||||
}
|
||||
|
||||
@@ -840,12 +751,6 @@ int sqlite3_changes(sqlite3 *db){
|
||||
** Return the number of changes since the database handle was opened.
|
||||
*/
|
||||
int sqlite3_total_changes(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return db->nTotalChange;
|
||||
}
|
||||
|
||||
@@ -1111,15 +1016,13 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
||||
|
||||
/*
|
||||
** Rollback all database files. If tripCode is not SQLITE_OK, then
|
||||
** any write cursors are invalidated ("tripped" - as in "tripping a circuit
|
||||
** any open cursors are invalidated ("tripped" - as in "tripping a circuit
|
||||
** breaker") and made to return tripCode if there are any further
|
||||
** attempts to use that cursor. Read cursors remain open and valid
|
||||
** but are "saved" in case the table pages are moved around.
|
||||
** attempts to use that cursor.
|
||||
*/
|
||||
void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
||||
int i;
|
||||
int inTrans = 0;
|
||||
int schemaChange;
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
sqlite3BeginBenignMalloc();
|
||||
|
||||
@@ -1130,7 +1033,6 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
||||
** the database rollback and schema reset, which can cause false
|
||||
** corruption reports in some cases. */
|
||||
sqlite3BtreeEnterAll(db);
|
||||
schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0;
|
||||
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Btree *p = db->aDb[i].pBt;
|
||||
@@ -1138,7 +1040,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
||||
if( sqlite3BtreeIsInTrans(p) ){
|
||||
inTrans = 1;
|
||||
}
|
||||
sqlite3BtreeRollback(p, tripCode, !schemaChange);
|
||||
sqlite3BtreeRollback(p, tripCode);
|
||||
}
|
||||
}
|
||||
sqlite3VtabRollback(db);
|
||||
@@ -1394,9 +1296,6 @@ int sqlite3_busy_handler(
|
||||
int (*xBusy)(void*,int),
|
||||
void *pArg
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->busyHandler.xFunc = xBusy;
|
||||
db->busyHandler.pArg = pArg;
|
||||
@@ -1418,12 +1317,6 @@ void sqlite3_progress_handler(
|
||||
int (*xProgress)(void*),
|
||||
void *pArg
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( nOps>0 ){
|
||||
db->xProgress = xProgress;
|
||||
@@ -1444,9 +1337,6 @@ void sqlite3_progress_handler(
|
||||
** specified number of milliseconds before returning 0.
|
||||
*/
|
||||
int sqlite3_busy_timeout(sqlite3 *db, int ms){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
if( ms>0 ){
|
||||
sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
|
||||
db->busyTimeout = ms;
|
||||
@@ -1460,12 +1350,6 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
|
||||
** Cause any pending operation to stop at its earliest opportunity.
|
||||
*/
|
||||
void sqlite3_interrupt(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
db->u1.isInterrupted = 1;
|
||||
}
|
||||
|
||||
@@ -1603,12 +1487,6 @@ int sqlite3_create_function_v2(
|
||||
){
|
||||
int rc = SQLITE_ERROR;
|
||||
FuncDestructor *pArg = 0;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( xDestroy ){
|
||||
pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor));
|
||||
@@ -1645,10 +1523,6 @@ int sqlite3_create_function16(
|
||||
){
|
||||
int rc;
|
||||
char *zFunc8;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zFunctionName==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
assert( !db->mallocFailed );
|
||||
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE);
|
||||
@@ -1680,12 +1554,6 @@ int sqlite3_overload_function(
|
||||
){
|
||||
int nName = sqlite3Strlen30(zName);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){
|
||||
rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
|
||||
@@ -1707,13 +1575,6 @@ int sqlite3_overload_function(
|
||||
*/
|
||||
void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
|
||||
void *pOld;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pOld = db->pTraceArg;
|
||||
db->xTrace = xTrace;
|
||||
@@ -1735,13 +1596,6 @@ void *sqlite3_profile(
|
||||
void *pArg
|
||||
){
|
||||
void *pOld;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pOld = db->pProfileArg;
|
||||
db->xProfile = xProfile;
|
||||
@@ -1762,13 +1616,6 @@ void *sqlite3_commit_hook(
|
||||
void *pArg /* Argument to the function */
|
||||
){
|
||||
void *pOld;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pOld = db->pCommitArg;
|
||||
db->xCommitCallback = xCallback;
|
||||
@@ -1787,13 +1634,6 @@ void *sqlite3_update_hook(
|
||||
void *pArg /* Argument to the function */
|
||||
){
|
||||
void *pRet;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pRet = db->pUpdateArg;
|
||||
db->xUpdateCallback = xCallback;
|
||||
@@ -1812,13 +1652,6 @@ void *sqlite3_rollback_hook(
|
||||
void *pArg /* Argument to the function */
|
||||
){
|
||||
void *pRet;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pRet = db->pRollbackArg;
|
||||
db->xRollbackCallback = xCallback;
|
||||
@@ -1865,9 +1698,6 @@ int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){
|
||||
UNUSED_PARAMETER(db);
|
||||
UNUSED_PARAMETER(nFrame);
|
||||
#else
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
if( nFrame>0 ){
|
||||
sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame));
|
||||
}else{
|
||||
@@ -1888,12 +1718,6 @@ void *sqlite3_wal_hook(
|
||||
){
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
void *pRet;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pRet = db->pWalArg;
|
||||
db->xWalCallback = xCallback;
|
||||
@@ -1921,10 +1745,6 @@ int sqlite3_wal_checkpoint_v2(
|
||||
int rc; /* Return code */
|
||||
int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
|
||||
/* Initialize the output variables to -1 in case an error occurs. */
|
||||
if( pnLog ) *pnLog = -1;
|
||||
if( pnCkpt ) *pnCkpt = -1;
|
||||
@@ -2321,12 +2141,6 @@ static const int aHardLimit[] = {
|
||||
int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
||||
int oldLimit;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME
|
||||
** there is a hard upper bound set at compile-time by a C preprocessor
|
||||
@@ -2403,8 +2217,7 @@ int sqlite3ParseUri(
|
||||
|
||||
assert( *pzErrMsg==0 );
|
||||
|
||||
if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */
|
||||
|| sqlite3GlobalConfig.bOpenUri) /* IMP: R-51689-46548 */
|
||||
if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
|
||||
&& nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */
|
||||
){
|
||||
char *zOpt;
|
||||
@@ -2613,9 +2426,6 @@ static int openDatabase(
|
||||
char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
|
||||
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
*ppDb = 0;
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
rc = sqlite3_initialize();
|
||||
@@ -2905,15 +2715,13 @@ int sqlite3_open16(
|
||||
sqlite3_value *pVal;
|
||||
int rc;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
assert( zFilename );
|
||||
assert( ppDb );
|
||||
*ppDb = 0;
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
rc = sqlite3_initialize();
|
||||
if( rc ) return rc;
|
||||
#endif
|
||||
if( zFilename==0 ) zFilename = "\000\000";
|
||||
pVal = sqlite3ValueNew(0);
|
||||
sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC);
|
||||
zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8);
|
||||
@@ -2943,7 +2751,13 @@ int sqlite3_create_collation(
|
||||
void* pCtx,
|
||||
int(*xCompare)(void*,int,const void*,int,const void*)
|
||||
){
|
||||
return sqlite3_create_collation_v2(db, zName, enc, pCtx, xCompare, 0);
|
||||
int rc;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
assert( !db->mallocFailed );
|
||||
rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, 0);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2958,10 +2772,6 @@ int sqlite3_create_collation_v2(
|
||||
void(*xDel)(void*)
|
||||
){
|
||||
int rc;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
assert( !db->mallocFailed );
|
||||
rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, xDel);
|
||||
@@ -2983,10 +2793,6 @@ int sqlite3_create_collation16(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
char *zName8;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
assert( !db->mallocFailed );
|
||||
zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE);
|
||||
@@ -3009,9 +2815,6 @@ int sqlite3_collation_needed(
|
||||
void *pCollNeededArg,
|
||||
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*)
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->xCollNeeded = xCollNeeded;
|
||||
db->xCollNeeded16 = 0;
|
||||
@@ -3030,9 +2833,6 @@ int sqlite3_collation_needed16(
|
||||
void *pCollNeededArg,
|
||||
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*)
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->xCollNeeded = 0;
|
||||
db->xCollNeeded16 = xCollNeeded16;
|
||||
@@ -3059,12 +2859,6 @@ int sqlite3_global_recover(void){
|
||||
** by the next COMMIT or ROLLBACK.
|
||||
*/
|
||||
int sqlite3_get_autocommit(sqlite3 *db){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return db->autoCommit;
|
||||
}
|
||||
|
||||
@@ -3247,9 +3041,6 @@ int sqlite3_sleep(int ms){
|
||||
** Enable or disable the extended result codes.
|
||||
*/
|
||||
int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->errMask = onoff ? 0xffffffff : 0xff;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
@@ -3263,9 +3054,6 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
|
||||
int rc = SQLITE_ERROR;
|
||||
Btree *pBtree;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
pBtree = sqlite3DbNameToBtree(db, zDbName);
|
||||
if( pBtree ){
|
||||
@@ -3608,7 +3396,7 @@ int sqlite3_test_control(int op, ...){
|
||||
** returns a NULL pointer.
|
||||
*/
|
||||
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
|
||||
if( zFilename==0 || zParam==0 ) return 0;
|
||||
if( zFilename==0 ) return 0;
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] ){
|
||||
int x = strcmp(zFilename, zParam);
|
||||
@@ -3664,12 +3452,6 @@ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
|
||||
** connection.
|
||||
*/
|
||||
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
|
||||
return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
|
||||
}
|
||||
@@ -3679,12 +3461,6 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
|
||||
** no such database exists.
|
||||
*/
|
||||
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
|
||||
return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
|
||||
}
|
||||
|
||||
+5
-6
@@ -377,12 +377,11 @@ void *sqlite3ScratchMalloc(int n){
|
||||
|
||||
|
||||
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
|
||||
/* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch
|
||||
** buffers per thread.
|
||||
**
|
||||
** This can only be checked in single-threaded mode.
|
||||
*/
|
||||
assert( scratchAllocOut==0 );
|
||||
/* Verify that no more than two scratch allocations per thread
|
||||
** are outstanding at one time. (This is only checked in the
|
||||
** single-threaded case since checking in the multi-threaded case
|
||||
** would be much more complicated.) */
|
||||
assert( scratchAllocOut<=1 );
|
||||
if( p ) scratchAllocOut++;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -82,7 +82,6 @@ int sqlite3MutexEnd(void){
|
||||
sqlite3_mutex *sqlite3_mutex_alloc(int id){
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
|
||||
if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
|
||||
#endif
|
||||
return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
|
||||
}
|
||||
|
||||
+2
-6
@@ -175,12 +175,8 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
assert( iType-2 >= 0 );
|
||||
assert( iType-2 < ArraySize(staticMutexes) );
|
||||
p = &staticMutexes[iType-2];
|
||||
#if SQLITE_MUTEX_NREF
|
||||
p->id = iType;
|
||||
|
||||
@@ -361,10 +361,6 @@ int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
|
||||
int rc = sqlite3_initialize();
|
||||
if( rc ) return rc;
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
|
||||
MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
|
||||
sqlite3_mutex_enter(mutex);
|
||||
vfsUnlink(pVfs);
|
||||
|
||||
+10
-17
@@ -34,11 +34,6 @@
|
||||
with SQLITE_OMIT_WAL."
|
||||
#endif
|
||||
|
||||
#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0
|
||||
# error "Memory mapped files require support from the Windows NT kernel,\
|
||||
compile with SQLITE_MAX_MMAP_SIZE=0."
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
|
||||
** based on the sub-platform)?
|
||||
@@ -168,11 +163,10 @@
|
||||
|
||||
/*
|
||||
** Do we need to manually define the Win32 file mapping APIs for use with WAL
|
||||
** mode or memory mapped files (e.g. these APIs are available in the Windows
|
||||
** CE SDK; however, they are not present in the header file)?
|
||||
** mode (e.g. these APIs are available in the Windows CE SDK; however, they
|
||||
** are not present in the header file)?
|
||||
*/
|
||||
#if SQLITE_WIN32_FILEMAPPING_API && \
|
||||
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
||||
#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
|
||||
/*
|
||||
** Two of the file mapping APIs are different under WinRT. Figure out which
|
||||
** set we need.
|
||||
@@ -200,7 +194,7 @@ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
|
||||
** This file mapping API is common to both Win32 and WinRT.
|
||||
*/
|
||||
WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
|
||||
#endif /* SQLITE_WIN32_FILEMAPPING_API */
|
||||
#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
|
||||
|
||||
/*
|
||||
** Some Microsoft compilers lack this definition.
|
||||
@@ -493,7 +487,7 @@ static struct win_syscall {
|
||||
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
|
||||
|
||||
#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
|
||||
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
|
||||
!defined(SQLITE_OMIT_WAL))
|
||||
{ "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
|
||||
#else
|
||||
{ "CreateFileMappingA", (SYSCALL)0, 0 },
|
||||
@@ -503,7 +497,7 @@ static struct win_syscall {
|
||||
DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
||||
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
|
||||
!defined(SQLITE_OMIT_WAL))
|
||||
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
|
||||
#else
|
||||
{ "CreateFileMappingW", (SYSCALL)0, 0 },
|
||||
@@ -843,8 +837,7 @@ static struct win_syscall {
|
||||
LPOVERLAPPED))aSyscall[48].pCurrent)
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \
|
||||
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
|
||||
{ "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
|
||||
#else
|
||||
{ "MapViewOfFile", (SYSCALL)0, 0 },
|
||||
@@ -914,7 +907,7 @@ static struct win_syscall {
|
||||
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
||||
LPOVERLAPPED))aSyscall[58].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
||||
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
|
||||
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
|
||||
#else
|
||||
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
|
||||
@@ -977,7 +970,7 @@ static struct win_syscall {
|
||||
#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
|
||||
FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
|
||||
{ "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
|
||||
#else
|
||||
{ "MapViewOfFileFromApp", (SYSCALL)0, 0 },
|
||||
@@ -1041,7 +1034,7 @@ static struct win_syscall {
|
||||
|
||||
#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
|
||||
{ "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
|
||||
#else
|
||||
{ "CreateFileMappingFromApp", (SYSCALL)0, 0 },
|
||||
|
||||
-13
@@ -6847,18 +6847,6 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The page handle passed as the first argument refers to a dirty page
|
||||
** with a page number other than iNew. This function changes the page's
|
||||
** page number to iNew and sets the value of the PgHdr.flags field to
|
||||
** the value passed as the third parameter.
|
||||
*/
|
||||
void sqlite3PagerRekey(DbPage *pPg, Pgno iNew, u16 flags){
|
||||
assert( pPg->pgno!=iNew );
|
||||
pPg->flags = flags;
|
||||
sqlite3PcacheMove(pPg, iNew);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to the data for the specified page.
|
||||
*/
|
||||
@@ -7257,5 +7245,4 @@ int sqlite3PagerWalFramesize(Pager *pPager){
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SQLITE_OMIT_DISKIO */
|
||||
|
||||
@@ -188,8 +188,6 @@ int sqlite3SectorSize(sqlite3_file *);
|
||||
/* Functions used to truncate the database file. */
|
||||
void sqlite3PagerTruncateImage(Pager*,Pgno);
|
||||
|
||||
void sqlite3PagerRekey(DbPage*, Pgno, u16);
|
||||
|
||||
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
|
||||
void *sqlite3PagerCodec(DbPage *);
|
||||
#endif
|
||||
|
||||
@@ -651,13 +651,6 @@ void sqlite3PcacheShrink(PCache *pCache){
|
||||
sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the size of the header added by this middleware layer
|
||||
** in the page-cache hierarchy.
|
||||
*/
|
||||
int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); }
|
||||
|
||||
|
||||
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** For all dirty pages currently in the cache, invoke the specified
|
||||
|
||||
@@ -160,8 +160,4 @@ void sqlite3PcacheStats(int*,int*,int*,int*);
|
||||
|
||||
void sqlite3PCacheSetDefault(void);
|
||||
|
||||
/* Return the header size */
|
||||
int sqlite3HeaderSizePcache(void);
|
||||
int sqlite3HeaderSizePcache1(void);
|
||||
|
||||
#endif /* _PCACHE_H_ */
|
||||
|
||||
@@ -981,11 +981,6 @@ void sqlite3PCacheSetDefault(void){
|
||||
sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the size of the header on each page of this PCACHE implementation.
|
||||
*/
|
||||
int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); }
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
/*
|
||||
** This function is called to free superfluous dynamically allocated memory
|
||||
|
||||
+4
-9
@@ -709,12 +709,9 @@ static int sqlite3LockAndPrepare(
|
||||
const char **pzTail /* OUT: End of parsed string */
|
||||
){
|
||||
int rc;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
assert( ppStmt!=0 );
|
||||
*ppStmt = 0;
|
||||
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
@@ -821,11 +818,9 @@ static int sqlite3Prepare16(
|
||||
const char *zTail8 = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
assert( ppStmt );
|
||||
*ppStmt = 0;
|
||||
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
if( nBytes>=0 ){
|
||||
|
||||
+19
-47
@@ -21,7 +21,11 @@
|
||||
** the glibc version so the glibc version is definitely preferred.
|
||||
*/
|
||||
#if !defined(HAVE_STRCHRNUL)
|
||||
# define HAVE_STRCHRNUL 0
|
||||
# if defined(linux)
|
||||
# define HAVE_STRCHRNUL 1
|
||||
# else
|
||||
# define HAVE_STRCHRNUL 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -212,7 +216,7 @@ void sqlite3VXPrintf(
|
||||
const et_info *infop; /* Pointer to the appropriate info structure */
|
||||
char *zOut; /* Rendering buffer */
|
||||
int nOut; /* Size of the rendering buffer */
|
||||
char *zExtra = 0; /* Malloced memory used by some conversion */
|
||||
char *zExtra; /* Malloced memory used by some conversion */
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int exp, e2; /* exponent of real numbers */
|
||||
int nsd; /* Number of significant digits returned */
|
||||
@@ -223,13 +227,6 @@ void sqlite3VXPrintf(
|
||||
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
|
||||
char buf[etBUFSIZE]; /* Conversion buffer */
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( ap==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
sqlite3StrAccumReset(pAccum);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bufpt = 0;
|
||||
if( bFlags ){
|
||||
if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
|
||||
@@ -336,6 +333,7 @@ void sqlite3VXPrintf(
|
||||
break;
|
||||
}
|
||||
}
|
||||
zExtra = 0;
|
||||
|
||||
/*
|
||||
** At this point, variables are initialized as follows:
|
||||
@@ -626,16 +624,13 @@ void sqlite3VXPrintf(
|
||||
}else{
|
||||
c = va_arg(ap,int);
|
||||
}
|
||||
if( precision>1 ){
|
||||
width -= precision-1;
|
||||
if( width>1 && !flag_leftjustify ){
|
||||
sqlite3AppendChar(pAccum, width-1, ' ');
|
||||
width = 0;
|
||||
}
|
||||
sqlite3AppendChar(pAccum, precision-1, c);
|
||||
buf[0] = (char)c;
|
||||
if( precision>=0 ){
|
||||
for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
|
||||
length = precision;
|
||||
}else{
|
||||
length =1;
|
||||
}
|
||||
length = 1;
|
||||
buf[0] = c;
|
||||
bufpt = buf;
|
||||
break;
|
||||
case etSTRING:
|
||||
@@ -736,14 +731,11 @@ void sqlite3VXPrintf(
|
||||
** the output.
|
||||
*/
|
||||
width -= length;
|
||||
if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
|
||||
if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, length);
|
||||
if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
|
||||
if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
|
||||
|
||||
if( zExtra ){
|
||||
sqlite3_free(zExtra);
|
||||
zExtra = 0;
|
||||
}
|
||||
if( zExtra ) sqlite3_free(zExtra);
|
||||
}/* End for loop over the format string */
|
||||
} /* End of function */
|
||||
|
||||
@@ -770,11 +762,6 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
|
||||
i64 szNew = p->nChar;
|
||||
szNew += N + 1;
|
||||
if( szNew+p->nChar<=p->mxAlloc ){
|
||||
/* Force exponential buffer size growth as long as it does not overflow,
|
||||
** to avoid having to call this routine too often */
|
||||
szNew += p->nChar;
|
||||
}
|
||||
if( szNew > p->mxAlloc ){
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
@@ -791,7 +778,6 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
assert( p->zText!=0 || p->nChar==0 );
|
||||
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
||||
p->zText = zNew;
|
||||
p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
|
||||
}else{
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
@@ -802,11 +788,11 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
}
|
||||
|
||||
/*
|
||||
** Append N copies of character c to the given string buffer.
|
||||
** Append N space characters to the given string buffer.
|
||||
*/
|
||||
void sqlite3AppendChar(StrAccum *p, int N, char c){
|
||||
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++] = c;
|
||||
while( (N--)>0 ) p->zText[p->nChar++] = ' ';
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -961,13 +947,6 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){
|
||||
char *z;
|
||||
char zBase[SQLITE_PRINT_BUF_SIZE];
|
||||
StrAccum acc;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( zFormat==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
#endif
|
||||
@@ -1010,13 +989,6 @@ char *sqlite3_mprintf(const char *zFormat, ...){
|
||||
char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
|
||||
StrAccum acc;
|
||||
if( n<=0 ) return zBuf;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( zBuf==0 || zFormat==0 ) {
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
if( zBuf && n>0 ) zBuf[0] = 0;
|
||||
return zBuf;
|
||||
}
|
||||
#endif
|
||||
sqlite3StrAccumInit(&acc, zBuf, n, 0);
|
||||
acc.useMalloc = 0;
|
||||
sqlite3VXPrintf(&acc, 0, zFormat, ap);
|
||||
|
||||
+4
-12
@@ -48,19 +48,11 @@ void sqlite3_randomness(int N, void *pBuf){
|
||||
#endif
|
||||
|
||||
#if SQLITE_THREADSAFE
|
||||
sqlite3_mutex *mutex;
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
if( sqlite3_initialize() ) return;
|
||||
#endif
|
||||
|
||||
#if SQLITE_THREADSAFE
|
||||
mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
|
||||
#endif
|
||||
|
||||
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
|
||||
sqlite3_mutex_enter(mutex);
|
||||
if( N<=0 || pBuf==0 ){
|
||||
#endif
|
||||
|
||||
if( N<=0 ){
|
||||
wsdPrng.isInit = 0;
|
||||
sqlite3_mutex_leave(mutex);
|
||||
return;
|
||||
|
||||
+4
-4
@@ -28,7 +28,7 @@
|
||||
** is a helper function - a callback for the tree walker.
|
||||
*/
|
||||
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
|
||||
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
|
||||
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.i;
|
||||
return WRC_Continue;
|
||||
}
|
||||
static void incrAggFunctionDepth(Expr *pExpr, int N){
|
||||
@@ -36,7 +36,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = incrAggDepth;
|
||||
w.u.n = N;
|
||||
w.u.i = N;
|
||||
sqlite3WalkExpr(&w, pExpr);
|
||||
}
|
||||
}
|
||||
@@ -584,7 +584,7 @@ static int exprProbability(Expr *p){
|
||||
sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
|
||||
assert( r>=0.0 );
|
||||
if( r>1.0 ) return -1;
|
||||
return (int)(r*134217728.0);
|
||||
return (int)(r*1000.0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -716,7 +716,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
|
||||
** likelihood(X,0.9375). */
|
||||
/* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
|
||||
pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120;
|
||||
pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
|
||||
+32
-132
@@ -172,8 +172,7 @@ static HANDLE hProcess;
|
||||
static FILETIME ftKernelBegin;
|
||||
static FILETIME ftUserBegin;
|
||||
static sqlite3_int64 ftWallBegin;
|
||||
typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
|
||||
LPFILETIME, LPFILETIME);
|
||||
typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
|
||||
static GETPROCTIMES getProcessTimesAddr = NULL;
|
||||
|
||||
/*
|
||||
@@ -184,16 +183,15 @@ static int hasTimer(void){
|
||||
if( getProcessTimesAddr ){
|
||||
return 1;
|
||||
} else {
|
||||
/* GetProcessTimes() isn't supported in WIN95 and some other Windows
|
||||
** versions. See if the version we are running on has it, and if it
|
||||
** does, save off a pointer to it and the current process handle.
|
||||
/* GetProcessTimes() isn't supported in WIN95 and some other Windows versions.
|
||||
** See if the version we are running on has it, and if it does, save off
|
||||
** a pointer to it and the current process handle.
|
||||
*/
|
||||
hProcess = GetCurrentProcess();
|
||||
if( hProcess ){
|
||||
HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
|
||||
if( NULL != hinstLib ){
|
||||
getProcessTimesAddr =
|
||||
(GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
|
||||
getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
|
||||
if( NULL != getProcessTimesAddr ){
|
||||
return 1;
|
||||
}
|
||||
@@ -210,8 +208,7 @@ static int hasTimer(void){
|
||||
static void beginTimer(void){
|
||||
if( enableTimer && getProcessTimesAddr ){
|
||||
FILETIME ftCreation, ftExit;
|
||||
getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
|
||||
&ftKernelBegin,&ftUserBegin);
|
||||
getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelBegin, &ftUserBegin);
|
||||
ftWallBegin = timeOfDay();
|
||||
}
|
||||
}
|
||||
@@ -230,7 +227,7 @@ static void endTimer(void){
|
||||
if( enableTimer && getProcessTimesAddr){
|
||||
FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
|
||||
sqlite3_int64 ftWallEnd = timeOfDay();
|
||||
getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
|
||||
getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd);
|
||||
printf("Run Time: real %.3f user %f sys %f\n",
|
||||
(ftWallEnd - ftWallBegin)*0.001,
|
||||
timeDiff(&ftUserBegin, &ftUserEnd),
|
||||
@@ -460,7 +457,6 @@ struct ShellState {
|
||||
int echoOn; /* True to echo input commands */
|
||||
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
|
||||
int statsOn; /* True to display memory stats before each finalize */
|
||||
int scanstatsOn; /* True to display scan stats before each finalize */
|
||||
int outCount; /* Revert to stdout when reaching zero */
|
||||
int cnt; /* Number of records displayed so far */
|
||||
FILE *out; /* Write results here */
|
||||
@@ -729,13 +725,7 @@ static void interrupt_handler(int NotUsed){
|
||||
** This is the callback routine that the shell
|
||||
** invokes for each row of a query result.
|
||||
*/
|
||||
static int shell_callback(
|
||||
void *pArg,
|
||||
int nArg, /* Number of result columns */
|
||||
char **azArg, /* Text of each result column */
|
||||
char **azCol, /* Column names */
|
||||
int *aiType /* Column types */
|
||||
){
|
||||
static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){
|
||||
int i;
|
||||
ShellState *p = (ShellState*)pArg;
|
||||
|
||||
@@ -1114,77 +1104,57 @@ static int display_stats(
|
||||
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out,
|
||||
"Memory Used: %d (max %d) bytes\n",
|
||||
iCur, iHiwtr);
|
||||
fprintf(pArg->out, "Memory Used: %d (max %d) bytes\n", iCur, iHiwtr);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n",
|
||||
iCur, iHiwtr);
|
||||
fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr);
|
||||
if( pArg->shellFlgs & SHFLG_Pagecache ){
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out,
|
||||
"Number of Pcache Pages Used: %d (max %d) pages\n",
|
||||
iCur, iHiwtr);
|
||||
fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr);
|
||||
}
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out,
|
||||
"Number of Pcache Overflow Bytes: %d (max %d) bytes\n",
|
||||
iCur, iHiwtr);
|
||||
fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr);
|
||||
if( pArg->shellFlgs & SHFLG_Scratch ){
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n",
|
||||
iCur, iHiwtr);
|
||||
fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr);
|
||||
}
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out,
|
||||
"Number of Scratch Overflow Bytes: %d (max %d) bytes\n",
|
||||
iCur, iHiwtr);
|
||||
fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Largest Allocation: %d bytes\n",
|
||||
iHiwtr);
|
||||
fprintf(pArg->out, "Largest Allocation: %d bytes\n", iHiwtr);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n",
|
||||
iHiwtr);
|
||||
fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n", iHiwtr);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n",
|
||||
iHiwtr);
|
||||
fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n", iHiwtr);
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n",
|
||||
iCur, iHiwtr);
|
||||
fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", iCur, iHiwtr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if( pArg && pArg->out && db ){
|
||||
if( pArg->shellFlgs & SHFLG_Lookaside ){
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
|
||||
&iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n",
|
||||
iCur, iHiwtr);
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
|
||||
&iCur, &iHiwtr, bReset);
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr);
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr);
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
|
||||
&iCur, &iHiwtr, bReset);
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr);
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
|
||||
&iCur, &iHiwtr, bReset);
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr);
|
||||
}
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Pager Heap Usage: %d bytes\n",iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
|
||||
fprintf(pArg->out, "Page cache hits: %d\n", iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
@@ -1195,19 +1165,18 @@ static int display_stats(
|
||||
fprintf(pArg->out, "Page cache writes: %d\n", iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Schema Heap Usage: %d bytes\n",iCur);
|
||||
fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur);
|
||||
iHiwtr = iCur = -1;
|
||||
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
|
||||
fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",iCur);
|
||||
fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur);
|
||||
}
|
||||
|
||||
if( pArg && pArg->out && db && pArg->pStmt ){
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
|
||||
bReset);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset);
|
||||
fprintf(pArg->out, "Fullscan Steps: %d\n", iCur);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
|
||||
fprintf(pArg->out, "Sort Operations: %d\n", iCur);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset);
|
||||
fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur);
|
||||
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
|
||||
fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
|
||||
@@ -1216,51 +1185,6 @@ static int display_stats(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Display scan stats.
|
||||
*/
|
||||
static void display_scanstats(
|
||||
sqlite3 *db, /* Database to query */
|
||||
ShellState *pArg /* Pointer to ShellState */
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
int i, k, n, mx;
|
||||
fprintf(pArg->out, "-------- scanstats --------\n");
|
||||
mx = 0;
|
||||
for(k=0; k<=mx; k++){
|
||||
double rEstLoop = 1.0;
|
||||
for(i=n=0; 1; i++){
|
||||
sqlite3_stmt *p = pArg->pStmt;
|
||||
sqlite3_int64 nLoop, nVisit;
|
||||
double rEst;
|
||||
int iSid;
|
||||
const char *zExplain;
|
||||
if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
|
||||
break;
|
||||
}
|
||||
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
|
||||
if( iSid>mx ) mx = iSid;
|
||||
if( iSid!=k ) continue;
|
||||
if( n==0 ){
|
||||
rEstLoop = (double)nLoop;
|
||||
if( k>0 ) fprintf(pArg->out, "-------- subquery %d -------\n", k);
|
||||
}
|
||||
n++;
|
||||
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
|
||||
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
|
||||
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
|
||||
fprintf(pArg->out, "Loop %2d: %s\n", n, zExplain);
|
||||
rEstLoop *= rEst;
|
||||
fprintf(pArg->out,
|
||||
" nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
|
||||
nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
|
||||
);
|
||||
}
|
||||
}
|
||||
fprintf(pArg->out, "---------------------------\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Parameter azArray points to a zero-terminated array of strings. zStr
|
||||
** points to a single nul-terminated string. Return non-zero if zStr
|
||||
@@ -1302,8 +1226,7 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
|
||||
|
||||
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
|
||||
"NextIfOpen", "PrevIfOpen", 0 };
|
||||
const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
|
||||
"Rewind", 0 };
|
||||
const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", "Rewind", 0 };
|
||||
const char *azGoto[] = { "Goto", 0 };
|
||||
|
||||
/* Try to figure out if this is really an EXPLAIN statement. If this
|
||||
@@ -1416,8 +1339,7 @@ static int shell_exec(
|
||||
/* 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));
|
||||
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 ){
|
||||
@@ -1501,11 +1423,6 @@ static int shell_exec(
|
||||
display_stats(db, pArg, 0);
|
||||
}
|
||||
|
||||
/* print loop-counters if required */
|
||||
if( pArg && pArg->scanstatsOn ){
|
||||
display_scanstats(db, pArg);
|
||||
}
|
||||
|
||||
/* Finalize the statement just executed. If this fails, save a
|
||||
** copy of the error message. Otherwise, set zSql to point to the
|
||||
** next statement to execute. */
|
||||
@@ -1716,7 +1633,6 @@ static char zHelp[] =
|
||||
".read FILENAME Execute SQL in FILENAME\n"
|
||||
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
|
||||
".save FILE Write in-memory database into FILE\n"
|
||||
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
|
||||
".schema ?TABLE? Show the CREATE statements\n"
|
||||
" If TABLE specified, only show tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
@@ -3098,19 +3014,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_close(pSrc);
|
||||
}else
|
||||
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->scanstatsOn = booleanValue(azArg[1]);
|
||||
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
fprintf(stderr, "Warning: .scanstats not available in this build.\n");
|
||||
#endif
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .scanstats on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
|
||||
ShellState data;
|
||||
char *zErrMsg = 0;
|
||||
@@ -3368,7 +3271,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
for(i=0; i<nPrintRow; i++){
|
||||
for(j=i; j<nRow; j+=nPrintRow){
|
||||
char *zSp = j<nPrintRow ? "" : " ";
|
||||
fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
|
||||
fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
|
||||
}
|
||||
fprintf(p->out, "\n");
|
||||
}
|
||||
@@ -3838,8 +3741,7 @@ static char *find_home_dir(void){
|
||||
static char *home_dir = NULL;
|
||||
if( home_dir ) return home_dir;
|
||||
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
|
||||
&& !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
{
|
||||
struct passwd *pwent;
|
||||
uid_t uid = getuid();
|
||||
@@ -4238,8 +4140,6 @@ int main(int argc, char **argv){
|
||||
data.autoEQP = 1;
|
||||
}else if( strcmp(z,"-stats")==0 ){
|
||||
data.statsOn = 1;
|
||||
}else if( strcmp(z,"-scanstats")==0 ){
|
||||
data.scanstatsOn = 1;
|
||||
}else if( strcmp(z,"-bail")==0 ){
|
||||
bail_on_error = 1;
|
||||
}else if( strcmp(z,"-version")==0 ){
|
||||
|
||||
+173
-303
@@ -52,7 +52,7 @@ extern "C" {
|
||||
/*
|
||||
** These no-op macros are used in front of interfaces to mark those
|
||||
** interfaces as either deprecated or experimental. New applications
|
||||
** should not use deprecated interfaces - they are supported for backwards
|
||||
** should not use deprecated interfaces - they are support for backwards
|
||||
** compatibility only. Application writers should be aware that
|
||||
** experimental interfaces are subject to change in point releases.
|
||||
**
|
||||
@@ -1499,27 +1499,25 @@ struct sqlite3_mem_methods {
|
||||
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
|
||||
** <dd> ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is
|
||||
** a pointer to an instance of the [sqlite3_mem_methods] structure.
|
||||
** The argument specifies
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** instance of the [sqlite3_mem_methods] structure. The argument specifies
|
||||
** alternative low-level memory allocation routines to be used in place of
|
||||
** the memory allocation routines built into SQLite.)^ ^SQLite makes
|
||||
** its own private copy of the content of the [sqlite3_mem_methods] structure
|
||||
** before the [sqlite3_config()] call returns.</dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
|
||||
** <dd> ^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which
|
||||
** is a pointer to an instance of the [sqlite3_mem_methods] structure.
|
||||
** The [sqlite3_mem_methods]
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
|
||||
** structure is filled with the currently defined memory allocation routines.)^
|
||||
** This option can be used to overload the default memory allocation
|
||||
** routines with a wrapper that simulations memory allocation failure or
|
||||
** tracks memory usage, for example. </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
|
||||
** interpreted as a boolean, which enables or disables the collection of
|
||||
** memory allocation statistics. ^(When memory allocation statistics are disabled, the
|
||||
** <dd> ^This option takes single argument of type int, interpreted as a
|
||||
** boolean, which enables or disables the collection of memory allocation
|
||||
** statistics. ^(When memory allocation statistics are disabled, the
|
||||
** following SQLite interfaces become non-operational:
|
||||
** <ul>
|
||||
** <li> [sqlite3_memory_used()]
|
||||
@@ -1533,65 +1531,53 @@ struct sqlite3_mem_methods {
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer
|
||||
** that SQLite can use for scratch memory. ^(There are three arguments
|
||||
** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte
|
||||
** <dd> ^This option specifies a static memory buffer that SQLite can use for
|
||||
** scratch memory. There are three arguments: A pointer an 8-byte
|
||||
** aligned memory buffer from which the scratch allocations will be
|
||||
** drawn, the size of each scratch allocation (sz),
|
||||
** and the maximum number of scratch allocations (N).)^
|
||||
** and the maximum number of scratch allocations (N). The sz
|
||||
** argument must be a multiple of 16.
|
||||
** The first argument must be a pointer to an 8-byte aligned buffer
|
||||
** of at least sz*N bytes of memory.
|
||||
** ^SQLite will not use more than one scratch buffers per thread.
|
||||
** ^SQLite will never request a scratch buffer that is more than 6
|
||||
** times the database page size.
|
||||
** ^If SQLite needs needs additional
|
||||
** ^SQLite will use no more than two scratch buffers per thread. So
|
||||
** N should be set to twice the expected maximum number of threads.
|
||||
** ^SQLite will never require a scratch buffer that is more than 6
|
||||
** times the database page size. ^If SQLite needs needs additional
|
||||
** scratch memory beyond what is provided by this configuration option, then
|
||||
** [sqlite3_malloc()] will be used to obtain the memory needed.<p>
|
||||
** ^When the application provides any amount of scratch memory using
|
||||
** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large
|
||||
** [sqlite3_malloc|heap allocations].
|
||||
** This can help [Robson proof|prevent memory allocation failures] due to heap
|
||||
** fragmentation in low-memory embedded systems.
|
||||
** </dd>
|
||||
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer
|
||||
** that SQLite can use for the database page cache with the default page
|
||||
** cache implementation.
|
||||
** <dd> ^This option specifies a static memory buffer that SQLite can use for
|
||||
** the database page cache with the default page cache implementation.
|
||||
** This configuration should not be used if an application-define page
|
||||
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]
|
||||
** configuration option.
|
||||
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned
|
||||
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option.
|
||||
** There are three arguments to this option: A pointer to 8-byte aligned
|
||||
** memory, the size of each page buffer (sz), and the number of pages (N).
|
||||
** The sz argument should be the size of the largest database page
|
||||
** (a power of two between 512 and 32768) plus some extra bytes for each
|
||||
** page header. ^The number of extra bytes needed by the page header
|
||||
** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option
|
||||
** to [sqlite3_config()].
|
||||
** ^It is harmless, apart from the wasted memory,
|
||||
** for the sz parameter to be larger than necessary. The first
|
||||
** argument should pointer to an 8-byte aligned block of memory that
|
||||
** is at least sz*N bytes of memory, otherwise subsequent behavior is
|
||||
** undefined.
|
||||
** (a power of two between 512 and 32768) plus a little extra for each
|
||||
** page header. ^The page header size is 20 to 40 bytes depending on
|
||||
** the host architecture. ^It is harmless, apart from the wasted memory,
|
||||
** to make sz a little too large. The first
|
||||
** argument should point to an allocation of at least sz*N bytes of memory.
|
||||
** ^SQLite will use the memory provided by the first argument to satisfy its
|
||||
** memory needs for the first N pages that it adds to cache. ^If additional
|
||||
** page cache memory is needed beyond what is provided by this option, then
|
||||
** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd>
|
||||
** SQLite goes to [sqlite3_malloc()] for the additional storage space.
|
||||
** The pointer in the first argument must
|
||||
** be aligned to an 8-byte boundary or subsequent behavior of SQLite
|
||||
** will be undefined.</dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
|
||||
** that SQLite will use for all of its dynamic memory allocation needs
|
||||
** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
|
||||
** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled
|
||||
** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns
|
||||
** [SQLITE_ERROR] if invoked otherwise.
|
||||
** ^There are three arguments to SQLITE_CONFIG_HEAP:
|
||||
** An 8-byte aligned pointer to the memory,
|
||||
** <dd> ^This option specifies a static memory buffer that SQLite will use
|
||||
** for all of its dynamic memory allocation needs beyond those provided
|
||||
** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
|
||||
** There are three arguments: An 8-byte aligned pointer to the memory,
|
||||
** the number of bytes in the memory buffer, and the minimum allocation size.
|
||||
** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts
|
||||
** to using its default memory allocator (the system malloc() implementation),
|
||||
** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the
|
||||
** memory pointer is not NULL then the alternative memory
|
||||
** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or
|
||||
** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory
|
||||
** allocator is engaged to handle all of SQLites memory allocation needs.
|
||||
** The first pointer (the memory pointer) must be aligned to an 8-byte
|
||||
** boundary or subsequent behavior of SQLite will be undefined.
|
||||
@@ -1599,9 +1585,9 @@ struct sqlite3_mem_methods {
|
||||
** for the minimum allocation size are 2**5 through 2**8.</dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
|
||||
** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a
|
||||
** pointer to an instance of the [sqlite3_mutex_methods] structure.
|
||||
** The argument specifies alternative low-level mutex routines to be used in place
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** instance of the [sqlite3_mutex_methods] structure. The argument specifies
|
||||
** alternative low-level mutex routines to be used in place
|
||||
** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the
|
||||
** content of the [sqlite3_mutex_methods] structure before the call to
|
||||
** [sqlite3_config()] returns. ^If SQLite is compiled with
|
||||
@@ -1611,8 +1597,8 @@ struct sqlite3_mem_methods {
|
||||
** return [SQLITE_ERROR].</dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
|
||||
** <dd> ^(The SQLITE_CONFIG_GETMUTEX option takes a single argument which
|
||||
** is a pointer to an instance of the [sqlite3_mutex_methods] structure. The
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** instance of the [sqlite3_mutex_methods] structure. The
|
||||
** [sqlite3_mutex_methods]
|
||||
** structure is filled with the currently defined mutex routines.)^
|
||||
** This option can be used to overload the default mutex allocation
|
||||
@@ -1624,24 +1610,24 @@ struct sqlite3_mem_methods {
|
||||
** return [SQLITE_ERROR].</dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
|
||||
** <dd> ^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine
|
||||
** the default size of lookaside memory on each [database connection].
|
||||
** The first argument is the
|
||||
** <dd> ^(This option takes two arguments that determine the default
|
||||
** memory allocation for the lookaside memory allocator on each
|
||||
** [database connection]. The first argument is the
|
||||
** size of each lookaside buffer slot and the second is the number of
|
||||
** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE
|
||||
** sets the <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
|
||||
** option to [sqlite3_db_config()] can be used to change the lookaside
|
||||
** slots allocated to each database connection.)^ ^(This option sets the
|
||||
** <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
|
||||
** verb to [sqlite3_db_config()] can be used to change the lookaside
|
||||
** configuration on individual connections.)^ </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
|
||||
** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is
|
||||
** a pointer to an [sqlite3_pcache_methods2] object. This object specifies
|
||||
** the interface to a custom page cache implementation.)^
|
||||
** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd>
|
||||
** <dd> ^(This option takes a single argument which is a pointer to
|
||||
** an [sqlite3_pcache_methods2] object. This object specifies the interface
|
||||
** to a custom page cache implementation.)^ ^SQLite makes a copy of the
|
||||
** object and uses it for page cache memory allocations.</dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
|
||||
** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which
|
||||
** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of the current
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** [sqlite3_pcache_methods2] object. SQLite copies of the current
|
||||
** page cache implementation into that object.)^ </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
|
||||
@@ -1665,10 +1651,10 @@ struct sqlite3_mem_methods {
|
||||
** function must be threadsafe. </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
|
||||
** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int.
|
||||
** If non-zero, then URI handling is globally enabled. If the parameter is zero,
|
||||
** then URI handling is globally disabled.)^ ^If URI handling is globally enabled,
|
||||
** all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
|
||||
** <dd>^(This option takes a single argument of type int. If non-zero, then
|
||||
** URI handling is globally enabled. If the parameter is zero, then URI handling
|
||||
** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
|
||||
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
|
||||
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
|
||||
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
|
||||
** connection is opened. ^If it is globally disabled, filenames are
|
||||
@@ -1678,10 +1664,9 @@ struct sqlite3_mem_methods {
|
||||
** [SQLITE_USE_URI] symbol defined.)^
|
||||
**
|
||||
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
|
||||
** <dd>^The SQLITE_CONFIG_COVERING_INDEX_SCAN option takes a single integer
|
||||
** argument which is interpreted as a boolean in order to enable or disable
|
||||
** the use of covering indices for full table scans in the query optimizer.
|
||||
** ^The default setting is determined
|
||||
** <dd>^This option takes a single integer argument which is interpreted as
|
||||
** a boolean in order to enable or disable the use of covering indices for
|
||||
** full table scans in the query optimizer. ^The default setting is determined
|
||||
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
|
||||
** if that compile-time option is omitted.
|
||||
** The ability to disable the use of covering indices for full table scans
|
||||
@@ -1721,28 +1706,19 @@ struct sqlite3_mem_methods {
|
||||
** ^The default setting can be overridden by each database connection using
|
||||
** either the [PRAGMA mmap_size] command, or by using the
|
||||
** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
|
||||
** will be silently truncated if necessary so that it does not exceed the
|
||||
** compile-time maximum mmap size set by the
|
||||
** cannot be changed at run-time. Nor may the maximum allowed mmap size
|
||||
** exceed the compile-time maximum mmap size set by the
|
||||
** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
|
||||
** ^If either argument to this option is negative, then that argument is
|
||||
** changed to its compile-time default.
|
||||
**
|
||||
** [[SQLITE_CONFIG_WIN32_HEAPSIZE]]
|
||||
** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
|
||||
** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
|
||||
** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro defined.
|
||||
** ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
|
||||
** <dd>^This option is only available if SQLite is compiled for Windows
|
||||
** with the [SQLITE_WIN32_MALLOC] pre-processor macro defined.
|
||||
** SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
|
||||
** that specifies the maximum size of the created heap.
|
||||
** </dl>
|
||||
**
|
||||
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
|
||||
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
|
||||
** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
|
||||
** is a pointer to an integer and writes into that integer the number of extra
|
||||
** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. The amount of
|
||||
** extra space required can change depending on the compiler,
|
||||
** target platform, and SQLite version.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
|
||||
@@ -1767,7 +1743,6 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
|
||||
#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
|
||||
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
|
||||
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@@ -1895,45 +1870,47 @@ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
|
||||
/*
|
||||
** CAPI3REF: Count The Number Of Rows Modified
|
||||
**
|
||||
** ^This function returns the number of rows modified, inserted or
|
||||
** deleted by the most recently completed INSERT, UPDATE or DELETE
|
||||
** statement on the database connection specified by the only parameter.
|
||||
** ^Executing any other type of SQL statement does not modify the value
|
||||
** returned by this function.
|
||||
** ^This function returns the number of database rows that were changed
|
||||
** or inserted or deleted by the most recently completed SQL statement
|
||||
** on the [database connection] specified by the first parameter.
|
||||
** ^(Only changes that are directly specified by the [INSERT], [UPDATE],
|
||||
** or [DELETE] statement are counted. Auxiliary changes caused by
|
||||
** triggers or [foreign key actions] are not counted.)^ Use the
|
||||
** [sqlite3_total_changes()] function to find the total number of changes
|
||||
** including changes caused by triggers and foreign key actions.
|
||||
**
|
||||
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
|
||||
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
|
||||
** [foreign key actions] or [REPLACE] constraint resolution are not counted.
|
||||
**
|
||||
** Changes to a view that are intercepted by
|
||||
** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value
|
||||
** returned by sqlite3_changes() immediately after an INSERT, UPDATE or
|
||||
** DELETE statement run on a view is always zero. Only changes made to real
|
||||
** tables are counted.
|
||||
** ^Changes to a view that are simulated by an [INSTEAD OF trigger]
|
||||
** are not counted. Only real table changes are counted.
|
||||
**
|
||||
** Things are more complicated if the sqlite3_changes() function is
|
||||
** executed while a trigger program is running. This may happen if the
|
||||
** program uses the [changes() SQL function], or if some other callback
|
||||
** function invokes sqlite3_changes() directly. Essentially:
|
||||
**
|
||||
** <ul>
|
||||
** <li> ^(Before entering a trigger program the value returned by
|
||||
** sqlite3_changes() function is saved. After the trigger program
|
||||
** has finished, the original value is restored.)^
|
||||
**
|
||||
** <li> ^(Within a trigger program each INSERT, UPDATE and DELETE
|
||||
** statement sets the value returned by sqlite3_changes()
|
||||
** upon completion as normal. Of course, this value will not include
|
||||
** any changes performed by sub-triggers, as the sqlite3_changes()
|
||||
** value will be saved and restored after each sub-trigger has run.)^
|
||||
** </ul>
|
||||
**
|
||||
** ^This means that if the changes() SQL function (or similar) is used
|
||||
** by the first INSERT, UPDATE or DELETE statement within a trigger, it
|
||||
** returns the value as set when the calling statement began executing.
|
||||
** ^If it is used by the second or subsequent such statement within a trigger
|
||||
** program, the value returned reflects the number of rows modified by the
|
||||
** previous INSERT, UPDATE or DELETE statement within the same trigger.
|
||||
** ^(A "row change" is a change to a single row of a single table
|
||||
** caused by an INSERT, DELETE, or UPDATE statement. Rows that
|
||||
** are changed as side effects of [REPLACE] constraint resolution,
|
||||
** rollback, ABORT processing, [DROP TABLE], or by any other
|
||||
** mechanisms do not count as direct row changes.)^
|
||||
**
|
||||
** A "trigger context" is a scope of execution that begins and
|
||||
** ends with the script of a [CREATE TRIGGER | trigger].
|
||||
** Most SQL statements are
|
||||
** evaluated outside of any trigger. This is the "top level"
|
||||
** trigger context. If a trigger fires from the top level, a
|
||||
** new trigger context is entered for the duration of that one
|
||||
** trigger. Subtriggers create subcontexts for their duration.
|
||||
**
|
||||
** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does
|
||||
** not create a new trigger context.
|
||||
**
|
||||
** ^This function returns the number of direct row changes in the
|
||||
** most recent INSERT, UPDATE, or DELETE statement within the same
|
||||
** trigger context.
|
||||
**
|
||||
** ^Thus, when called from the top level, this function returns the
|
||||
** number of changes in the most recent INSERT, UPDATE, or DELETE
|
||||
** that also occurred at the top level. ^(Within the body of a trigger,
|
||||
** the sqlite3_changes() interface can be called to find the number of
|
||||
** changes in the most recently completed INSERT, UPDATE, or DELETE
|
||||
** statement within the body of the same trigger.
|
||||
** However, the number returned does not include changes
|
||||
** caused by subtriggers since those have their own context.)^
|
||||
**
|
||||
** See also the [sqlite3_total_changes()] interface, the
|
||||
** [count_changes pragma], and the [changes() SQL function].
|
||||
@@ -1947,17 +1924,20 @@ int sqlite3_changes(sqlite3*);
|
||||
/*
|
||||
** CAPI3REF: Total Number Of Rows Modified
|
||||
**
|
||||
** ^This function returns the total number of rows inserted, modified or
|
||||
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
|
||||
** since the database connection was opened, including those executed as
|
||||
** part of trigger programs. ^Executing any other type of SQL statement
|
||||
** does not affect the value returned by sqlite3_total_changes().
|
||||
**
|
||||
** ^Changes made as part of [foreign key actions] are included in the
|
||||
** count, but those made as part of REPLACE constraint resolution are
|
||||
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
|
||||
** are not counted.
|
||||
**
|
||||
** ^This function returns the number of row changes caused by [INSERT],
|
||||
** [UPDATE] or [DELETE] statements since the [database connection] was opened.
|
||||
** ^(The count returned by sqlite3_total_changes() includes all changes
|
||||
** from all [CREATE TRIGGER | trigger] contexts and changes made by
|
||||
** [foreign key actions]. However,
|
||||
** the count does not include changes used to implement [REPLACE] constraints,
|
||||
** do rollbacks or ABORT processing, or [DROP TABLE] processing. The
|
||||
** count does not include rows of views that fire an [INSTEAD OF trigger],
|
||||
** though if the INSTEAD OF trigger makes changes of its own, those changes
|
||||
** are counted.)^
|
||||
** ^The sqlite3_total_changes() function counts the changes as soon as
|
||||
** the statement that makes them is completed (when the statement handle
|
||||
** is passed to [sqlite3_reset()] or [sqlite3_finalize()]).
|
||||
**
|
||||
** See also the [sqlite3_changes()] interface, the
|
||||
** [count_changes pragma], and the [total_changes() SQL function].
|
||||
**
|
||||
@@ -2435,14 +2415,13 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
|
||||
** applications to access the same PRNG for other purposes.
|
||||
**
|
||||
** ^A call to this routine stores N bytes of randomness into buffer P.
|
||||
** ^The P parameter can be a NULL pointer.
|
||||
** ^If N is less than one, then P can be a NULL pointer.
|
||||
**
|
||||
** ^If this routine has not been previously called or if the previous
|
||||
** call had N less than one or a NULL pointer for P, then the PRNG is
|
||||
** seeded using randomness obtained from the xRandomness method of
|
||||
** the default [sqlite3_vfs] object.
|
||||
** ^If the previous call to this routine had an N of 1 or more and a
|
||||
** non-NULL P then the pseudo-randomness is generated
|
||||
** call had N less than one, then the PRNG is seeded using randomness
|
||||
** obtained from the xRandomness method of the default [sqlite3_vfs] object.
|
||||
** ^If the previous call to this routine had an N of 1 or more then
|
||||
** the pseudo-randomness is generated
|
||||
** internally and without recourse to the [sqlite3_vfs] xRandomness
|
||||
** method.
|
||||
*/
|
||||
@@ -5657,42 +5636,26 @@ typedef struct sqlite3_blob sqlite3_blob;
|
||||
** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
|
||||
** </pre>)^
|
||||
**
|
||||
** ^(Parameter zDb is not the filename that contains the database, but
|
||||
** rather the symbolic name of the database. For attached databases, this is
|
||||
** the name that appears after the AS keyword in the [ATTACH] statement.
|
||||
** For the main database file, the database name is "main". For TEMP
|
||||
** tables, the database name is "temp".)^
|
||||
**
|
||||
** ^If the flags parameter is non-zero, then the BLOB is opened for read
|
||||
** and write access. ^If the flags parameter is zero, the BLOB is opened for
|
||||
** read-only access.
|
||||
** and write access. ^If it is zero, the BLOB is opened for read access.
|
||||
** ^It is not possible to open a column that is part of an index or primary
|
||||
** key for writing. ^If [foreign key constraints] are enabled, it is
|
||||
** not possible to open a column that is part of a [child key] for writing.
|
||||
**
|
||||
** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored
|
||||
** in *ppBlob. Otherwise an [error code] is returned and, unless the error
|
||||
** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided
|
||||
** the API is not misused, it is always safe to call [sqlite3_blob_close()]
|
||||
** on *ppBlob after this function it returns.
|
||||
**
|
||||
** This function fails with SQLITE_ERROR if any of the following are true:
|
||||
** <ul>
|
||||
** <li> ^(Database zDb does not exist)^,
|
||||
** <li> ^(Table zTable does not exist within database zDb)^,
|
||||
** <li> ^(Table zTable is a WITHOUT ROWID table)^,
|
||||
** <li> ^(Column zColumn does not exist)^,
|
||||
** <li> ^(Row iRow is not present in the table)^,
|
||||
** <li> ^(The specified column of row iRow contains a value that is not
|
||||
** a TEXT or BLOB value)^,
|
||||
** <li> ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE
|
||||
** constraint and the blob is being opened for read/write access)^,
|
||||
** <li> ^([foreign key constraints | Foreign key constraints] are enabled,
|
||||
** column zColumn is part of a [child key] definition and the blob is
|
||||
** being opened for read/write access)^.
|
||||
** </ul>
|
||||
**
|
||||
** ^Unless it returns SQLITE_MISUSE, this function sets the
|
||||
** [database connection] error code and message accessible via
|
||||
** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
|
||||
** ^Note that the database name is not the filename that contains
|
||||
** the database but rather the symbolic name of the database that
|
||||
** appears after the AS keyword when the database is connected using [ATTACH].
|
||||
** ^For the main database file, the database name is "main".
|
||||
** ^For TEMP tables, the database name is "temp".
|
||||
**
|
||||
** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written
|
||||
** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set
|
||||
** to be a null pointer.)^
|
||||
** ^This function sets the [database connection] error code and message
|
||||
** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related
|
||||
** functions. ^Note that the *ppBlob variable is always initialized in a
|
||||
** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob
|
||||
** regardless of the success or failure of this routine.
|
||||
**
|
||||
** ^(If the row that a BLOB handle points to is modified by an
|
||||
** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
|
||||
@@ -5710,9 +5673,13 @@ typedef struct sqlite3_blob sqlite3_blob;
|
||||
** interface. Use the [UPDATE] SQL command to change the size of a
|
||||
** blob.
|
||||
**
|
||||
** ^The [sqlite3_blob_open()] interface will fail for a [WITHOUT ROWID]
|
||||
** table. Incremental BLOB I/O is not possible on [WITHOUT ROWID] tables.
|
||||
**
|
||||
** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
|
||||
** and the built-in [zeroblob] SQL function may be used to create a
|
||||
** zero-filled blob to read or write using the incremental-blob interface.
|
||||
** and the built-in [zeroblob] SQL function can be used, if desired,
|
||||
** to create an empty, zero-filled blob in which to read or write using
|
||||
** this interface.
|
||||
**
|
||||
** To avoid a resource leak, every open [BLOB handle] should eventually
|
||||
** be released by a call to [sqlite3_blob_close()].
|
||||
@@ -5754,22 +5721,24 @@ SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
|
||||
/*
|
||||
** CAPI3REF: Close A BLOB Handle
|
||||
**
|
||||
** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed
|
||||
** unconditionally. Even if this routine returns an error code, the
|
||||
** handle is still closed.)^
|
||||
** ^Closes an open [BLOB handle].
|
||||
**
|
||||
** ^If the blob handle being closed was opened for read-write access, and if
|
||||
** the database is in auto-commit mode and there are no other open read-write
|
||||
** blob handles or active write statements, the current transaction is
|
||||
** committed. ^If an error occurs while committing the transaction, an error
|
||||
** code is returned and the transaction rolled back.
|
||||
** ^Closing a BLOB shall cause the current transaction to commit
|
||||
** if there are no other BLOBs, no pending prepared statements, and the
|
||||
** database connection is in [autocommit mode].
|
||||
** ^If any writes were made to the BLOB, they might be held in cache
|
||||
** until the close operation if they will fit.
|
||||
**
|
||||
** Calling this function with an argument that is not a NULL pointer or an
|
||||
** open blob handle results in undefined behaviour. ^Calling this routine
|
||||
** with a null pointer (such as would be returned by a failed call to
|
||||
** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function
|
||||
** is passed a valid open blob handle, the values returned by the
|
||||
** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
|
||||
** ^(Closing the BLOB often forces the changes
|
||||
** out to disk and so if any I/O errors occur, they will likely occur
|
||||
** at the time when the BLOB is closed. Any errors that occur during
|
||||
** closing are reported as a non-zero return value.)^
|
||||
**
|
||||
** ^(The BLOB is closed unconditionally. Even if this routine returns
|
||||
** an error code, the BLOB is still closed.)^
|
||||
**
|
||||
** ^Calling this routine with a null pointer (such as would be returned
|
||||
** by a failed call to [sqlite3_blob_open()]) is a harmless no-op.
|
||||
*/
|
||||
int sqlite3_blob_close(sqlite3_blob *);
|
||||
|
||||
@@ -5819,27 +5788,21 @@ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
|
||||
/*
|
||||
** CAPI3REF: Write Data Into A BLOB Incrementally
|
||||
**
|
||||
** ^(This function is used to write data into an open [BLOB handle] from a
|
||||
** caller-supplied buffer. N bytes of data are copied from the buffer Z
|
||||
** into the open BLOB, starting at offset iOffset.)^
|
||||
**
|
||||
** ^(On success, sqlite3_blob_write() returns SQLITE_OK.
|
||||
** Otherwise, an [error code] or an [extended error code] is returned.)^
|
||||
** ^Unless SQLITE_MISUSE is returned, this function sets the
|
||||
** [database connection] error code and message accessible via
|
||||
** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
|
||||
** ^This function is used to write data into an open [BLOB handle] from a
|
||||
** caller-supplied buffer. ^N bytes of data are copied from the buffer Z
|
||||
** into the open BLOB, starting at offset iOffset.
|
||||
**
|
||||
** ^If the [BLOB handle] passed as the first argument was not opened for
|
||||
** writing (the flags parameter to [sqlite3_blob_open()] was zero),
|
||||
** this function returns [SQLITE_READONLY].
|
||||
**
|
||||
** This function may only modify the contents of the BLOB; it is
|
||||
** ^This function may only modify the contents of the BLOB; it is
|
||||
** not possible to increase the size of a BLOB using this API.
|
||||
** ^If offset iOffset is less than N bytes from the end of the BLOB,
|
||||
** [SQLITE_ERROR] is returned and no data is written. The size of the
|
||||
** BLOB (and hence the maximum value of N+iOffset) can be determined
|
||||
** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less
|
||||
** than zero [SQLITE_ERROR] is returned and no data is written.
|
||||
** [SQLITE_ERROR] is returned and no data is written. ^If N is
|
||||
** less than zero [SQLITE_ERROR] is returned and no data is written.
|
||||
** The size of the BLOB (and hence the maximum value of N+iOffset)
|
||||
** can be determined using the [sqlite3_blob_bytes()] interface.
|
||||
**
|
||||
** ^An attempt to write to an expired [BLOB handle] fails with an
|
||||
** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred
|
||||
@@ -5848,6 +5811,9 @@ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
|
||||
** have been overwritten by the statement that expired the BLOB handle
|
||||
** or by other independent statements.
|
||||
**
|
||||
** ^(On success, sqlite3_blob_write() returns SQLITE_OK.
|
||||
** Otherwise, an [error code] or an [extended error code] is returned.)^
|
||||
**
|
||||
** This routine only works on a [BLOB handle] which has been created
|
||||
** by a prior successful call to [sqlite3_blob_open()] and which has not
|
||||
** been closed by [sqlite3_blob_close()]. Passing any other pointer in
|
||||
@@ -6848,10 +6814,6 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** must be different or else sqlite3_backup_init(D,N,S,M) will fail with
|
||||
** an error.
|
||||
**
|
||||
** ^A call to sqlite3_backup_init() will fail, returning SQLITE_ERROR, if
|
||||
** there is already a read or read-write transaction open on the
|
||||
** destination database.
|
||||
**
|
||||
** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is
|
||||
** returned and an error code and error message are stored in the
|
||||
** destination [database connection] D.
|
||||
@@ -7444,98 +7406,6 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
/* #define SQLITE_ABORT 4 // Also an error code */
|
||||
#define SQLITE_REPLACE 5
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepared Statement Scan Status Opcodes
|
||||
** KEYWORDS: {scanstatus options}
|
||||
**
|
||||
** The following constants can be used for the T parameter to the
|
||||
** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a
|
||||
** different metric for sqlite3_stmt_scanstatus() to return.
|
||||
**
|
||||
** <dl>
|
||||
** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
|
||||
** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the
|
||||
** total number of times that the X-th loop has run.</dd>
|
||||
**
|
||||
** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt>
|
||||
** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the
|
||||
** total number of rows examined by all iterations of the X-th loop.</dd>
|
||||
**
|
||||
** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
|
||||
** <dd>^The "double" variable pointed to by the T parameter will be set to the
|
||||
** query planner's estimate for the average number of rows output from each
|
||||
** iteration of the X-th loop. If the query planner's estimates was accurate,
|
||||
** then this value will approximate the quotient NVISIT/NLOOP and the
|
||||
** product of this value for all prior loops with the same SELECTID will
|
||||
** be the NLOOP value for the current loop.
|
||||
**
|
||||
** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
|
||||
** <dd>^The "const char *" variable pointed to by the T parameter will be set to
|
||||
** a zero-terminated UTF-8 string containing the name of the index or table used
|
||||
** for the X-th loop.
|
||||
**
|
||||
** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
|
||||
** <dd>^The "const char *" variable pointed to by the T parameter will be set to
|
||||
** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description
|
||||
** for the X-th loop.
|
||||
**
|
||||
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt>
|
||||
** <dd>^The "int" variable pointed to by the T parameter will be set to the
|
||||
** "select-id" for the X-th loop. The select-id identifies which query or
|
||||
** subquery the loop is part of. The main query has a select-id of zero.
|
||||
** The select-id is the same value as is output in the first column
|
||||
** of an [EXPLAIN QUERY PLAN] query.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_SCANSTAT_NLOOP 0
|
||||
#define SQLITE_SCANSTAT_NVISIT 1
|
||||
#define SQLITE_SCANSTAT_EST 2
|
||||
#define SQLITE_SCANSTAT_NAME 3
|
||||
#define SQLITE_SCANSTAT_EXPLAIN 4
|
||||
#define SQLITE_SCANSTAT_SELECTID 5
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepared Statement Scan Status
|
||||
**
|
||||
** Return status data for a single loop within query pStmt.
|
||||
**
|
||||
** The "iScanStatusOp" parameter determines which status information to return.
|
||||
** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior of
|
||||
** this interface is undefined.
|
||||
** ^The requested measurement is written into a variable pointed to by
|
||||
** the "pOut" parameter.
|
||||
** Parameter "idx" identifies the specific loop to retrieve statistics for.
|
||||
** Loops are numbered starting from zero. ^If idx is out of range - less than
|
||||
** zero or greater than or equal to the total number of loops used to implement
|
||||
** the statement - a non-zero value is returned and the variable that pOut
|
||||
** points to is unchanged.
|
||||
**
|
||||
** ^Statistics might not be available for all loops in all statements. ^In cases
|
||||
** where there exist loops with no available statistics, this function behaves
|
||||
** as if the loop did not exist - it returns non-zero and leave the variable
|
||||
** that pOut points to unchanged.
|
||||
**
|
||||
** This API is only available if the library is built with pre-processor
|
||||
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
|
||||
**
|
||||
** See also: [sqlite3_stmt_scanstatus_reset()]
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
|
||||
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
|
||||
int idx, /* Index of loop to report on */
|
||||
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
|
||||
void *pOut /* Result written here */
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Zero Scan-Status Counters
|
||||
**
|
||||
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
|
||||
**
|
||||
** This API is only available if the library is built with pre-processor
|
||||
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
+9
-12
@@ -193,9 +193,10 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** EVIDENCE-OF: R-25715-37072 Memory allocation statistics are enabled by
|
||||
** default unless SQLite is compiled with SQLITE_DEFAULT_MEMSTATUS=0 in
|
||||
** which case memory allocation statistics are disabled by default.
|
||||
** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
|
||||
** It determines whether or not the features related to
|
||||
** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
|
||||
** be overridden at runtime using the sqlite3_config() API.
|
||||
*/
|
||||
#if !defined(SQLITE_DEFAULT_MEMSTATUS)
|
||||
# define SQLITE_DEFAULT_MEMSTATUS 1
|
||||
@@ -562,7 +563,7 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
|
||||
** gives a possible range of values of approximately 1.0e986 to 1e-986.
|
||||
** But the allowed values are "grainy". Not every value is representable.
|
||||
** For example, quantities 16 and 17 are both represented by a LogEst
|
||||
** of 40. However, since LogEst quantities are suppose to be estimates,
|
||||
** of 40. However, since LogEst quantaties are suppose to be estimates,
|
||||
** not exact values, this imprecision is not a problem.
|
||||
**
|
||||
** "LogEst" is short for "Logarithmic Estimate".
|
||||
@@ -1213,7 +1214,7 @@ struct sqlite3 {
|
||||
#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
|
||||
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
|
||||
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
|
||||
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
|
||||
#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */
|
||||
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
||||
|
||||
/*
|
||||
@@ -1795,7 +1796,6 @@ struct Index {
|
||||
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
|
||||
unsigned isResized:1; /* True if resizeIndexObject() has been called */
|
||||
unsigned isCovering:1; /* True if this is a covering index */
|
||||
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
int nSample; /* Number of elements in aSample[] */
|
||||
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
|
||||
@@ -2000,7 +2000,7 @@ struct Expr {
|
||||
int iTable; /* TK_COLUMN: cursor number of table holding column
|
||||
** TK_REGISTER: register number
|
||||
** TK_TRIGGER: 1 -> new, 0 -> old
|
||||
** EP_Unlikely: 134217728 times likelihood */
|
||||
** EP_Unlikely: 1000 times likelihood */
|
||||
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
|
||||
** TK_VARIABLE: variable number (always >= 1). */
|
||||
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
||||
@@ -2892,11 +2892,9 @@ struct Walker {
|
||||
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
|
||||
Parse *pParse; /* Parser context. */
|
||||
int walkerDepth; /* Number of subqueries */
|
||||
u8 eCode; /* A small processing code */
|
||||
union { /* Extra data for callback */
|
||||
NameContext *pNC; /* Naming context */
|
||||
int n; /* A counter */
|
||||
int iCur; /* A cursor number */
|
||||
int i; /* Integer value */
|
||||
SrcList *pSrcList; /* FROM clause */
|
||||
struct SrcCount *pSrcCount; /* Counting column references */
|
||||
} u;
|
||||
@@ -3297,7 +3295,6 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
||||
int sqlite3ExprIsConstant(Expr*);
|
||||
int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
||||
int sqlite3ExprIsTableConstant(Expr*,int);
|
||||
int sqlite3ExprIsInteger(Expr*, int*);
|
||||
int sqlite3ExprCanBeNull(const Expr*);
|
||||
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||
@@ -3543,7 +3540,7 @@ int sqlite3OpenTempDatabase(Parse *);
|
||||
void sqlite3StrAccumInit(StrAccum*, char*, int, int);
|
||||
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
|
||||
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
|
||||
void sqlite3AppendChar(StrAccum*,int,char);
|
||||
void sqlite3AppendSpace(StrAccum*,int);
|
||||
char *sqlite3StrAccumFinish(StrAccum*);
|
||||
void sqlite3StrAccumReset(StrAccum*);
|
||||
void sqlite3SelectDestInit(SelectDest*,int,int);
|
||||
|
||||
@@ -86,9 +86,6 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
*pCurrent = wsdStat.nowValue[op];
|
||||
*pHighwater = wsdStat.mxValue[op];
|
||||
if( resetFlag ){
|
||||
@@ -108,11 +105,6 @@ int sqlite3_db_status(
|
||||
int resetFlag /* Reset high-water mark if true */
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
switch( op ){
|
||||
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
|
||||
|
||||
@@ -126,9 +126,6 @@ int sqlite3_get_table(
|
||||
int rc;
|
||||
TabResult res;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pazResult==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
*pazResult = 0;
|
||||
if( pnColumn ) *pnColumn = 0;
|
||||
if( pnRow ) *pnRow = 0;
|
||||
|
||||
@@ -3641,45 +3641,6 @@ static int db_use_legacy_prepare_cmd(
|
||||
Tcl_ResetResult(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Tclcmd: db_last_stmt_ptr DB
|
||||
**
|
||||
** If the statement cache associated with database DB is not empty,
|
||||
** return the text representation of the most recently used statement
|
||||
** handle.
|
||||
*/
|
||||
static int db_last_stmt_ptr(
|
||||
ClientData cd,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
|
||||
Tcl_CmdInfo cmdInfo;
|
||||
SqliteDb *pDb;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
char zBuf[100];
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
|
||||
Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pDb = (SqliteDb*)cmdInfo.objClientData;
|
||||
|
||||
if( pDb->stmtList ) pStmt = pDb->stmtList->pStmt;
|
||||
if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -3725,7 +3686,6 @@ static void init_all(Tcl_Interp *interp){
|
||||
extern int Sqlitetest9_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestasync_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_autoext_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_blob_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_demovfs_Init(Tcl_Interp *);
|
||||
extern int Sqlitetest_func_Init(Tcl_Interp*);
|
||||
extern int Sqlitetest_hexio_Init(Tcl_Interp*);
|
||||
@@ -3769,7 +3729,6 @@ static void init_all(Tcl_Interp *interp){
|
||||
Sqlitetest9_Init(interp);
|
||||
Sqlitetestasync_Init(interp);
|
||||
Sqlitetest_autoext_Init(interp);
|
||||
Sqlitetest_blob_Init(interp);
|
||||
Sqlitetest_demovfs_Init(interp);
|
||||
Sqlitetest_func_Init(interp);
|
||||
Sqlitetest_hexio_Init(interp);
|
||||
@@ -3801,9 +3760,6 @@ static void init_all(Tcl_Interp *interp){
|
||||
Tcl_CreateObjCommand(
|
||||
interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0
|
||||
);
|
||||
Tcl_CreateObjCommand(
|
||||
interp, "db_last_stmt_ptr", db_last_stmt_ptr, 0, 0
|
||||
);
|
||||
|
||||
#ifdef SQLITE_SSE
|
||||
Sqlitetestsse_Init(interp);
|
||||
|
||||
+153
-79
@@ -1651,6 +1651,154 @@ static int blobHandleFromObj(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_bytes CHANNEL
|
||||
*/
|
||||
static int test_blob_bytes(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int nByte;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
nByte = sqlite3_blob_bytes(pBlob);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte));
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_close CHANNEL
|
||||
*/
|
||||
static int test_blob_close(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
sqlite3_blob_close(pBlob);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_read CHANNEL OFFSET N
|
||||
**
|
||||
** This command is used to test the sqlite3_blob_read() in ways that
|
||||
** the Tcl channel interface does not. The first argument should
|
||||
** be the name of a valid channel created by the [incrblob] method
|
||||
** of a database handle. This function calls sqlite3_blob_read()
|
||||
** to read N bytes from offset OFFSET from the underlying SQLite
|
||||
** blob handle.
|
||||
**
|
||||
** On success, a byte-array object containing the read data is
|
||||
** returned. On failure, the interpreter result is set to the
|
||||
** text representation of the returned error code (i.e. "SQLITE_NOMEM")
|
||||
** and a Tcl exception is thrown.
|
||||
*/
|
||||
static int test_blob_read(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int nByte;
|
||||
int iOffset;
|
||||
unsigned char *zBuf = 0;
|
||||
int rc;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset)
|
||||
|| TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte)
|
||||
){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( nByte>0 ){
|
||||
zBuf = (unsigned char *)Tcl_Alloc(nByte);
|
||||
}
|
||||
rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset);
|
||||
if( rc==SQLITE_OK ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte));
|
||||
}else{
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
}
|
||||
Tcl_Free((char *)zBuf);
|
||||
|
||||
return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_write CHANNEL OFFSET DATA ?NDATA?
|
||||
**
|
||||
** This command is used to test the sqlite3_blob_write() in ways that
|
||||
** the Tcl channel interface does not. The first argument should
|
||||
** be the name of a valid channel created by the [incrblob] method
|
||||
** of a database handle. This function calls sqlite3_blob_write()
|
||||
** to write the DATA byte-array to the underlying SQLite blob handle.
|
||||
** at offset OFFSET.
|
||||
**
|
||||
** On success, an empty string is returned. On failure, the interpreter
|
||||
** result is set to the text representation of the returned error code
|
||||
** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown.
|
||||
*/
|
||||
static int test_blob_write(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int iOffset;
|
||||
int rc;
|
||||
|
||||
unsigned char *zBuf;
|
||||
int nBuf;
|
||||
|
||||
if( objc!=4 && objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
|
||||
if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
}
|
||||
|
||||
return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
||||
}
|
||||
|
||||
static int test_blob_reopen(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
@@ -2153,77 +2301,6 @@ static int test_stmt_status(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
/*
|
||||
** Usage: sqlite3_stmt_scanstatus STMT IDX
|
||||
*/
|
||||
static int test_stmt_scanstatus(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_stmt *pStmt; /* First argument */
|
||||
int idx; /* Second argument */
|
||||
|
||||
const char *zName;
|
||||
const char *zExplain;
|
||||
sqlite3_int64 nLoop;
|
||||
sqlite3_int64 nVisit;
|
||||
double rEst;
|
||||
int res;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
|
||||
|
||||
res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
|
||||
if( res==0 ){
|
||||
Tcl_Obj *pRet = Tcl_NewObj();
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
|
||||
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
|
||||
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
|
||||
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
|
||||
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
|
||||
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
|
||||
Tcl_SetObjResult(interp, pRet);
|
||||
}else{
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_stmt_scanstatus_reset STMT
|
||||
*/
|
||||
static int test_stmt_scanstatus_reset(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_stmt *pStmt; /* First argument */
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "STMT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
sqlite3_stmt_scanstatus_reset(pStmt);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_next_stmt DB STMT
|
||||
**
|
||||
@@ -6216,8 +6293,7 @@ static int optimization_control(
|
||||
{ "transitive", SQLITE_Transitive },
|
||||
{ "subquery-coroutine", SQLITE_SubqCoroutine },
|
||||
{ "omit-noop-join", SQLITE_OmitNoopJoin },
|
||||
{ "stat3", SQLITE_Stat34 },
|
||||
{ "stat4", SQLITE_Stat34 },
|
||||
{ "stat3", SQLITE_Stat3 },
|
||||
};
|
||||
|
||||
if( objc!=4 ){
|
||||
@@ -6260,7 +6336,6 @@ static int tclLoadStaticExtensionCmd(
|
||||
){
|
||||
extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
|
||||
@@ -6276,7 +6351,6 @@ static int tclLoadStaticExtensionCmd(
|
||||
} aExtension[] = {
|
||||
{ "amatch", sqlite3_amatch_init },
|
||||
{ "closure", sqlite3_closure_init },
|
||||
{ "eval", sqlite3_eval_init },
|
||||
{ "fileio", sqlite3_fileio_init },
|
||||
{ "fuzzer", sqlite3_fuzzer_init },
|
||||
{ "ieee754", sqlite3_ieee_init },
|
||||
@@ -6764,7 +6838,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
{ "sqlite3_blob_read", test_blob_read, 0 },
|
||||
{ "sqlite3_blob_write", test_blob_write, 0 },
|
||||
{ "sqlite3_blob_reopen", test_blob_reopen, 0 },
|
||||
{ "sqlite3_blob_bytes", test_blob_bytes, 0 },
|
||||
{ "sqlite3_blob_close", test_blob_close, 0 },
|
||||
#endif
|
||||
{ "pcache_stats", test_pcache_stats, 0 },
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
@@ -6789,10 +6867,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_user_change", test_user_change, 0 },
|
||||
{ "sqlite3_user_delete", test_user_delete, 0 },
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
{ "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 },
|
||||
{ "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 },
|
||||
#endif
|
||||
|
||||
};
|
||||
static int bitmask_size = sizeof(Bitmask)*8;
|
||||
|
||||
-319
@@ -1,319 +0,0 @@
|
||||
/*
|
||||
** 2014 October 30
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* These functions are implemented in main.c. */
|
||||
extern const char *sqlite3ErrName(int);
|
||||
|
||||
/* From test1.c: */
|
||||
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
|
||||
extern void *sqlite3TestTextToPtr(const char *z);
|
||||
|
||||
/*
|
||||
** Return a pointer to a buffer containing a text representation of the
|
||||
** pointer passed as the only argument. The original pointer may be extracted
|
||||
** from the text using sqlite3TestTextToPtr().
|
||||
*/
|
||||
static char *ptrToText(void *p){
|
||||
static char buf[100];
|
||||
sqlite3_snprintf(sizeof(buf)-1, buf, "%p", p);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to extract a blob handle (type sqlite3_blob*) from the Tcl
|
||||
** object passed as the second argument. If successful, set *ppBlob to
|
||||
** point to the blob handle and return TCL_OK. Otherwise, store an error
|
||||
** message in the tcl interpreter and return TCL_ERROR. The final value
|
||||
** of *ppBlob is undefined in this case.
|
||||
**
|
||||
** If the object contains a string that begins with "incrblob_", then it
|
||||
** is assumed to be the name of a Tcl channel opened using the [db incrblob]
|
||||
** command (see tclsqlite.c). Otherwise, it is assumed to be a pointer
|
||||
** encoded using the ptrToText() routine or similar.
|
||||
*/
|
||||
static int blobHandleFromObj(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *pObj,
|
||||
sqlite3_blob **ppBlob
|
||||
){
|
||||
char *z;
|
||||
int n;
|
||||
|
||||
z = Tcl_GetStringFromObj(pObj, &n);
|
||||
if( n==0 ){
|
||||
*ppBlob = 0;
|
||||
}else if( n>9 && 0==memcmp("incrblob_", z, 9) ){
|
||||
int notUsed;
|
||||
Tcl_Channel channel;
|
||||
ClientData instanceData;
|
||||
|
||||
channel = Tcl_GetChannel(interp, z, ¬Used);
|
||||
if( !channel ) return TCL_ERROR;
|
||||
|
||||
Tcl_Flush(channel);
|
||||
Tcl_Seek(channel, 0, SEEK_SET);
|
||||
|
||||
instanceData = Tcl_GetChannelInstanceData(channel);
|
||||
*ppBlob = *((sqlite3_blob **)instanceData);
|
||||
}else{
|
||||
*ppBlob = (sqlite3_blob*)sqlite3TestTextToPtr(z);
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Like Tcl_GetString(), except that if the string is 0 bytes in size, a
|
||||
** NULL Pointer is returned.
|
||||
*/
|
||||
static char *blobStringFromObj(Tcl_Obj *pObj){
|
||||
int n;
|
||||
char *z;
|
||||
z = Tcl_GetStringFromObj(pObj, &n);
|
||||
return (n ? z : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_open DB DATABASE TABLE COLUMN ROWID FLAGS VARNAME
|
||||
**
|
||||
** Tcl test harness for the sqlite3_blob_open() function.
|
||||
*/
|
||||
static int test_blob_open(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* Calling TCL interpreter */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3 *db;
|
||||
const char *zDb;
|
||||
const char *zTable;
|
||||
const char *zColumn;
|
||||
sqlite_int64 iRowid;
|
||||
int flags;
|
||||
const char *zVarname;
|
||||
int nVarname;
|
||||
|
||||
sqlite3_blob *pBlob = (sqlite3_blob*)0xFFFFFFFF;
|
||||
int rc;
|
||||
|
||||
if( objc!=8 ){
|
||||
const char *zUsage = "DB DATABASE TABLE COLUMN ROWID FLAGS VARNAME";
|
||||
Tcl_WrongNumArgs(interp, 1, objv, zUsage);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
zDb = Tcl_GetString(objv[2]);
|
||||
zTable = blobStringFromObj(objv[3]);
|
||||
zColumn = Tcl_GetString(objv[4]);
|
||||
if( Tcl_GetWideIntFromObj(interp, objv[5], &iRowid) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[6], &flags) ) return TCL_ERROR;
|
||||
zVarname = Tcl_GetStringFromObj(objv[7], &nVarname);
|
||||
|
||||
if( nVarname>0 ){
|
||||
rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRowid, flags, &pBlob);
|
||||
Tcl_SetVar(interp, zVarname, ptrToText(pBlob), 0);
|
||||
}else{
|
||||
rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRowid, flags, 0);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
Tcl_ResetResult(interp);
|
||||
}else{
|
||||
Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** sqlite3_blob_close HANDLE
|
||||
*/
|
||||
static int test_blob_close(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int rc;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
rc = sqlite3_blob_close(pBlob);
|
||||
|
||||
if( rc ){
|
||||
Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
}else{
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_bytes HANDLE
|
||||
*/
|
||||
static int test_blob_bytes(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int nByte;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
nByte = sqlite3_blob_bytes(pBlob);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte));
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_read CHANNEL OFFSET N
|
||||
**
|
||||
** This command is used to test the sqlite3_blob_read() in ways that
|
||||
** the Tcl channel interface does not. The first argument should
|
||||
** be the name of a valid channel created by the [incrblob] method
|
||||
** of a database handle. This function calls sqlite3_blob_read()
|
||||
** to read N bytes from offset OFFSET from the underlying SQLite
|
||||
** blob handle.
|
||||
**
|
||||
** On success, a byte-array object containing the read data is
|
||||
** returned. On failure, the interpreter result is set to the
|
||||
** text representation of the returned error code (i.e. "SQLITE_NOMEM")
|
||||
** and a Tcl exception is thrown.
|
||||
*/
|
||||
static int test_blob_read(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int nByte;
|
||||
int iOffset;
|
||||
unsigned char *zBuf = 0;
|
||||
int rc;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset)
|
||||
|| TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte)
|
||||
){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( nByte>0 ){
|
||||
zBuf = (unsigned char *)Tcl_Alloc(nByte);
|
||||
}
|
||||
rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset);
|
||||
if( rc==SQLITE_OK ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte));
|
||||
}else{
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
}
|
||||
Tcl_Free((char *)zBuf);
|
||||
|
||||
return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_blob_write HANDLE OFFSET DATA ?NDATA?
|
||||
**
|
||||
** This command is used to test the sqlite3_blob_write() in ways that
|
||||
** the Tcl channel interface does not. The first argument should
|
||||
** be the name of a valid channel created by the [incrblob] method
|
||||
** of a database handle. This function calls sqlite3_blob_write()
|
||||
** to write the DATA byte-array to the underlying SQLite blob handle.
|
||||
** at offset OFFSET.
|
||||
**
|
||||
** On success, an empty string is returned. On failure, the interpreter
|
||||
** result is set to the text representation of the returned error code
|
||||
** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown.
|
||||
*/
|
||||
static int test_blob_write(
|
||||
ClientData clientData, /* Not used */
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
sqlite3_blob *pBlob;
|
||||
int iOffset;
|
||||
int rc;
|
||||
|
||||
unsigned char *zBuf;
|
||||
int nBuf;
|
||||
|
||||
if( objc!=4 && objc!=5 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "HANDLE OFFSET DATA ?NDATA?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
||||
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
|
||||
if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
}
|
||||
|
||||
return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register commands with the TCL interpreter.
|
||||
*/
|
||||
int Sqlitetest_blob_Init(Tcl_Interp *interp){
|
||||
static struct {
|
||||
char *zName;
|
||||
Tcl_ObjCmdProc *xProc;
|
||||
} aObjCmd[] = {
|
||||
{ "sqlite3_blob_open", test_blob_open },
|
||||
{ "sqlite3_blob_close", test_blob_close },
|
||||
{ "sqlite3_blob_bytes", test_blob_bytes },
|
||||
{ "sqlite3_blob_read", test_blob_read },
|
||||
{ "sqlite3_blob_write", test_blob_write },
|
||||
};
|
||||
int i;
|
||||
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
|
||||
Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -155,12 +155,6 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
Tcl_SetVar2(interp, "sqlite_options", "api_armor", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "api_armor", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
@@ -490,12 +484,6 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
Tcl_SetVar2(interp, "sqlite_options", "stat3", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
Tcl_SetVar2(interp, "sqlite_options", "scanstatus", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "scanstatus", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
|
||||
# if defined(__APPLE__)
|
||||
# define SQLITE_ENABLE_LOCKING_STYLE 1
|
||||
|
||||
+4
-2
@@ -98,7 +98,8 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
||||
|
||||
|
||||
/********************************* Win32 Threads ****************************/
|
||||
#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
|
||||
#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
|
||||
SQLITE_THREADSAFE>0 && defined(_MSC_VER)
|
||||
|
||||
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
|
||||
#include <process.h>
|
||||
@@ -191,7 +192,8 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
||||
return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */
|
||||
#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
|
||||
SQLITE_THREADSAFE>0 && defined(_MSC_VER) */
|
||||
/******************************** End Win32 Threads *************************/
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -431,8 +431,8 @@ void sqlite3Update(
|
||||
|
||||
/* Top of the update loop */
|
||||
if( okOnePass ){
|
||||
if( aToOpen[iDataCur-iBaseCur] && !isView ){
|
||||
assert( pPk );
|
||||
if( aToOpen[iDataCur-iBaseCur] ){
|
||||
assert( pPk!=0 );
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
|
||||
VdbeCoverageNeverTaken(v);
|
||||
}
|
||||
|
||||
-10
@@ -251,11 +251,6 @@ int sqlite3Dequote(char *z){
|
||||
*/
|
||||
int sqlite3_stricmp(const char *zLeft, const char *zRight){
|
||||
register unsigned char *a, *b;
|
||||
if( zLeft==0 ){
|
||||
return zRight ? -1 : 0;
|
||||
}else if( zRight==0 ){
|
||||
return 1;
|
||||
}
|
||||
a = (unsigned char *)zLeft;
|
||||
b = (unsigned char *)zRight;
|
||||
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
|
||||
@@ -263,11 +258,6 @@ int sqlite3_stricmp(const char *zLeft, const char *zRight){
|
||||
}
|
||||
int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
|
||||
register unsigned char *a, *b;
|
||||
if( zLeft==0 ){
|
||||
return zRight ? -1 : 0;
|
||||
}else if( zRight==0 ){
|
||||
return 1;
|
||||
}
|
||||
a = (unsigned char *)zLeft;
|
||||
b = (unsigned char *)zRight;
|
||||
while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
|
||||
** overwriting the database with the vacuumed content.
|
||||
**
|
||||
** Only 1x temporary space and only 1x writes would be required if
|
||||
** the copy of step (3) were replaced by deleting the original database
|
||||
** the copy of step (3) were replace by deleting the original database
|
||||
** and renaming the transient database as the original. But that will
|
||||
** not work if other processes are attached to the original database.
|
||||
** And a power loss in between deleting the original and renaming the
|
||||
|
||||
+10
-27
@@ -608,9 +608,6 @@ int sqlite3VdbeExec(
|
||||
#endif
|
||||
nVmStep++;
|
||||
pOp = &aOp[pc];
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
if( p->anExec ) p->anExec[pc]++;
|
||||
#endif
|
||||
|
||||
/* Only allow tracing if SQLITE_DEBUG is defined.
|
||||
*/
|
||||
@@ -2301,7 +2298,7 @@ case OP_Column: {
|
||||
pC->payloadSize = pC->szRow = avail = pReg->n;
|
||||
pC->aRow = (u8*)pReg->z;
|
||||
}else{
|
||||
sqlite3VdbeMemSetNull(pDest);
|
||||
MemSetTypeFlag(pDest, MEM_Null);
|
||||
goto op_column_out;
|
||||
}
|
||||
}else{
|
||||
@@ -2444,7 +2441,7 @@ case OP_Column: {
|
||||
if( pOp->p4type==P4_MEM ){
|
||||
sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
|
||||
}else{
|
||||
sqlite3VdbeMemSetNull(pDest);
|
||||
MemSetTypeFlag(pDest, MEM_Null);
|
||||
}
|
||||
goto op_column_out;
|
||||
}
|
||||
@@ -2825,17 +2822,11 @@ case OP_Savepoint: {
|
||||
db->isTransactionSavepoint = 0;
|
||||
rc = p->rc;
|
||||
}else{
|
||||
int isSchemaChange;
|
||||
iSavepoint = db->nSavepoint - iSavepoint - 1;
|
||||
if( p1==SAVEPOINT_ROLLBACK ){
|
||||
isSchemaChange = (db->flags & SQLITE_InternChanges)!=0;
|
||||
for(ii=0; ii<db->nDb; ii++){
|
||||
rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT,
|
||||
isSchemaChange==0);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT);
|
||||
}
|
||||
}else{
|
||||
isSchemaChange = 0;
|
||||
}
|
||||
for(ii=0; ii<db->nDb; ii++){
|
||||
rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
|
||||
@@ -2843,7 +2834,7 @@ case OP_Savepoint: {
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
}
|
||||
if( isSchemaChange ){
|
||||
if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
db->flags = (db->flags | SQLITE_InternChanges);
|
||||
@@ -3240,7 +3231,7 @@ case OP_OpenWrite: {
|
||||
|| p->readOnly==0 );
|
||||
|
||||
if( p->expired ){
|
||||
rc = SQLITE_ABORT_ROLLBACK;
|
||||
rc = SQLITE_ABORT;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3804,11 +3795,10 @@ case OP_Found: { /* jump, in3 */
|
||||
}else{
|
||||
pIdxKey = sqlite3VdbeAllocUnpackedRecord(
|
||||
pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
|
||||
);
|
||||
);
|
||||
if( pIdxKey==0 ) goto no_mem;
|
||||
assert( pIn3->flags & MEM_Blob );
|
||||
/* assert( (pIn3->flags & MEM_Zero)==0 ); // zeroblobs already expanded */
|
||||
ExpandBlob(pIn3);
|
||||
assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
|
||||
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
|
||||
}
|
||||
pIdxKey->default_rc = 0;
|
||||
@@ -4498,9 +4488,9 @@ case OP_Sort: { /* jump */
|
||||
**
|
||||
** The next use of the Rowid or Column or Next instruction for P1
|
||||
** will refer to the first entry in the database table or index.
|
||||
** If the table or index is empty, jump immediately to P2.
|
||||
** If the table or index is not empty, fall through to the following
|
||||
** instruction.
|
||||
** If the table or index is empty and P2>0, then jump immediately to P2.
|
||||
** If P2 is 0 or if the table or index is not empty, fall through
|
||||
** to the following instruction.
|
||||
**
|
||||
** This opcode leaves the cursor configured to move in forward order,
|
||||
** from the beginning toward the end. In other words, the cursor is
|
||||
@@ -5416,9 +5406,6 @@ case OP_Program: { /* jump */
|
||||
pFrame->token = pProgram->token;
|
||||
pFrame->aOnceFlag = p->aOnceFlag;
|
||||
pFrame->nOnceFlag = p->nOnceFlag;
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
pFrame->anExec = p->anExec;
|
||||
#endif
|
||||
|
||||
pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
|
||||
for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
|
||||
@@ -5436,7 +5423,6 @@ case OP_Program: { /* jump */
|
||||
pFrame->pParent = p->pFrame;
|
||||
pFrame->lastRowid = lastRowid;
|
||||
pFrame->nChange = p->nChange;
|
||||
pFrame->nDbChange = p->db->nChange;
|
||||
p->nChange = 0;
|
||||
p->pFrame = pFrame;
|
||||
p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
|
||||
@@ -5447,9 +5433,6 @@ case OP_Program: { /* jump */
|
||||
p->nOp = pProgram->nOp;
|
||||
p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
|
||||
p->nOnceFlag = pProgram->nOnce;
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
p->anExec = 0;
|
||||
#endif
|
||||
pc = -1;
|
||||
memset(p->aOnceFlag, 0, p->nOnceFlag);
|
||||
|
||||
|
||||
@@ -282,10 +282,4 @@ void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
|
||||
# define VDBE_OFFSET_LINENO(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*);
|
||||
#else
|
||||
# define sqlite3VdbeScanStatus(a,b,c,d,e)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+1
-18
@@ -132,7 +132,6 @@ struct VdbeFrame {
|
||||
Vdbe *v; /* VM this frame belongs to */
|
||||
VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
|
||||
Op *aOp; /* Program instructions for parent frame */
|
||||
i64 *anExec; /* Event counters from parent frame */
|
||||
Mem *aMem; /* Array of memory cells for parent frame */
|
||||
u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */
|
||||
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
|
||||
@@ -145,8 +144,7 @@ struct VdbeFrame {
|
||||
int nOnceFlag; /* Number of entries in aOnceFlag */
|
||||
int nChildMem; /* Number of memory cells for child frame */
|
||||
int nChildCsr; /* Number of cursors for child frame */
|
||||
int nChange; /* Statement changes (Vdbe.nChange) */
|
||||
int nDbChange; /* Value of db->nChange */
|
||||
int nChange; /* Statement changes (Vdbe.nChanges) */
|
||||
};
|
||||
|
||||
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
|
||||
@@ -297,16 +295,6 @@ struct Explain {
|
||||
*/
|
||||
typedef unsigned bft; /* Bit Field Type */
|
||||
|
||||
typedef struct ScanStatus ScanStatus;
|
||||
struct ScanStatus {
|
||||
int addrExplain; /* OP_Explain for loop */
|
||||
int addrLoop; /* Address of "loops" counter */
|
||||
int addrVisit; /* Address of "rows visited" counter */
|
||||
int iSelectID; /* The "Select-ID" for this loop */
|
||||
LogEst nEst; /* Estimated output rows per loop */
|
||||
char *zName; /* Name of table or index */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of the virtual machine. This structure contains the complete
|
||||
** state of the virtual machine.
|
||||
@@ -379,11 +367,6 @@ struct Vdbe {
|
||||
int nOnceFlag; /* Size of array aOnceFlag[] */
|
||||
u8 *aOnceFlag; /* Flags for OP_Once */
|
||||
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
i64 *anExec; /* Number of times each op has been executed */
|
||||
int nScan; /* Entries in aScan[] */
|
||||
ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+5
-95
@@ -966,19 +966,11 @@ static const void *columnName(
|
||||
const void *(*xFunc)(Mem*),
|
||||
int useType
|
||||
){
|
||||
const void *ret;
|
||||
Vdbe *p;
|
||||
const void *ret = 0;
|
||||
Vdbe *p = (Vdbe *)pStmt;
|
||||
int n;
|
||||
sqlite3 *db;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pStmt==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
ret = 0;
|
||||
p = (Vdbe *)pStmt;
|
||||
db = p->db;
|
||||
sqlite3 *db = p->db;
|
||||
|
||||
assert( db!=0 );
|
||||
n = sqlite3_column_count(pStmt);
|
||||
if( N<n && N>=0 ){
|
||||
@@ -1443,12 +1435,6 @@ int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
|
||||
*/
|
||||
sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
|
||||
sqlite3_stmt *pNext;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(pDb) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(pDb->mutex);
|
||||
if( pStmt==0 ){
|
||||
pNext = (sqlite3_stmt*)pDb->pVdbe;
|
||||
@@ -1464,83 +1450,7 @@ sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
|
||||
*/
|
||||
int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
|
||||
Vdbe *pVdbe = (Vdbe*)pStmt;
|
||||
u32 v;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !pStmt ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
v = pVdbe->aCounter[op];
|
||||
u32 v = pVdbe->aCounter[op];
|
||||
if( resetFlag ) pVdbe->aCounter[op] = 0;
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
/*
|
||||
** Return status data for a single loop within query pStmt.
|
||||
*/
|
||||
int sqlite3_stmt_scanstatus(
|
||||
sqlite3_stmt *pStmt, /* Prepared statement being queried */
|
||||
int idx, /* Index of loop to report on */
|
||||
int iScanStatusOp, /* Which metric to return */
|
||||
void *pOut /* OUT: Write the answer here */
|
||||
){
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
ScanStatus *pScan;
|
||||
if( idx<0 || idx>=p->nScan ) return 1;
|
||||
pScan = &p->aScan[idx];
|
||||
switch( iScanStatusOp ){
|
||||
case SQLITE_SCANSTAT_NLOOP: {
|
||||
*(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop];
|
||||
break;
|
||||
}
|
||||
case SQLITE_SCANSTAT_NVISIT: {
|
||||
*(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit];
|
||||
break;
|
||||
}
|
||||
case SQLITE_SCANSTAT_EST: {
|
||||
double r = 1.0;
|
||||
LogEst x = pScan->nEst;
|
||||
while( x<100 ){
|
||||
x += 10;
|
||||
r *= 0.5;
|
||||
}
|
||||
*(double*)pOut = r*sqlite3LogEstToInt(x);
|
||||
break;
|
||||
}
|
||||
case SQLITE_SCANSTAT_NAME: {
|
||||
*(const char**)pOut = pScan->zName;
|
||||
break;
|
||||
}
|
||||
case SQLITE_SCANSTAT_EXPLAIN: {
|
||||
if( pScan->addrExplain ){
|
||||
*(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z;
|
||||
}else{
|
||||
*(const char**)pOut = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SQLITE_SCANSTAT_SELECTID: {
|
||||
if( pScan->addrExplain ){
|
||||
*(int*)pOut = p->aOp[ pScan->addrExplain ].p1;
|
||||
}else{
|
||||
*(int*)pOut = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Zero all counters associated with the sqlite3_stmt_scanstatus() data.
|
||||
*/
|
||||
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
memset(p->anExec, 0, p->nOp * sizeof(i64));
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STMT_SCANSTATUS */
|
||||
|
||||
@@ -597,34 +597,6 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
|
||||
return addr;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS)
|
||||
/*
|
||||
** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus().
|
||||
*/
|
||||
void sqlite3VdbeScanStatus(
|
||||
Vdbe *p, /* VM to add scanstatus() to */
|
||||
int addrExplain, /* Address of OP_Explain (or 0) */
|
||||
int addrLoop, /* Address of loop counter */
|
||||
int addrVisit, /* Address of rows visited counter */
|
||||
LogEst nEst, /* Estimated number of output rows */
|
||||
const char *zName /* Name of table or index being scanned */
|
||||
){
|
||||
int nByte = (p->nScan+1) * sizeof(ScanStatus);
|
||||
ScanStatus *aNew;
|
||||
aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
|
||||
if( aNew ){
|
||||
ScanStatus *pNew = &aNew[p->nScan++];
|
||||
pNew->addrExplain = addrExplain;
|
||||
pNew->addrLoop = addrLoop;
|
||||
pNew->addrVisit = addrVisit;
|
||||
pNew->nEst = nEst;
|
||||
pNew->zName = sqlite3DbStrDup(p->db, zName);
|
||||
p->aScan = aNew;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Change the value of the P1 operand for a specific instruction.
|
||||
** This routine is useful when a large program is loaded from a
|
||||
@@ -1723,9 +1695,6 @@ void sqlite3VdbeMakeReady(
|
||||
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
|
||||
&zCsr, zEnd, &nByte);
|
||||
p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte);
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), &zCsr, zEnd, &nByte);
|
||||
#endif
|
||||
if( nByte ){
|
||||
p->pFree = sqlite3DbMallocZero(db, nByte);
|
||||
}
|
||||
@@ -1793,9 +1762,6 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
||||
*/
|
||||
int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
|
||||
Vdbe *v = pFrame->v;
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
v->anExec = pFrame->anExec;
|
||||
#endif
|
||||
v->aOnceFlag = pFrame->aOnceFlag;
|
||||
v->nOnceFlag = pFrame->nOnceFlag;
|
||||
v->aOp = pFrame->aOp;
|
||||
@@ -1806,7 +1772,6 @@ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
|
||||
v->nCursor = pFrame->nCursor;
|
||||
v->db->lastRowid = pFrame->lastRowid;
|
||||
v->nChange = pFrame->nChange;
|
||||
v->db->nChange = pFrame->nDbChange;
|
||||
return pFrame->pc;
|
||||
}
|
||||
|
||||
@@ -2374,7 +2339,6 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
|
||||
sqlite3CloseSavepoints(db);
|
||||
db->autoCommit = 1;
|
||||
p->nChange = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2415,7 +2379,6 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
}else if( rc!=SQLITE_OK ){
|
||||
p->rc = rc;
|
||||
sqlite3RollbackAll(db, SQLITE_OK);
|
||||
p->nChange = 0;
|
||||
}else{
|
||||
db->nDeferredCons = 0;
|
||||
db->nDeferredImmCons = 0;
|
||||
@@ -2424,7 +2387,6 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
}
|
||||
}else{
|
||||
sqlite3RollbackAll(db, SQLITE_OK);
|
||||
p->nChange = 0;
|
||||
}
|
||||
db->nStatement = 0;
|
||||
}else if( eStatementOp==0 ){
|
||||
@@ -2436,7 +2398,6 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
|
||||
sqlite3CloseSavepoints(db);
|
||||
db->autoCommit = 1;
|
||||
p->nChange = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2457,7 +2418,6 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
|
||||
sqlite3CloseSavepoints(db);
|
||||
db->autoCommit = 1;
|
||||
p->nChange = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2719,12 +2679,6 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
|
||||
sqlite3DbFree(db, p->aColName);
|
||||
sqlite3DbFree(db, p->zSql);
|
||||
sqlite3DbFree(db, p->pFree);
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
for(i=0; i<p->nScan; i++){
|
||||
sqlite3DbFree(db, p->aScan[i].zName);
|
||||
}
|
||||
sqlite3DbFree(db, p->aScan);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-6
@@ -153,11 +153,6 @@ int sqlite3_blob_open(
|
||||
Parse *pParse = 0;
|
||||
Incrblob *pBlob = 0;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || ppBlob==0 || zTable==0 ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
flags = !!flags; /* flags = (flags ? 1 : 0); */
|
||||
*ppBlob = 0;
|
||||
|
||||
@@ -376,6 +371,7 @@ static int blobReadWrite(
|
||||
if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){
|
||||
/* Request is out of range. Return a transient error. */
|
||||
rc = SQLITE_ERROR;
|
||||
sqlite3Error(db, SQLITE_ERROR);
|
||||
}else if( v==0 ){
|
||||
/* If there is no statement handle, then the blob-handle has
|
||||
** already been invalidated. Return SQLITE_ABORT in this case.
|
||||
@@ -393,10 +389,10 @@ static int blobReadWrite(
|
||||
sqlite3VdbeFinalize(v);
|
||||
p->pStmt = 0;
|
||||
}else{
|
||||
db->errCode = rc;
|
||||
v->rc = rc;
|
||||
}
|
||||
}
|
||||
sqlite3Error(db, rc);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
|
||||
+6
-4
@@ -100,7 +100,7 @@
|
||||
** The sorter is running in multi-threaded mode if (a) the library was built
|
||||
** with pre-processor symbol SQLITE_MAX_WORKER_THREADS set to a value greater
|
||||
** than zero, and (b) worker threads have been enabled at runtime by calling
|
||||
** "PRAGMA threads=N" with some value of N greater than 0.
|
||||
** sqlite3_config(SQLITE_CONFIG_WORKER_THREADS, ...).
|
||||
**
|
||||
** When Rewind() is called, any data remaining in memory is flushed to a
|
||||
** final PMA. So at this point the data is stored in some number of sorted
|
||||
@@ -847,9 +847,11 @@ int sqlite3VdbeSorterInit(
|
||||
if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING;
|
||||
pSorter->mxPmaSize = mxCache * pgsz;
|
||||
|
||||
/* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
|
||||
** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
|
||||
** large heap allocations.
|
||||
/* If the application has not configure scratch memory using
|
||||
** SQLITE_CONFIG_SCRATCH then we assume it is OK to do large memory
|
||||
** allocations. If scratch memory has been configured, then assume
|
||||
** large memory allocations should be avoided to prevent heap
|
||||
** fragmentation.
|
||||
*/
|
||||
if( sqlite3GlobalConfig.pScratch==0 ){
|
||||
assert( pSorter->iMemory==0 );
|
||||
|
||||
+1
-15
@@ -81,9 +81,6 @@ int sqlite3_create_module(
|
||||
const sqlite3_module *pModule, /* The definition of the module */
|
||||
void *pAux /* Context pointer for xCreate/xConnect */
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
return createModule(db, zName, pModule, pAux, 0);
|
||||
}
|
||||
|
||||
@@ -97,9 +94,6 @@ int sqlite3_create_module_v2(
|
||||
void *pAux, /* Context pointer for xCreate/xConnect */
|
||||
void (*xDestroy)(void *) /* Module destructor function */
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
return createModule(db, zName, pModule, pAux, xDestroy);
|
||||
}
|
||||
|
||||
@@ -704,9 +698,6 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
Table *pTab;
|
||||
char *zErr = 0;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
|
||||
sqlite3Error(db, SQLITE_MISUSE);
|
||||
@@ -1063,9 +1054,6 @@ int sqlite3_vtab_on_conflict(sqlite3 *db){
|
||||
static const unsigned char aMap[] = {
|
||||
SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
|
||||
};
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
|
||||
assert( OE_Ignore==4 && OE_Replace==5 );
|
||||
assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
|
||||
@@ -1081,10 +1069,8 @@ int sqlite3_vtab_config(sqlite3 *db, int op, ...){
|
||||
va_list ap;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
va_start(ap, op);
|
||||
switch( op ){
|
||||
case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
|
||||
|
||||
@@ -1504,7 +1504,7 @@ static void walMergesort(
|
||||
** Free an iterator allocated by walIteratorInit().
|
||||
*/
|
||||
static void walIteratorFree(WalIterator *p){
|
||||
sqlite3_free(p);
|
||||
sqlite3ScratchFree(p);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1539,7 +1539,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
|
||||
nByte = sizeof(WalIterator)
|
||||
+ (nSegment-1)*sizeof(struct WalSegment)
|
||||
+ iLast*sizeof(ht_slot);
|
||||
p = (WalIterator *)sqlite3_malloc(nByte);
|
||||
p = (WalIterator *)sqlite3ScratchMalloc(nByte);
|
||||
if( !p ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -1549,7 +1549,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
|
||||
/* Allocate temporary space used by the merge-sort routine. This block
|
||||
** of memory will be freed before this function returns.
|
||||
*/
|
||||
aTmp = (ht_slot *)sqlite3_malloc(
|
||||
aTmp = (ht_slot *)sqlite3ScratchMalloc(
|
||||
sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
|
||||
);
|
||||
if( !aTmp ){
|
||||
@@ -1586,7 +1586,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
|
||||
p->aSegment[i].aPgno = (u32 *)aPgno;
|
||||
}
|
||||
}
|
||||
sqlite3_free(aTmp);
|
||||
sqlite3ScratchFree(aTmp);
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
walIteratorFree(p);
|
||||
@@ -2506,7 +2506,7 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
|
||||
memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
|
||||
|
||||
for(iFrame=pWal->hdr.mxFrame+1;
|
||||
rc==SQLITE_OK && iFrame<=iMax;
|
||||
ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
|
||||
iFrame++
|
||||
){
|
||||
/* This call cannot fail. Unless the page for which the page number
|
||||
@@ -2525,6 +2525,7 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
|
||||
}
|
||||
if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
|
||||
}
|
||||
assert( rc==SQLITE_OK );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+51
-139
@@ -225,7 +225,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
|
||||
}
|
||||
pTerm = &pWC->a[idx = pWC->nTerm++];
|
||||
if( p && ExprHasProperty(p, EP_Unlikely) ){
|
||||
pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
|
||||
pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
|
||||
}else{
|
||||
pTerm->truthProb = 1;
|
||||
}
|
||||
@@ -756,15 +756,6 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Mark term iChild as being a child of term iParent
|
||||
*/
|
||||
static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
|
||||
pWC->a[iChild].iParent = iParent;
|
||||
pWC->a[iChild].truthProb = pWC->a[iParent].truthProb;
|
||||
pWC->a[iParent].nChild++;
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
|
||||
/*
|
||||
** Analyze a term that consists of two or more OR-connected
|
||||
@@ -1062,7 +1053,8 @@ static void exprAnalyzeOrTerm(
|
||||
testcase( idxNew==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pWC->a[idxNew].iParent = idxTerm;
|
||||
pTerm->nChild = 1;
|
||||
}else{
|
||||
sqlite3ExprListDelete(db, pList);
|
||||
}
|
||||
@@ -1164,8 +1156,9 @@ static void exprAnalyze(
|
||||
idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
|
||||
if( idxNew==0 ) return;
|
||||
pNew = &pWC->a[idxNew];
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pNew->iParent = idxTerm;
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->nChild = 1;
|
||||
pTerm->wtFlags |= TERM_COPIED;
|
||||
if( pExpr->op==TK_EQ
|
||||
&& !ExprHasProperty(pExpr, EP_FromJoin)
|
||||
@@ -1222,8 +1215,9 @@ static void exprAnalyze(
|
||||
testcase( idxNew==0 );
|
||||
exprAnalyze(pSrc, pWC, idxNew);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pWC->a[idxNew].iParent = idxTerm;
|
||||
}
|
||||
pTerm->nChild = 2;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */
|
||||
|
||||
@@ -1298,8 +1292,9 @@ static void exprAnalyze(
|
||||
exprAnalyze(pSrc, pWC, idxNew2);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
if( isComplete ){
|
||||
markTermAsChild(pWC, idxNew1, idxTerm);
|
||||
markTermAsChild(pWC, idxNew2, idxTerm);
|
||||
pWC->a[idxNew1].iParent = idxTerm;
|
||||
pWC->a[idxNew2].iParent = idxTerm;
|
||||
pTerm->nChild = 2;
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
|
||||
@@ -1332,8 +1327,9 @@ static void exprAnalyze(
|
||||
pNewTerm->leftCursor = pLeft->iTable;
|
||||
pNewTerm->u.leftColumn = pLeft->iColumn;
|
||||
pNewTerm->eOperator = WO_MATCH;
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pNewTerm->iParent = idxTerm;
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->nChild = 1;
|
||||
pTerm->wtFlags |= TERM_COPIED;
|
||||
pNewTerm->prereqAll = pTerm->prereqAll;
|
||||
}
|
||||
@@ -1354,7 +1350,7 @@ static void exprAnalyze(
|
||||
if( pExpr->op==TK_NOTNULL
|
||||
&& pExpr->pLeft->op==TK_COLUMN
|
||||
&& pExpr->pLeft->iColumn>=0
|
||||
&& OptimizationEnabled(db, SQLITE_Stat34)
|
||||
&& OptimizationEnabled(db, SQLITE_Stat3)
|
||||
){
|
||||
Expr *pNewExpr;
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
@@ -1373,8 +1369,9 @@ static void exprAnalyze(
|
||||
pNewTerm->leftCursor = pLeft->iTable;
|
||||
pNewTerm->u.leftColumn = pLeft->iColumn;
|
||||
pNewTerm->eOperator = WO_GT;
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pNewTerm->iParent = idxTerm;
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->nChild = 1;
|
||||
pTerm->wtFlags |= TERM_COPIED;
|
||||
pNewTerm->prereqAll = pTerm->prereqAll;
|
||||
}
|
||||
@@ -1594,8 +1591,6 @@ static void constructAutomaticIndex(
|
||||
Bitmask idxCols; /* Bitmap of columns used for indexing */
|
||||
Bitmask extraCols; /* Bitmap of additional columns */
|
||||
u8 sentWarning = 0; /* True if a warnning has been issued */
|
||||
Expr *pPartial = 0; /* Partial Index Expression */
|
||||
int iContinue = 0; /* Jump here to skip excluded rows */
|
||||
|
||||
/* Generate code to skip over the creation and initialization of the
|
||||
** transient index on 2nd and subsequent iterations of the loop. */
|
||||
@@ -1611,12 +1606,6 @@ static void constructAutomaticIndex(
|
||||
pLoop = pLevel->pWLoop;
|
||||
idxCols = 0;
|
||||
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
|
||||
if( pLoop->prereq==0
|
||||
&& (pTerm->wtFlags & TERM_VIRTUAL)==0
|
||||
&& sqlite3ExprIsTableConstant(pTerm->pExpr, pSrc->iCursor) ){
|
||||
pPartial = sqlite3ExprAnd(pParse->db, pPartial,
|
||||
sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
|
||||
}
|
||||
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
|
||||
int iCol = pTerm->u.leftColumn;
|
||||
Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
|
||||
@@ -1629,9 +1618,7 @@ static void constructAutomaticIndex(
|
||||
sentWarning = 1;
|
||||
}
|
||||
if( (idxCols & cMask)==0 ){
|
||||
if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){
|
||||
goto end_auto_index_create;
|
||||
}
|
||||
if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ) return;
|
||||
pLoop->aLTerm[nKeyCol++] = pTerm;
|
||||
idxCols |= cMask;
|
||||
}
|
||||
@@ -1651,7 +1638,7 @@ static void constructAutomaticIndex(
|
||||
** if they go out of sync.
|
||||
*/
|
||||
extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
|
||||
mxBitCol = MIN(BMS-1,pTable->nCol);
|
||||
mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol;
|
||||
testcase( pTable->nCol==BMS-1 );
|
||||
testcase( pTable->nCol==BMS-2 );
|
||||
for(i=0; i<mxBitCol; i++){
|
||||
@@ -1660,10 +1647,11 @@ static void constructAutomaticIndex(
|
||||
if( pSrc->colUsed & MASKBIT(BMS-1) ){
|
||||
nKeyCol += pTable->nCol - BMS + 1;
|
||||
}
|
||||
pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY;
|
||||
|
||||
/* Construct the Index object to describe this index */
|
||||
pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed);
|
||||
if( pIdx==0 ) goto end_auto_index_create;
|
||||
if( pIdx==0 ) return;
|
||||
pLoop->u.btree.pIndex = pIdx;
|
||||
pIdx->zName = "auto-index";
|
||||
pIdx->pTable = pTable;
|
||||
@@ -1715,29 +1703,18 @@ static void constructAutomaticIndex(
|
||||
VdbeComment((v, "for %s", pTable->zName));
|
||||
|
||||
/* Fill the automatic index with content */
|
||||
sqlite3ExprCachePush(pParse);
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
|
||||
if( pPartial ){
|
||||
iContinue = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL);
|
||||
pLoop->wsFlags |= WHERE_PARTIALIDX;
|
||||
}
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
|
||||
sqlite3VdbeJumpHere(v, addrTop);
|
||||
sqlite3ReleaseTempReg(pParse, regRecord);
|
||||
sqlite3ExprCachePop(pParse);
|
||||
|
||||
/* Jump here when skipping the initialization */
|
||||
sqlite3VdbeJumpHere(v, addrInit);
|
||||
|
||||
end_auto_index_create:
|
||||
sqlite3ExprDelete(pParse->db, pPartial);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
|
||||
|
||||
@@ -1897,6 +1874,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
|
||||
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
/*
|
||||
** Estimate the location of a particular key among all keys in an
|
||||
@@ -1905,10 +1883,9 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
** aStat[0] Est. number of rows less than pVal
|
||||
** aStat[1] Est. number of rows equal to pVal
|
||||
**
|
||||
** Return the index of the sample that is the smallest sample that
|
||||
** is greater than or equal to pRec.
|
||||
** Return SQLITE_OK on success.
|
||||
*/
|
||||
static int whereKeyStats(
|
||||
static void whereKeyStats(
|
||||
Parse *pParse, /* Database connection */
|
||||
Index *pIdx, /* Index to consider domain of */
|
||||
UnpackedRecord *pRec, /* Vector of values to consider */
|
||||
@@ -1990,7 +1967,6 @@ static int whereKeyStats(
|
||||
}
|
||||
aStat[0] = iLower + iGap;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
||||
|
||||
@@ -2141,7 +2117,7 @@ static int whereRangeSkipScanEst(
|
||||
** If either of the upper or lower bound is not present, then NULL is passed in
|
||||
** place of the corresponding WhereTerm.
|
||||
**
|
||||
** The value in (pBuilder->pNew->u.btree.nEq) is the number of the index
|
||||
** The value in (pBuilder->pNew->u.btree.nEq) is the index of the index
|
||||
** column subject to the range constraint. Or, equivalently, the number of
|
||||
** equality constraints optimized by the proposed index scan. For example,
|
||||
** assuming index p is on t1(a, b), and the SQL query is:
|
||||
@@ -2157,7 +2133,7 @@ static int whereRangeSkipScanEst(
|
||||
**
|
||||
** When this function is called, *pnOut is set to the sqlite3LogEst() of the
|
||||
** number of rows that the index scan is expected to visit without
|
||||
** considering the range constraints. If nEq is 0, then *pnOut is the number of
|
||||
** considering the range constraints. If nEq is 0, this is the number of
|
||||
** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
|
||||
** to account for the range constraints pLower and pUpper.
|
||||
**
|
||||
@@ -2181,7 +2157,10 @@ static int whereRangeScanEst(
|
||||
Index *p = pLoop->u.btree.pIndex;
|
||||
int nEq = pLoop->u.btree.nEq;
|
||||
|
||||
if( p->nSample>0 && nEq<p->nSampleCol ){
|
||||
if( p->nSample>0
|
||||
&& nEq<p->nSampleCol
|
||||
&& OptimizationEnabled(pParse->db, SQLITE_Stat3)
|
||||
){
|
||||
if( nEq==pBuilder->nRecValid ){
|
||||
UnpackedRecord *pRec = pBuilder->pRec;
|
||||
tRowcnt a[2];
|
||||
@@ -2197,19 +2176,15 @@ static int whereRangeScanEst(
|
||||
** is not a simple variable or literal value), the lower bound of the
|
||||
** range is $P. Due to a quirk in the way whereKeyStats() works, even
|
||||
** if $L is available, whereKeyStats() is called for both ($P) and
|
||||
** ($P:$L) and the larger of the two returned values is used.
|
||||
** ($P:$L) and the larger of the two returned values used.
|
||||
**
|
||||
** Similarly, iUpper is to be set to the estimate of the number of rows
|
||||
** less than the upper bound of the range query. Where the upper bound
|
||||
** is either ($P) or ($P:$U). Again, even if $U is available, both values
|
||||
** of iUpper are requested of whereKeyStats() and the smaller used.
|
||||
**
|
||||
** The number of rows between the two bounds is then just iUpper-iLower.
|
||||
*/
|
||||
tRowcnt iLower; /* Rows less than the lower bound */
|
||||
tRowcnt iUpper; /* Rows less than the upper bound */
|
||||
int iLwrIdx = -2; /* aSample[] for the lower bound */
|
||||
int iUprIdx = -1; /* aSample[] for the upper bound */
|
||||
tRowcnt iLower;
|
||||
tRowcnt iUpper;
|
||||
|
||||
if( pRec ){
|
||||
testcase( pRec->nField!=pBuilder->nRecValid );
|
||||
@@ -2247,7 +2222,7 @@ static int whereRangeScanEst(
|
||||
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
|
||||
if( rc==SQLITE_OK && bOk ){
|
||||
tRowcnt iNew;
|
||||
iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a);
|
||||
whereKeyStats(pParse, p, pRec, 0, a);
|
||||
iNew = a[0] + ((pLower->eOperator & (WO_GT|WO_LE)) ? a[1] : 0);
|
||||
if( iNew>iLower ) iLower = iNew;
|
||||
nOut--;
|
||||
@@ -2262,7 +2237,7 @@ static int whereRangeScanEst(
|
||||
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
|
||||
if( rc==SQLITE_OK && bOk ){
|
||||
tRowcnt iNew;
|
||||
iUprIdx = whereKeyStats(pParse, p, pRec, 1, a);
|
||||
whereKeyStats(pParse, p, pRec, 1, a);
|
||||
iNew = a[0] + ((pUpper->eOperator & (WO_GT|WO_LE)) ? a[1] : 0);
|
||||
if( iNew<iUpper ) iUpper = iNew;
|
||||
nOut--;
|
||||
@@ -2274,11 +2249,6 @@ static int whereRangeScanEst(
|
||||
if( rc==SQLITE_OK ){
|
||||
if( iUpper>iLower ){
|
||||
nNew = sqlite3LogEst(iUpper - iLower);
|
||||
/* TUNING: If both iUpper and iLower are derived from the same
|
||||
** sample, then assume they are 4x more selective. This brings
|
||||
** the estimated selectivity more in line with what it would be
|
||||
** if estimated without the use of STAT3/4 tables. */
|
||||
if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) );
|
||||
}else{
|
||||
nNew = 10; assert( 10==sqlite3LogEst(2) );
|
||||
}
|
||||
@@ -2303,15 +2273,12 @@ static int whereRangeScanEst(
|
||||
nNew = whereRangeAdjust(pLower, nOut);
|
||||
nNew = whereRangeAdjust(pUpper, nNew);
|
||||
|
||||
/* TUNING: If there is both an upper and lower limit and neither limit
|
||||
** has an application-defined likelihood(), assume the range is
|
||||
/* TUNING: If there is both an upper and lower limit, assume the range is
|
||||
** reduced by an additional 75%. This means that, by default, an open-ended
|
||||
** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the
|
||||
** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to
|
||||
** match 1/64 of the index. */
|
||||
if( pLower && pLower->truthProb>0 && pUpper && pUpper->truthProb>0 ){
|
||||
nNew -= 20;
|
||||
}
|
||||
if( pLower && pUpper ) nNew -= 20;
|
||||
|
||||
nOut -= (pLower!=0) + (pUpper!=0);
|
||||
if( nNew<10 ) nNew = 10;
|
||||
@@ -2816,14 +2783,11 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop, Table *pTab){
|
||||
|
||||
/*
|
||||
** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
|
||||
** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was
|
||||
** defined at compile-time. If it is not a no-op, a single OP_Explain opcode
|
||||
** is added to the output to describe the table scan strategy in pLevel.
|
||||
**
|
||||
** If an OP_Explain opcode is added to the VM, its address is returned.
|
||||
** Otherwise, if no OP_Explain is coded, zero is returned.
|
||||
** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single
|
||||
** record is added to the output to describe the table scan strategy in
|
||||
** pLevel.
|
||||
*/
|
||||
static int explainOneScan(
|
||||
static void explainOneScan(
|
||||
Parse *pParse, /* Parse context */
|
||||
SrcList *pTabList, /* Table list this loop refers to */
|
||||
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
|
||||
@@ -2831,8 +2795,7 @@ static int explainOneScan(
|
||||
int iFrom, /* Value for "from" column of output */
|
||||
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
|
||||
){
|
||||
int ret = 0;
|
||||
#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
|
||||
#ifndef SQLITE_DEBUG
|
||||
if( pParse->explain==2 )
|
||||
#endif
|
||||
{
|
||||
@@ -2849,7 +2812,7 @@ static int explainOneScan(
|
||||
|
||||
pLoop = pLevel->pWLoop;
|
||||
flags = pLoop->wsFlags;
|
||||
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return 0;
|
||||
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
|
||||
|
||||
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|
||||
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|
||||
@@ -2878,8 +2841,6 @@ static int explainOneScan(
|
||||
if( isSearch ){
|
||||
zFmt = "PRIMARY KEY";
|
||||
}
|
||||
}else if( flags & WHERE_PARTIALIDX ){
|
||||
zFmt = "AUTOMATIC PARTIAL COVERING INDEX";
|
||||
}else if( flags & WHERE_AUTO_INDEX ){
|
||||
zFmt = "AUTOMATIC COVERING INDEX";
|
||||
}else if( flags & WHERE_IDX_ONLY ){
|
||||
@@ -2921,46 +2882,13 @@ static int explainOneScan(
|
||||
}
|
||||
#endif
|
||||
zMsg = sqlite3StrAccumFinish(&str);
|
||||
ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC);
|
||||
sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
# define explainOneScan(u,v,w,x,y,z) 0
|
||||
# define explainOneScan(u,v,w,x,y,z)
|
||||
#endif /* SQLITE_OMIT_EXPLAIN */
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
/*
|
||||
** Configure the VM passed as the first argument with an
|
||||
** sqlite3_stmt_scanstatus() entry corresponding to the scan used to
|
||||
** implement level pLvl. Argument pSrclist is a pointer to the FROM
|
||||
** clause that the scan reads data from.
|
||||
**
|
||||
** If argument addrExplain is not 0, it must be the address of an
|
||||
** OP_Explain instruction that describes the same loop.
|
||||
*/
|
||||
static void addScanStatus(
|
||||
Vdbe *v, /* Vdbe to add scanstatus entry to */
|
||||
SrcList *pSrclist, /* FROM clause pLvl reads data from */
|
||||
WhereLevel *pLvl, /* Level to add scanstatus() entry for */
|
||||
int addrExplain /* Address of OP_Explain (or 0) */
|
||||
){
|
||||
const char *zObj = 0;
|
||||
WhereLoop *pLoop = pLvl->pWLoop;
|
||||
if( (pLoop->wsFlags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
|
||||
zObj = pLoop->u.btree.pIndex->zName;
|
||||
}else{
|
||||
zObj = pSrclist->a[pLvl->iFrom].zName;
|
||||
}
|
||||
sqlite3VdbeScanStatus(
|
||||
v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj
|
||||
);
|
||||
}
|
||||
#else
|
||||
# define addScanStatus(a, b, c, d) ((void)d)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
||||
@@ -3627,11 +3555,9 @@ static Bitmask codeOneLoopStart(
|
||||
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
|
||||
if( pSubWInfo ){
|
||||
WhereLoop *pSubLoop;
|
||||
int addrExplain = explainOneScan(
|
||||
explainOneScan(
|
||||
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
|
||||
);
|
||||
addScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain);
|
||||
|
||||
/* This is the sub-WHERE clause body. First skip over
|
||||
** duplicate rows from prior sub-WHERE clauses, and record the
|
||||
** rowid (or PRIMARY KEY) for the current row so that the same
|
||||
@@ -3762,10 +3688,6 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
pLevel->addrVisit = sqlite3VdbeCurrentAddr(v);
|
||||
#endif
|
||||
|
||||
/* Insert code to test every subexpression that can be completely
|
||||
** computed using the current set of tables.
|
||||
*/
|
||||
@@ -4016,11 +3938,10 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if all of the following are true:
|
||||
** Return TRUE if both of the following are true:
|
||||
**
|
||||
** (1) X has the same or lower cost that Y
|
||||
** (2) X is a proper subset of Y
|
||||
** (3) X skips at least as many columns as Y
|
||||
**
|
||||
** By "proper subset" we mean that X uses fewer WHERE clause terms
|
||||
** than Y and that every WHERE clause term used by X is also used
|
||||
@@ -4028,9 +3949,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
||||
**
|
||||
** If X is a proper subset of Y then Y is a better choice and ought
|
||||
** to have a lower cost. This routine returns TRUE when that cost
|
||||
** relationship is inverted and needs to be adjusted. The third rule
|
||||
** was added because if X uses skip-scan less than Y it still might
|
||||
** deserve a lower cost even if it is a proper subset of Y.
|
||||
** relationship is inverted and needs to be adjusted.
|
||||
*/
|
||||
static int whereLoopCheaperProperSubset(
|
||||
const WhereLoop *pX, /* First WhereLoop to compare */
|
||||
@@ -4040,7 +3959,6 @@ static int whereLoopCheaperProperSubset(
|
||||
if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){
|
||||
return 0; /* X is not a subset of Y */
|
||||
}
|
||||
if( pY->nSkip > pX->nSkip ) return 0;
|
||||
if( pX->rRun >= pY->rRun ){
|
||||
if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */
|
||||
if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */
|
||||
@@ -4076,7 +3994,9 @@ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
|
||||
if( (p->wsFlags & WHERE_INDEXED)==0 ) continue;
|
||||
if( whereLoopCheaperProperSubset(p, pTemplate) ){
|
||||
/* Adjust pTemplate cost downward so that it is cheaper than its
|
||||
** subset p. */
|
||||
** subset p. Except, do not adjust the cost estimate downward for
|
||||
** a loop that skips more columns. */
|
||||
if( pTemplate->nSkip>p->nSkip ) continue;
|
||||
WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
|
||||
pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1));
|
||||
pTemplate->rRun = p->rRun;
|
||||
@@ -4502,6 +4422,7 @@ static int whereLoopAddBtreeIndex(
|
||||
if( nInMul==0
|
||||
&& pProbe->nSample
|
||||
&& pNew->u.btree.nEq<=pProbe->nSampleCol
|
||||
&& OptimizationEnabled(db, SQLITE_Stat3)
|
||||
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
|
||||
){
|
||||
Expr *pExpr = pTerm->pExpr;
|
||||
@@ -4587,7 +4508,6 @@ static int whereLoopAddBtreeIndex(
|
||||
assert( 42==sqlite3LogEst(18) );
|
||||
if( saved_nEq==saved_nSkip
|
||||
&& saved_nEq+1<pProbe->nKeyCol
|
||||
&& pProbe->noSkipScan==0
|
||||
&& pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
|
||||
&& (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
|
||||
){
|
||||
@@ -6470,10 +6390,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
notReady = ~(Bitmask)0;
|
||||
for(ii=0; ii<nTabList; ii++){
|
||||
int addrExplain;
|
||||
int wsFlags;
|
||||
pLevel = &pWInfo->a[ii];
|
||||
wsFlags = pLevel->pWLoop->wsFlags;
|
||||
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
|
||||
constructAutomaticIndex(pParse, &pWInfo->sWC,
|
||||
@@ -6481,15 +6398,10 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
}
|
||||
#endif
|
||||
addrExplain = explainOneScan(
|
||||
pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags
|
||||
);
|
||||
explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
|
||||
pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
|
||||
notReady = codeOneLoopStart(pWInfo, ii, notReady);
|
||||
pWInfo->iContinue = pLevel->addrCont;
|
||||
if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_ONETABLE_ONLY)==0 ){
|
||||
addScanStatus(v, pTabList, pLevel, addrExplain);
|
||||
}
|
||||
}
|
||||
|
||||
/* Done. */
|
||||
|
||||
@@ -85,9 +85,6 @@ struct WhereLevel {
|
||||
} u;
|
||||
struct WhereLoop *pWLoop; /* The selected WhereLoop object */
|
||||
Bitmask notReady; /* FROM entries not usable at this level */
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
int addrVisit; /* Address at which row is visited */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -462,4 +459,3 @@ struct WhereInfo {
|
||||
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
|
||||
#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
|
||||
#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
|
||||
#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
|
||||
|
||||
+4
-4
@@ -86,23 +86,23 @@ do_test 2.1 {
|
||||
# range.
|
||||
#
|
||||
# Test 3.2 is a little unstable. It depends on the planner estimating
|
||||
# that (b BETWEEN 30 AND 34) will match more rows than (c BETWEEN
|
||||
# that (b BETWEEN 50 AND 54) will match more rows than (c BETWEEN
|
||||
# 800000 AND 900000). Which is a pretty close call (50 vs. 32), so
|
||||
# the planner could get it wrong with an unlucky set of samples. This
|
||||
# case happens to work, but others ("b BETWEEN 40 AND 44" for example)
|
||||
# will fail.
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
SELECT count(*) FROM t1 WHERE b BETWEEN 30 AND 34;
|
||||
SELECT count(*) FROM t1 WHERE b BETWEEN 50 AND 54;
|
||||
SELECT count(*) FROM t1 WHERE c BETWEEN 0 AND 100000;
|
||||
SELECT count(*) FROM t1 WHERE c BETWEEN 800000 AND 900000;
|
||||
} {50 376 32}
|
||||
do_test 3.1 {
|
||||
eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 0 AND 100000}
|
||||
eqp {SELECT * FROM t1 WHERE b BETWEEN 50 AND 54 AND c BETWEEN 0 AND 100000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
do_test 3.2 {
|
||||
eqp {SELECT * FROM t1
|
||||
WHERE b BETWEEN 30 AND 34 AND c BETWEEN 800000 AND 900000}
|
||||
WHERE b BETWEEN 50 AND 54 AND c BETWEEN 800000 AND 900000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
do_test 3.3 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
# 2014-10-24
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing automatic index creation logic,
|
||||
# and specifically creation of automatic partial indexes.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test autoindex4-1.0 {
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1 VALUES(123,'abc'),(234,'def'),(234,'ghi'),(345,'jkl');
|
||||
CREATE TABLE t2(x,y);
|
||||
INSERT INTO t2 VALUES(987,'zyx'),(654,'wvu'),(987,'rqp');
|
||||
|
||||
SELECT *, '|' FROM t1, t2 WHERE a=234 AND x=987 ORDER BY +b;
|
||||
} {234 def 987 rqp | 234 def 987 zyx | 234 ghi 987 rqp | 234 ghi 987 zyx |}
|
||||
do_execsql_test autoindex4-1.1 {
|
||||
SELECT *, '|' FROM t1, t2 WHERE a=234 AND x=555;
|
||||
} {}
|
||||
|
||||
do_execsql_test autoindex4-1.2 {
|
||||
SELECT *, '|' FROM t1 LEFT JOIN t2 ON a=234 AND x=555;
|
||||
} {123 abc {} {} | 234 def {} {} | 234 ghi {} {} | 345 jkl {} {} |}
|
||||
do_execsql_test autoindex4-1.3 {
|
||||
SELECT *, '|' FROM t1 LEFT JOIN t2 ON x=555 WHERE a=234;
|
||||
} {234 def {} {} | 234 ghi {} {} |}
|
||||
do_execsql_test autoindex4-1.4 {
|
||||
SELECT *, '|' FROM t1 LEFT JOIN t2 WHERE a=234 AND x=555;
|
||||
} {}
|
||||
|
||||
|
||||
do_execsql_test autoindex4-2.0 {
|
||||
CREATE TABLE t3(e,f);
|
||||
INSERT INTO t3 VALUES(123,654),(555,444),(234,987);
|
||||
|
||||
SELECT (SELECT count(*) FROM t1, t2 WHERE a=e AND x=f), e, f, '|'
|
||||
FROM t3
|
||||
ORDER BY rowid;
|
||||
} {1 123 654 | 0 555 444 | 4 234 987 |}
|
||||
|
||||
finish_test
|
||||
@@ -217,7 +217,6 @@ foreach nPagePerStep {1 200} {
|
||||
INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000))
|
||||
" $db_dest
|
||||
}
|
||||
execsql COMMIT $db_dest
|
||||
}
|
||||
|
||||
# Backup the source database.
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# 2014 November 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix backup5
|
||||
|
||||
forcedelete test2.db
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(a, b);
|
||||
INSERT INTO t2 VALUES(1, 1);
|
||||
INSERT INTO t2 VALUES(2, 2);
|
||||
INSERT INTO t2 VALUES(3, 3);
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
forcecopy test.db test.db2
|
||||
db eval {
|
||||
DROP TABLE t2;
|
||||
INSERT INTO t1 VALUES(zeroblob(1000), zeroblob(1000));
|
||||
INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000));
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 1.2 {
|
||||
sqlite3 db2 test.db2
|
||||
set stmt [sqlite3_prepare_v2 db2 "SELECT * FROM t2" -1 dummy]
|
||||
sqlite3_step $stmt
|
||||
} {SQLITE_ROW}
|
||||
|
||||
do_test 1.3 {
|
||||
list [catch { sqlite3_backup B db2 main db main } msg] $msg
|
||||
} {1 {sqlite3_backup_init() failed}}
|
||||
|
||||
do_test 1.4 {
|
||||
sqlite3_errmsg db2
|
||||
} {destination database is in use}
|
||||
|
||||
do_test 1.5 {
|
||||
sqlite3_reset $stmt
|
||||
sqlite3_backup B db2 main db main
|
||||
B step 200
|
||||
B finish
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test 1.6 {
|
||||
list [sqlite3_step $stmt] [sqlite3_finalize $stmt]
|
||||
} {SQLITE_ERROR SQLITE_ERROR}
|
||||
|
||||
do_test 1.7 {
|
||||
sqlite3_errmsg db2
|
||||
} {no such table: t2}
|
||||
|
||||
finish_test
|
||||
+3
-3
@@ -912,7 +912,7 @@ do_test capi3-11.9.3 {
|
||||
} 1
|
||||
do_test capi3-11.10 {
|
||||
sqlite3_step $STMT
|
||||
} {SQLITE_ROW}
|
||||
} {SQLITE_ERROR}
|
||||
ifcapable !autoreset {
|
||||
# If SQLITE_OMIT_AUTORESET is defined, then the statement must be
|
||||
# reset() before it can be passed to step() again.
|
||||
@@ -921,11 +921,11 @@ ifcapable !autoreset {
|
||||
}
|
||||
do_test capi3-11.11 {
|
||||
sqlite3_step $STMT
|
||||
} {SQLITE_DONE}
|
||||
} {SQLITE_ROW}
|
||||
do_test capi3-11.12 {
|
||||
sqlite3_step $STMT
|
||||
sqlite3_step $STMT
|
||||
} {SQLITE_ROW}
|
||||
} {SQLITE_DONE}
|
||||
do_test capi3-11.13 {
|
||||
sqlite3_finalize $STMT
|
||||
} {SQLITE_OK}
|
||||
|
||||
+3
-3
@@ -863,7 +863,7 @@ do_test capi3c-11.9.3 {
|
||||
} 1
|
||||
do_test capi3c-11.10 {
|
||||
sqlite3_step $STMT
|
||||
} {SQLITE_ROW}
|
||||
} {SQLITE_ABORT}
|
||||
ifcapable !autoreset {
|
||||
# If SQLITE_OMIT_AUTORESET is defined, then the statement must be
|
||||
# reset() before it can be passed to step() again.
|
||||
@@ -872,11 +872,11 @@ ifcapable !autoreset {
|
||||
}
|
||||
do_test capi3c-11.11 {
|
||||
sqlite3_step $STMT
|
||||
} {SQLITE_DONE}
|
||||
} {SQLITE_ROW}
|
||||
do_test capi3c-11.12 {
|
||||
sqlite3_step $STMT
|
||||
sqlite3_step $STMT
|
||||
} {SQLITE_ROW}
|
||||
} {SQLITE_DONE}
|
||||
do_test capi3c-11.13 {
|
||||
sqlite3_finalize $STMT
|
||||
} {SQLITE_OK}
|
||||
|
||||
@@ -155,6 +155,7 @@ do_execsql_test capi3d-4.1 {
|
||||
}
|
||||
|
||||
do_test capi3d-4.2.1 {
|
||||
breakpoint
|
||||
set ::s1 [sqlite3_prepare_v2 db "ROLLBACK" -1 notused]
|
||||
sqlite3_step $::s1
|
||||
} {SQLITE_DONE}
|
||||
|
||||
@@ -64,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) } {
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
# 2014 October 30
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix e_blobbytes
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE q1(r INTEGER PRIMARY KEY, s TEXT);
|
||||
WITH d(a, b) AS (
|
||||
SELECT 0, ''
|
||||
UNION ALL
|
||||
SELECT a+1, b||'.' FROM d WHERE a<10000
|
||||
)
|
||||
INSERT INTO q1 SELECT * FROM d;
|
||||
}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-07796-55423 Returns the size in bytes of the BLOB
|
||||
# accessible via the successfully opened BLOB handle in its only
|
||||
# argument.
|
||||
#
|
||||
proc check_blob_size {tn rowid bytes} {
|
||||
uplevel [list do_test $tn [subst -nocommands {
|
||||
sqlite3_blob_open db main q1 s $rowid 0 B
|
||||
set res [sqlite3_blob_bytes [set B]]
|
||||
sqlite3_blob_close [set B]
|
||||
set res
|
||||
}] $bytes]
|
||||
}
|
||||
check_blob_size 1.1 43 43
|
||||
check_blob_size 1.2 391 391
|
||||
check_blob_size 1.3 6349 6349
|
||||
check_blob_size 1.4 2621 2621
|
||||
check_blob_size 1.5 7771 7771
|
||||
check_blob_size 1.6 7949 7949
|
||||
check_blob_size 1.7 4374 4374
|
||||
check_blob_size 1.8 2578 2578
|
||||
check_blob_size 1.9 7004 7004
|
||||
check_blob_size 1.10 2180 2180
|
||||
check_blob_size 1.11 3796 3796
|
||||
check_blob_size 1.12 7101 7101
|
||||
check_blob_size 1.13 7449 7449
|
||||
check_blob_size 1.14 7224 7224
|
||||
check_blob_size 1.15 3038 3038
|
||||
check_blob_size 1.16 1083 1083
|
||||
check_blob_size 1.17 5157 5157
|
||||
check_blob_size 1.18 6686 6686
|
||||
check_blob_size 1.19 6592 6592
|
||||
check_blob_size 1.20 0 0
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-53088-19343 The incremental blob I/O routines can only
|
||||
# read or overwriting existing blob content; they cannot change the size
|
||||
# of a blob.
|
||||
#
|
||||
# Also demonstrated in other e_blobXXX.test files.
|
||||
#
|
||||
do_test 2.1 {
|
||||
sqlite3_blob_open db main q1 s 86 1 B
|
||||
list [catch { sqlite3_blob_write $B 86 "1" 1 } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
sqlite3_blob_close $B
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
# 2014 October 30
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix e_blobclose
|
||||
|
||||
set dots [string repeat . 40]
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE x1(a INTEGER PRIMARY KEY, b DOTS);
|
||||
INSERT INTO x1 VALUES(-1, $dots);
|
||||
INSERT INTO x1 VALUES(-10, $dots);
|
||||
INSERT INTO x1 VALUES(-100, $dots);
|
||||
INSERT INTO x1 VALUES(-1000, $dots);
|
||||
INSERT INTO x1 VALUES(-10000, $dots);
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-03145-46390 This function closes an open BLOB handle.
|
||||
#
|
||||
# It's not clear how to test that a blob handle really is closed.
|
||||
# Attempting to use a closed blob handle will likely crash the process.
|
||||
# Assume here that if the SHARED lock on the db file is released,
|
||||
# the blob handle has been closed.
|
||||
#
|
||||
do_execsql_test 1.1 { PRAGMA lock_status } {main unlocked temp closed}
|
||||
sqlite3_blob_open db main x1 b -1 0 B
|
||||
do_execsql_test 1.2 { PRAGMA lock_status } {main shared temp closed}
|
||||
sqlite3_blob_close $B
|
||||
do_execsql_test 1.3 { PRAGMA lock_status } {main unlocked temp closed}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-34027-00617 If the blob handle being closed was opened
|
||||
# for read-write access, and if the database is in auto-commit mode and
|
||||
# there are no other open read-write blob handles or active write
|
||||
# statements, the current transaction is committed.
|
||||
#
|
||||
# 2.1.*: Transaction is not committed if there are other open
|
||||
# read-write blob handles.
|
||||
#
|
||||
# 2.2.*: Transaction is not committed if not in auto-commit mode.
|
||||
#
|
||||
# 2.3.*: Active write statements.
|
||||
#
|
||||
do_test 2.1.1 {
|
||||
sqlite3_blob_open db main x1 b -100 1 B1
|
||||
sqlite3_blob_open db main x1 b -1000 1 B2
|
||||
sqlite3_blob_open db main x1 b -10000 1 B3
|
||||
sqlite3_blob_open db main x1 b -10000 0 B4 ;# B4 is read-only!
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main reserved temp closed}
|
||||
do_test 2.1.2 {
|
||||
sqlite3_blob_close $B1
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main reserved temp closed}
|
||||
do_test 2.1.3 {
|
||||
sqlite3_blob_close $B2
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main reserved temp closed}
|
||||
do_test 2.1.4 {
|
||||
sqlite3_blob_close $B3
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main shared temp closed}
|
||||
do_test 2.1.5 {
|
||||
sqlite3_blob_close $B4
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main unlocked temp closed}
|
||||
|
||||
do_test 2.2.1 {
|
||||
sqlite3_blob_open db main x1 b -100 1 B1
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main reserved temp closed}
|
||||
do_test 2.2.2 {
|
||||
execsql { BEGIN }
|
||||
sqlite3_blob_close $B1
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main reserved temp closed}
|
||||
do_test 2.2.3 {
|
||||
execsql { COMMIT }
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main unlocked temp closed}
|
||||
|
||||
proc val {} {
|
||||
sqlite3_blob_close $::B
|
||||
db eval { PRAGMA lock_status }
|
||||
}
|
||||
db func val val
|
||||
do_test 2.3.1 {
|
||||
sqlite3_blob_open db main x1 b -100 1 B
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main reserved temp closed}
|
||||
do_test 2.3.2 {
|
||||
execsql { INSERT INTO x1 VALUES(15, val()) }
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main unlocked temp closed}
|
||||
do_test 2.3.3 {
|
||||
execsql { SELECT * FROM x1 WHERE a = 15 }
|
||||
} {15 {main reserved temp closed}}
|
||||
|
||||
# A reader does not inhibit commit.
|
||||
do_test 2.3.4 {
|
||||
sqlite3_blob_open db main x1 b -100 1 B
|
||||
execsql { PRAGMA lock_status }
|
||||
} {main reserved temp closed}
|
||||
do_test 2.3.5 {
|
||||
execsql { SELECT a, val() FROM x1 LIMIT 1 }
|
||||
} {-10000 {main shared temp closed}}
|
||||
|
||||
|
||||
do_test 3.1 {
|
||||
sqlite3_blob_open db main x1 b -10 1 B
|
||||
execsql {
|
||||
INSERT INTO x1 VALUES(1, 'abc');
|
||||
SELECT * FROM x1 WHERE a=1;
|
||||
}
|
||||
} {1 abc}
|
||||
do_test 3.2 {
|
||||
sqlite3_blob_write $B 0 "abcdefghij" 10
|
||||
execsql { SELECT * FROM x1 WHERE a=-10 }
|
||||
} {-10 abcdefghij..............................}
|
||||
|
||||
do_test 3.3 {
|
||||
sqlite3 db2 test.db
|
||||
execsql { BEGIN ; SELECT * FROM x1 } db2
|
||||
sqlite3_blob_close $B
|
||||
} {SQLITE_BUSY}
|
||||
|
||||
# EVIDENCE-OF: R-41959-38737 Otherwise, if this function is passed a
|
||||
# valid open blob handle, the values returned by the sqlite3_errcode()
|
||||
# and sqlite3_errmsg() functions are set before returning.
|
||||
#
|
||||
do_test 3.4 {
|
||||
list [sqlite3_errcode db] [sqlite3_errmsg db]
|
||||
} {SQLITE_BUSY {database is locked}}
|
||||
|
||||
# EVIDENCE-OF: R-37801-37633 The BLOB handle is closed unconditionally.
|
||||
# Even if this routine returns an error code, the handle is still
|
||||
# closed.
|
||||
#
|
||||
# Test that the lock has been released. Assume this means the handle
|
||||
# is closed, even though blob_close() returned SQLITE_BUSY.
|
||||
#
|
||||
do_execsql_test 3.4 { PRAGMA lock_status } {main unlocked temp closed}
|
||||
|
||||
# EVIDENCE-OF: R-35111-05628 If an error occurs while committing the
|
||||
# transaction, an error code is returned and the transaction rolled
|
||||
# back.
|
||||
#
|
||||
# Row 1 is removed (it was inserted this transaction) and row -10
|
||||
# is restored to its original state. Transaction has been rolled back.
|
||||
#
|
||||
do_execsql_test 3.5 {
|
||||
SELECT * FROM x1 WHERE a IN (1, -10);
|
||||
} {-10 ........................................}
|
||||
|
||||
# EVIDENCE-OF: R-25894-51060 Calling this routine with a null pointer
|
||||
# (such as would be returned by a failed call to sqlite3_blob_open()) is
|
||||
# a harmless no-op.
|
||||
#
|
||||
do_test 4.0 { sqlite3_blob_close 0 } {}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,549 +0,0 @@
|
||||
# 2014 October 30
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix e_blobopen
|
||||
|
||||
forcedelete test.db2
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
|
||||
CREATE TABLE main.t1(a INTEGER PRIMARY KEY, b TEXT, c BLOB);
|
||||
CREATE TEMP TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c BLOB);
|
||||
CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b TEXT, c BLOB);
|
||||
|
||||
CREATE TABLE main.x1(a INTEGER PRIMARY KEY, b TEXT, c BLOB);
|
||||
CREATE TEMP TABLE x2(a INTEGER PRIMARY KEY, b TEXT, c BLOB);
|
||||
CREATE TABLE aux.x3(a INTEGER PRIMARY KEY, b TEXT, c BLOB);
|
||||
|
||||
INSERT INTO main.t1 VALUES(1, 'main one', X'0101');
|
||||
INSERT INTO main.t1 VALUES(2, 'main two', X'0102');
|
||||
INSERT INTO main.t1 VALUES(3, 'main three', X'0103');
|
||||
INSERT INTO main.t1 VALUES(4, 'main four', X'0104');
|
||||
INSERT INTO main.t1 VALUES(5, 'main five', X'0105');
|
||||
|
||||
INSERT INTO main.x1 VALUES(1, 'x main one', X'000101');
|
||||
INSERT INTO main.x1 VALUES(2, 'x main two', X'000102');
|
||||
INSERT INTO main.x1 VALUES(3, 'x main three', X'000103');
|
||||
INSERT INTO main.x1 VALUES(4, 'x main four', X'000104');
|
||||
INSERT INTO main.x1 VALUES(5, 'x main five', X'000105');
|
||||
|
||||
INSERT INTO temp.t1 VALUES(1, 'temp one', X'0201');
|
||||
INSERT INTO temp.t1 VALUES(2, 'temp two', X'0202');
|
||||
INSERT INTO temp.t1 VALUES(3, 'temp three', X'0203');
|
||||
INSERT INTO temp.t1 VALUES(4, 'temp four', X'0204');
|
||||
INSERT INTO temp.t1 VALUES(5, 'temp five', X'0205');
|
||||
|
||||
INSERT INTO temp.x2 VALUES(1, 'x temp one', X'000201');
|
||||
INSERT INTO temp.x2 VALUES(2, 'x temp two', X'000202');
|
||||
INSERT INTO temp.x2 VALUES(3, 'x temp three', X'000203');
|
||||
INSERT INTO temp.x2 VALUES(4, 'x temp four', X'000204');
|
||||
INSERT INTO temp.x2 VALUES(5, 'x temp five', X'000205');
|
||||
|
||||
INSERT INTO aux.t1 VALUES(1, 'aux one', X'0301');
|
||||
INSERT INTO aux.t1 VALUES(2, 'aux two', X'0302');
|
||||
INSERT INTO aux.t1 VALUES(3, 'aux three', X'0303');
|
||||
INSERT INTO aux.t1 VALUES(4, 'aux four', X'0304');
|
||||
INSERT INTO aux.t1 VALUES(5, 'aux five', X'0305');
|
||||
|
||||
INSERT INTO aux.x3 VALUES(1, 'x aux one', X'000301');
|
||||
INSERT INTO aux.x3 VALUES(2, 'x aux two', X'000302');
|
||||
INSERT INTO aux.x3 VALUES(3, 'x aux three', X'000303');
|
||||
INSERT INTO aux.x3 VALUES(4, 'x aux four', X'000304');
|
||||
INSERT INTO aux.x3 VALUES(5, 'x aux five', X'000305');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-37639-55938 This interfaces opens a handle to the BLOB
|
||||
# located in row iRow, column zColumn, table zTable in database zDb; in
|
||||
# other words, the same BLOB that would be selected by: SELECT zColumn
|
||||
# FROM zDb.zTable WHERE rowid = iRow;
|
||||
#
|
||||
proc read_blob {zDb zTab zCol iRow} {
|
||||
sqlite3_blob_open db $zDb $zTab $zCol $iRow 0 B
|
||||
set nByte [sqlite3_blob_bytes $B]
|
||||
set data [sqlite3_blob_read $B 0 $nByte]
|
||||
sqlite3_blob_close $B
|
||||
return $data
|
||||
}
|
||||
|
||||
do_test 1.1.1 { read_blob main t1 b 1 } "main one"
|
||||
do_test 1.1.2 { read_blob main t1 c 1 } "\01\01"
|
||||
do_test 1.1.3 { read_blob temp t1 b 1 } "temp one"
|
||||
do_test 1.1.4 { read_blob temp t1 c 1 } "\02\01"
|
||||
do_test 1.1.6 { read_blob aux t1 b 1 } "aux one"
|
||||
do_test 1.1.7 { read_blob aux t1 c 1 } "\03\01"
|
||||
|
||||
do_test 1.2.1 { read_blob main t1 b 4 } "main four"
|
||||
do_test 1.2.2 { read_blob main t1 c 4 } "\01\04"
|
||||
do_test 1.2.3 { read_blob temp t1 b 4 } "temp four"
|
||||
do_test 1.2.4 { read_blob temp t1 c 4 } "\02\04"
|
||||
do_test 1.2.6 { read_blob aux t1 b 4 } "aux four"
|
||||
do_test 1.2.7 { read_blob aux t1 c 4 } "\03\04"
|
||||
|
||||
do_test 1.3.1 { read_blob main x1 b 2 } "x main two"
|
||||
do_test 1.3.2 { read_blob main x1 c 2 } "\00\01\02"
|
||||
do_test 1.3.3 { read_blob temp x2 b 2 } "x temp two"
|
||||
do_test 1.3.4 { read_blob temp x2 c 2 } "\00\02\02"
|
||||
do_test 1.3.6 { read_blob aux x3 b 2 } "x aux two"
|
||||
do_test 1.3.7 { read_blob aux x3 c 2 } "\00\03\02"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-27234-05761 Parameter zDb is not the filename that
|
||||
# contains the database, but rather the symbolic name of the database.
|
||||
# For attached databases, this is the name that appears after the AS
|
||||
# keyword in the ATTACH statement. For the main database file, the
|
||||
# database name is "main". For TEMP tables, the database name is "temp".
|
||||
#
|
||||
# The test cases immediately above demonstrate that the database name
|
||||
# for the main db, for TEMP tables and for those in attached databases
|
||||
# is correct. The following tests check that filenames cannot be
|
||||
# used as well.
|
||||
#
|
||||
do_test 2.1 {
|
||||
list [catch { sqlite3_blob_open db "test.db" t1 b 1 0 B } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
do_test 2.2 {
|
||||
list [catch { sqlite3_blob_open db "test.db2" t1 b 1 0 B } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-50854-53979 If the flags parameter is non-zero, then
|
||||
# the BLOB is opened for read and write access.
|
||||
#
|
||||
# EVIDENCE-OF: R-03922-41160 If the flags parameter is zero, the BLOB is
|
||||
# opened for read-only access.
|
||||
#
|
||||
foreach {tn iRow flags} {
|
||||
1 1 0
|
||||
2 2 1
|
||||
3 3 -1
|
||||
4 4 2147483647
|
||||
5 5 -2147483648
|
||||
} {
|
||||
do_test 3.$tn.1 {
|
||||
sqlite3_blob_open db main x1 c $iRow $flags B
|
||||
set n [sqlite3_blob_bytes $B]
|
||||
sqlite3_blob_read $B 0 $n
|
||||
} [binary format ccc 0 1 $iRow]
|
||||
|
||||
if {$flags==0} {
|
||||
# Blob was opened for read-only access - writing returns an error.
|
||||
do_test 3.$tn.2 {
|
||||
list [catch { sqlite3_blob_write $B 0 xxx 3 } msg] $msg
|
||||
} {1 SQLITE_READONLY}
|
||||
|
||||
do_execsql_test 3.$tn.3 {
|
||||
SELECT c FROM x1 WHERE a=$iRow;
|
||||
} [binary format ccc 0 1 $iRow]
|
||||
} else {
|
||||
# Blob was opened for read/write access - writing succeeds
|
||||
do_test 3.$tn.4 {
|
||||
list [catch { sqlite3_blob_write $B 0 xxx 3 } msg] $msg
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 3.$tn.5 {
|
||||
SELECT c FROM x1 WHERE a=$iRow;
|
||||
} {xxx}
|
||||
}
|
||||
|
||||
sqlite3_blob_close $B
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
INSERT INTO t1 VALUES('abcd', 152);
|
||||
INSERT INTO t1 VALUES(NULL, X'00010203');
|
||||
INSERT INTO t1 VALUES('', 154.2);
|
||||
|
||||
CREATE TABLE t2(x PRIMARY KEY, y) WITHOUT ROWID;
|
||||
INSERT INTO t2 VALUES(1, 'blob');
|
||||
|
||||
CREATE TABLE t3(a PRIMARY KEY, b, c, d, e, f, UNIQUE(e, f));
|
||||
INSERT INTO t3 VALUES('aaaa', 'bbbb', 'cccc', 'dddd', 'eeee', 'ffff');
|
||||
CREATE INDEX t3b ON t3(b);
|
||||
|
||||
CREATE TABLE p1(x PRIMARY KEY);
|
||||
INSERT INTO p1 VALUES('abc');
|
||||
|
||||
CREATE TABLE c1(a INTEGER PRIMARY KEY, b REFERENCES p1);
|
||||
INSERT INTO c1 VALUES(45, 'abc');
|
||||
}
|
||||
|
||||
proc test_blob_open {tn zDb zTab zCol iRow flags errcode errmsg} {
|
||||
global B
|
||||
set B "0x1234"
|
||||
|
||||
if {$errcode=="SQLITE_OK"} {
|
||||
set expected "0 {}"
|
||||
} else {
|
||||
set expected "1 $errcode"
|
||||
}
|
||||
|
||||
set ::res [list [
|
||||
catch { sqlite3_blob_open db $zDb $zTab $zCol $iRow $flags B } msg
|
||||
] $msg]
|
||||
do_test 4.$tn.1 { set ::res } $expected
|
||||
|
||||
# EVIDENCE-OF: R-08940-21305 Unless it returns SQLITE_MISUSE, this
|
||||
# function sets the database connection error code and message
|
||||
# accessible via sqlite3_errcode() and sqlite3_errmsg() and related
|
||||
# functions.
|
||||
#
|
||||
# This proc (test_blob_open) is used below to test various error and
|
||||
# non-error conditions. But never SQLITE_MISUSE conditions. So these
|
||||
# test cases are considered as partly verifying the requirement above.
|
||||
# See below for a test of the SQLITE_MISUSE case.
|
||||
#
|
||||
do_test 4.$tn.2 {
|
||||
sqlite3_errcode db
|
||||
} $errcode
|
||||
do_test 4.$tn.3 {
|
||||
sqlite3_errmsg db
|
||||
} $errmsg
|
||||
|
||||
# EVIDENCE-OF: R-31086-35521 On success, SQLITE_OK is returned and the
|
||||
# new BLOB handle is stored in *ppBlob. Otherwise an error code is
|
||||
# returned and, unless the error code is SQLITE_MISUSE, *ppBlob is set
|
||||
# to NULL.
|
||||
#
|
||||
do_test 4.$tn.4 {
|
||||
expr {$B == "0"}
|
||||
} [expr {$errcode != "SQLITE_OK"}]
|
||||
|
||||
# EVIDENCE-OF: R-63421-15521 This means that, provided the API is not
|
||||
# misused, it is always safe to call sqlite3_blob_close() on *ppBlob
|
||||
# after this function it returns.
|
||||
do_test 4.$tn.5 {
|
||||
sqlite3_blob_close $B
|
||||
} {}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-31204-44780 Database zDb does not exist
|
||||
test_blob_open 1 nosuchdb t1 x 1 0 SQLITE_ERROR "no such table: nosuchdb.t1"
|
||||
|
||||
# EVIDENCE-OF: R-28676-08005 Table zTable does not exist within database zDb
|
||||
test_blob_open 2 main tt1 x 1 0 SQLITE_ERROR "no such table: main.tt1"
|
||||
|
||||
# EVIDENCE-OF: R-40134-30296 Table zTable is a WITHOUT ROWID table
|
||||
test_blob_open 3 main t2 y 1 0 SQLITE_ERROR \
|
||||
"cannot open table without rowid: t2"
|
||||
|
||||
# EVIDENCE-OF: R-56376-21261 Column zColumn does not exist
|
||||
test_blob_open 4 main t1 z 2 0 SQLITE_ERROR "no such column: \"z\""
|
||||
|
||||
# EVIDENCE-OF: R-28258-23166 Row iRow is not present in the table
|
||||
test_blob_open 5 main t1 y 6 0 SQLITE_ERROR "no such rowid: 6"
|
||||
|
||||
# EVIDENCE-OF: R-11683-62380 The specified column of row iRow contains a
|
||||
# value that is not a TEXT or BLOB value
|
||||
test_blob_open 6 main t1 x 2 0 SQLITE_ERROR "cannot open value of type null"
|
||||
test_blob_open 7 main t1 y 1 0 SQLITE_ERROR "cannot open value of type integer"
|
||||
test_blob_open 8 main t1 y 3 0 SQLITE_ERROR "cannot open value of type real"
|
||||
|
||||
# EVIDENCE-OF: R-34146-30782 Column zColumn is part of an index, PRIMARY
|
||||
# KEY or UNIQUE constraint and the blob is being opened for read/write
|
||||
# access
|
||||
#
|
||||
# Test cases 8.1.* show that such columns can be opened for read-access.
|
||||
# Tests 8.2.* show that read-write access is different. Columns "c" and "c"
|
||||
# are not part of an index, PK or UNIQUE constraint, so they work in both
|
||||
# cases.
|
||||
#
|
||||
test_blob_open 8.1.1 main t3 a 1 0 SQLITE_OK "not an error"
|
||||
test_blob_open 8.1.2 main t3 b 1 0 SQLITE_OK "not an error"
|
||||
test_blob_open 8.1.3 main t3 c 1 0 SQLITE_OK "not an error"
|
||||
test_blob_open 8.1.4 main t3 d 1 0 SQLITE_OK "not an error"
|
||||
test_blob_open 8.1.5 main t3 e 1 0 SQLITE_OK "not an error"
|
||||
test_blob_open 8.1.6 main t3 f 1 0 SQLITE_OK "not an error"
|
||||
|
||||
set cannot "cannot open indexed column for writing"
|
||||
test_blob_open 8.2.1 main t3 a 1 8 SQLITE_ERROR $cannot
|
||||
test_blob_open 8.2.2 main t3 b 1 8 SQLITE_ERROR $cannot
|
||||
test_blob_open 8.2.3 main t3 c 1 8 SQLITE_OK "not an error"
|
||||
test_blob_open 8.2.4 main t3 d 1 8 SQLITE_OK "not an error"
|
||||
test_blob_open 8.2.5 main t3 e 1 8 SQLITE_ERROR $cannot
|
||||
test_blob_open 8.2.6 main t3 f 1 8 SQLITE_ERROR $cannot
|
||||
|
||||
# EVIDENCE-OF: R-50117-55204 Foreign key constraints are enabled, column
|
||||
# zColumn is part of a child key definition and the blob is being opened
|
||||
# for read/write access
|
||||
#
|
||||
# 9.1: FK disabled, read-only access.
|
||||
# 9.2: FK disabled, read-only access.
|
||||
# 9.3: FK enabled, read/write access.
|
||||
# 9.4: FK enabled, read/write access.
|
||||
#
|
||||
test_blob_open 9.1 main c1 b 45 0 SQLITE_OK "not an error"
|
||||
test_blob_open 9.2 main c1 b 45 1 SQLITE_OK "not an error"
|
||||
execsql { PRAGMA foreign_keys = ON }
|
||||
test_blob_open 9.3 main c1 b 45 0 SQLITE_OK "not an error"
|
||||
test_blob_open 9.4 main c1 b 45 1 SQLITE_ERROR \
|
||||
"cannot open foreign key column for writing"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-08940-21305 Unless it returns SQLITE_MISUSE, this
|
||||
# function sets the database connection error code and message
|
||||
# accessible via sqlite3_errcode() and sqlite3_errmsg() and related
|
||||
# functions.
|
||||
#
|
||||
# This requirement is partially verified by the many uses of test
|
||||
# command [test_blob_open] above. All that is left is to verify the
|
||||
# SQLITE_MISUSE case.
|
||||
#
|
||||
# SQLITE_MISUSE is only returned if SQLITE_ENABLE_API_ARMOR is defined
|
||||
# during compilation.
|
||||
#
|
||||
ifcapable api_armor {
|
||||
sqlite3_blob_open db main t1 x 1 0 B
|
||||
|
||||
do_test 10.1.1 {
|
||||
list [catch {sqlite3_blob_open $B main t1 x 1 0 B2} msg] $msg
|
||||
} {1 SQLITE_MISUSE}
|
||||
do_test 10.1.2 {
|
||||
list [sqlite3_errcode db] [sqlite3_errmsg db]
|
||||
} {SQLITE_OK {not an error}}
|
||||
sqlite3_blob_close $B
|
||||
|
||||
do_test 10.2.1 {
|
||||
list [catch {sqlite3_blob_open db main {} x 1 0 B} msg] $msg
|
||||
} {1 SQLITE_MISUSE}
|
||||
do_test 10.2.2 {
|
||||
list [sqlite3_errcode db] [sqlite3_errmsg db]
|
||||
} {SQLITE_OK {not an error}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-50542-62589 If the row that a BLOB handle points to is
|
||||
# modified by an UPDATE, DELETE, or by ON CONFLICT side-effects then the
|
||||
# BLOB handle is marked as "expired". This is true if any column of the
|
||||
# row is changed, even a column other than the one the BLOB handle is
|
||||
# open on.
|
||||
#
|
||||
# EVIDENCE-OF: R-48367-20048 Calls to sqlite3_blob_read() and
|
||||
# sqlite3_blob_write() for an expired BLOB handle fail with a return
|
||||
# code of SQLITE_ABORT.
|
||||
#
|
||||
# 11.2: read-only handle, DELETE.
|
||||
# 11.3: read-only handle, UPDATE.
|
||||
# 11.4: read-only handle, REPLACE.
|
||||
# 11.5: read/write handle, DELETE.
|
||||
# 11.6: read/write handle, UPDATE.
|
||||
# 11.7: read/write handle, REPLACE.
|
||||
#
|
||||
do_execsql_test 11.1 {
|
||||
CREATE TABLE b1(a INTEGER PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO b1 VALUES(1, '1234567890', 1);
|
||||
INSERT INTO b1 VALUES(2, '1234567890', 2);
|
||||
INSERT INTO b1 VALUES(3, '1234567890', 3);
|
||||
INSERT INTO b1 VALUES(4, '1234567890', 4);
|
||||
INSERT INTO b1 VALUES(5, '1234567890', 5);
|
||||
INSERT INTO b1 VALUES(6, '1234567890', 6);
|
||||
|
||||
CREATE TABLE b2(a INTEGER PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO b2 VALUES(1, '1234567890', 1);
|
||||
INSERT INTO b2 VALUES(2, '1234567890', 2);
|
||||
INSERT INTO b2 VALUES(3, '1234567890', 3);
|
||||
INSERT INTO b2 VALUES(4, '1234567890', 4);
|
||||
INSERT INTO b2 VALUES(5, '1234567890', 5);
|
||||
INSERT INTO b2 VALUES(6, '1234567890', 6);
|
||||
}
|
||||
|
||||
do_test 11.2.1 {
|
||||
sqlite3_blob_open db main b1 b 2 0 B
|
||||
sqlite3_blob_read $B 0 10
|
||||
} {1234567890}
|
||||
do_test 11.2.2 {
|
||||
# Deleting a different row does not invalidate the blob handle.
|
||||
execsql { DELETE FROM b1 WHERE a = 1 }
|
||||
sqlite3_blob_read $B 0 10
|
||||
} {1234567890}
|
||||
do_test 11.2.3 {
|
||||
execsql { DELETE FROM b1 WHERE a = 2 }
|
||||
list [catch { sqlite3_blob_read $B 0 10 } msg] $msg
|
||||
} {1 SQLITE_ABORT}
|
||||
do_test 11.2.4 {
|
||||
sqlite3_blob_close $B
|
||||
} {}
|
||||
|
||||
do_test 11.3.1 {
|
||||
sqlite3_blob_open db main b1 b 3 0 B
|
||||
sqlite3_blob_read $B 0 10
|
||||
} {1234567890}
|
||||
do_test 11.3.2 {
|
||||
# Updating a different row
|
||||
execsql { UPDATE b1 SET c = 42 WHERE a=4 }
|
||||
sqlite3_blob_read $B 0 10
|
||||
} {1234567890}
|
||||
do_test 11.3.3 {
|
||||
execsql { UPDATE b1 SET c = 43 WHERE a=3 }
|
||||
list [catch { sqlite3_blob_read $B 0 10 } msg] $msg
|
||||
} {1 SQLITE_ABORT}
|
||||
do_test 11.3.4 {
|
||||
sqlite3_blob_close $B
|
||||
} {}
|
||||
|
||||
do_test 11.4.1 {
|
||||
sqlite3_blob_open db main b1 b 6 0 B
|
||||
sqlite3_blob_read $B 0 10
|
||||
} {1234567890}
|
||||
do_test 11.4.2 {
|
||||
# Replace a different row
|
||||
execsql { INSERT OR REPLACE INTO b1 VALUES(10, 'abcdefghij', 5) }
|
||||
sqlite3_blob_read $B 0 10
|
||||
} {1234567890}
|
||||
do_test 11.4.3 {
|
||||
execsql { INSERT OR REPLACE INTO b1 VALUES(11, 'abcdefghij', 6) }
|
||||
list [catch { sqlite3_blob_read $B 0 10 } msg] $msg
|
||||
} {1 SQLITE_ABORT}
|
||||
do_test 11.4.4 {
|
||||
sqlite3_blob_close $B
|
||||
} {}
|
||||
|
||||
do_test 11.4.1 {
|
||||
sqlite3_blob_open db main b2 b 2 1 B
|
||||
sqlite3_blob_write $B 0 "abcdefghij"
|
||||
} {}
|
||||
do_test 11.4.2 {
|
||||
# Deleting a different row does not invalidate the blob handle.
|
||||
execsql { DELETE FROM b2 WHERE a = 1 }
|
||||
sqlite3_blob_write $B 0 "ABCDEFGHIJ"
|
||||
} {}
|
||||
do_test 11.4.3 {
|
||||
execsql { DELETE FROM b2 WHERE a = 2 }
|
||||
list [catch { sqlite3_blob_write $B 0 "0987654321" } msg] $msg
|
||||
} {1 SQLITE_ABORT}
|
||||
do_test 11.4.4 {
|
||||
sqlite3_blob_close $B
|
||||
} {}
|
||||
|
||||
do_test 11.5.1 {
|
||||
sqlite3_blob_open db main b2 b 3 1 B
|
||||
sqlite3_blob_write $B 0 "abcdefghij"
|
||||
} {}
|
||||
do_test 11.5.2 {
|
||||
# Updating a different row
|
||||
execsql { UPDATE b2 SET c = 42 WHERE a=4 }
|
||||
sqlite3_blob_write $B 0 "ABCDEFGHIJ"
|
||||
} {}
|
||||
do_test 11.5.3 {
|
||||
execsql { UPDATE b2 SET c = 43 WHERE a=3 }
|
||||
list [catch { sqlite3_blob_write $B 0 "0987654321" } msg] $msg
|
||||
} {1 SQLITE_ABORT}
|
||||
do_test 11.5.4 {
|
||||
sqlite3_blob_close $B
|
||||
} {}
|
||||
|
||||
do_test 11.6.1 {
|
||||
sqlite3_blob_open db main b2 b 6 1 B
|
||||
sqlite3_blob_write $B 0 "abcdefghij"
|
||||
} {}
|
||||
do_test 11.6.2 {
|
||||
# Replace a different row
|
||||
execsql { INSERT OR REPLACE INTO b2 VALUES(10, 'abcdefghij', 5) }
|
||||
sqlite3_blob_write $B 0 "ABCDEFGHIJ"
|
||||
} {}
|
||||
do_test 11.6.3 {
|
||||
execsql { INSERT OR REPLACE INTO b2 VALUES(11, 'abcdefghij', 6) }
|
||||
list [catch { sqlite3_blob_write $B 0 "0987654321" } msg] $msg
|
||||
} {1 SQLITE_ABORT}
|
||||
do_test 11.6.4 {
|
||||
sqlite3_blob_close $B
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-45408-40694 Changes written into a BLOB prior to the
|
||||
# BLOB expiring are not rolled back by the expiration of the BLOB. Such
|
||||
# changes will eventually commit if the transaction continues to
|
||||
# completion.
|
||||
#
|
||||
do_execsql_test 12.1 {
|
||||
CREATE TABLE b3(x INTEGER PRIMARY KEY, y TEXT, z INTEGER);
|
||||
INSERT INTO b3 VALUES(22, '..........', NULL);
|
||||
}
|
||||
do_test 12.2 {
|
||||
sqlite3_blob_open db main b3 y 22 1 B
|
||||
sqlite3_blob_write $B 0 "xxxxx" 5
|
||||
} {}
|
||||
do_execsql_test 12.3 {
|
||||
UPDATE b3 SET z = 'not null';
|
||||
}
|
||||
do_test 12.4 {
|
||||
list [catch {sqlite3_blob_write $B 5 "xxxxx" 5} msg] $msg
|
||||
} {1 SQLITE_ABORT}
|
||||
do_execsql_test 12.5 {
|
||||
SELECT * FROM b3;
|
||||
} {22 xxxxx..... {not null}}
|
||||
do_test 12.5 {
|
||||
sqlite3_blob_close $B
|
||||
} {}
|
||||
do_execsql_test 12.6 {
|
||||
SELECT * FROM b3;
|
||||
} {22 xxxxx..... {not null}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-58813-55036 The sqlite3_bind_zeroblob() and
|
||||
# sqlite3_result_zeroblob() interfaces and the built-in zeroblob SQL
|
||||
# function may be used to create a zero-filled blob to read or write
|
||||
# using the incremental-blob interface.
|
||||
#
|
||||
do_execsql_test 13.1 {
|
||||
CREATE TABLE c2(i INTEGER PRIMARY KEY, j);
|
||||
INSERT INTO c2 VALUES(10, zeroblob(24));
|
||||
}
|
||||
|
||||
do_test 13.2 {
|
||||
set stmt [sqlite3_prepare_v2 db "INSERT INTO c2 VALUES(11, ?)" -1]
|
||||
sqlite3_bind_zeroblob $stmt 1 45
|
||||
sqlite3_step $stmt
|
||||
sqlite3_finalize $stmt
|
||||
} {SQLITE_OK}
|
||||
|
||||
# The blobs can be read:
|
||||
#
|
||||
do_test 13.3.1 {
|
||||
sqlite3_blob_open db main c2 j 10 1 B
|
||||
sqlite3_blob_open db main c2 j 11 1 B2
|
||||
list [sqlite3_blob_bytes $B] [sqlite3_blob_bytes $B2]
|
||||
} {24 45}
|
||||
do_test 13.3.2 {
|
||||
sqlite3_blob_read $B 0 24
|
||||
} [string repeat [binary format c 0] 24]
|
||||
do_test 13.3.3 {
|
||||
sqlite3_blob_read $B2 0 45
|
||||
} [string repeat [binary format c 0] 45]
|
||||
|
||||
# And also written:
|
||||
#
|
||||
do_test 13.4.1 {
|
||||
sqlite3_blob_write $B 0 [string repeat [binary format c 1] 24]
|
||||
} {}
|
||||
do_test 13.4.2 {
|
||||
sqlite3_blob_write $B2 0 [string repeat [binary format c 1] 45]
|
||||
} {}
|
||||
do_test 13.5 {
|
||||
sqlite3_blob_close $B
|
||||
sqlite3_blob_close $B2
|
||||
execsql { SELECT j FROM c2 }
|
||||
} [list \
|
||||
[string repeat [binary format c 1] 24] \
|
||||
[string repeat [binary format c 1] 45] \
|
||||
]
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
# 2014 October 30
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix e_blobwrite
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-62898-22698 This function is used to write data into an
|
||||
# open BLOB handle from a caller-supplied buffer. N bytes of data are
|
||||
# copied from the buffer Z into the open BLOB, starting at offset
|
||||
# iOffset.
|
||||
#
|
||||
set dots [string repeat . 40]
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, t TEXT);
|
||||
INSERT INTO t1 VALUES(-1, $dots);
|
||||
INSERT INTO t1 VALUES(-2, $dots);
|
||||
INSERT INTO t1 VALUES(-3, $dots);
|
||||
INSERT INTO t1 VALUES(-4, $dots);
|
||||
INSERT INTO t1 VALUES(-5, $dots);
|
||||
INSERT INTO t1 VALUES(-6, $dots);
|
||||
}
|
||||
|
||||
proc blob_write_test {tn id iOffset blob nData final} {
|
||||
sqlite3_blob_open db main t1 t $id 1 B
|
||||
|
||||
# EVIDENCE-OF: R-45864-01884 On success, sqlite3_blob_write() returns
|
||||
# SQLITE_OK. Otherwise, an error code or an extended error code is
|
||||
# returned.
|
||||
#
|
||||
# This block tests the SQLITE_OK case in the requirement above (the
|
||||
# Tcl sqlite3_blob_write() wrapper uses an empty string in place of
|
||||
# "SQLITE_OK"). The error cases are tested by the "blob_write_error_test"
|
||||
# tests below.
|
||||
#
|
||||
set res [sqlite3_blob_write $B $iOffset $blob $nData]
|
||||
uplevel [list do_test $tn.1 [list set {} $res] {}]
|
||||
|
||||
sqlite3_blob_close $B
|
||||
uplevel [list do_execsql_test $tn.3 "SELECT t FROM t1 WHERE a=$id" $final]
|
||||
}
|
||||
|
||||
set blob "0123456789012345678901234567890123456789"
|
||||
blob_write_test 1.1 -1 0 $blob 10 { 0123456789.............................. }
|
||||
blob_write_test 1.2 -2 8 $blob 10 { ........0123456789...................... }
|
||||
blob_write_test 1.3 -3 8 $blob 1 { ........0............................... }
|
||||
blob_write_test 1.4 -4 18 $blob 22 { ..................0123456789012345678901 }
|
||||
blob_write_test 1.5 -5 18 $blob 0 { ........................................ }
|
||||
blob_write_test 1.6 -6 0 $blob 40 { 0123456789012345678901234567890123456789 }
|
||||
|
||||
|
||||
proc blob_write_error_test {tn B iOffset blob nData errcode errmsg} {
|
||||
|
||||
# In cases where the underlying sqlite3_blob_write() function returns
|
||||
# SQLITE_OK, the Tcl wrapper returns an empty string. If the underlying
|
||||
# function returns an error, the Tcl wrapper throws an exception with
|
||||
# the error code as the Tcl exception message.
|
||||
#
|
||||
if {$errcode=="SQLITE_OK"} {
|
||||
set ret ""
|
||||
set isError 0
|
||||
} else {
|
||||
set ret $errcode
|
||||
set isError 1
|
||||
}
|
||||
|
||||
set cmd [list sqlite3_blob_write $B $iOffset $blob $nData]
|
||||
uplevel [list do_test $tn.1 [subst -nocommands {
|
||||
list [catch {$cmd} msg] [set msg]
|
||||
}] [list $isError $ret]]
|
||||
|
||||
# EVIDENCE-OF: R-34782-18311 Unless SQLITE_MISUSE is returned, this
|
||||
# function sets the database connection error code and message
|
||||
# accessible via sqlite3_errcode() and sqlite3_errmsg() and related
|
||||
# functions.
|
||||
#
|
||||
if {$errcode == "SQLITE_MISUSE"} { error "test proc misuse!" }
|
||||
uplevel [list do_test $tn.2 [list sqlite3_errcode db] $errcode]
|
||||
uplevel [list do_test $tn.3 [list sqlite3_errmsg db] $errmsg]
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t2(a TEXT, b INTEGER PRIMARY KEY);
|
||||
INSERT INTO t2 VALUES($dots, 43);
|
||||
INSERT INTO t2 VALUES($dots, 44);
|
||||
INSERT INTO t2 VALUES($dots, 45);
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-63341-57517 If the BLOB handle passed as the first
|
||||
# argument was not opened for writing (the flags parameter to
|
||||
# sqlite3_blob_open() was zero), this function returns SQLITE_READONLY.
|
||||
#
|
||||
sqlite3_blob_open db main t2 a 43 0 B
|
||||
blob_write_error_test 2.1 $B 0 $blob 10 \
|
||||
SQLITE_READONLY {attempt to write a readonly database}
|
||||
sqlite3_blob_close $B
|
||||
|
||||
# EVIDENCE-OF: R-29804-27366 If offset iOffset is less than N bytes from
|
||||
# the end of the BLOB, SQLITE_ERROR is returned and no data is written.
|
||||
#
|
||||
sqlite3_blob_open db main t2 a 44 3 B
|
||||
blob_write_error_test 2.2.1 $B 31 $blob 10 \
|
||||
SQLITE_ERROR {SQL logic error or missing database}
|
||||
|
||||
# Make a successful write to the blob handle. This shows that the
|
||||
# sqlite3_errcode() and sqlite3_errmsg() values are set even if the
|
||||
# blob_write() call succeeds (see requirement in the [blob_write_error_test]
|
||||
# proc).
|
||||
blob_write_error_test 2.2.1 $B 30 $blob 10 SQLITE_OK {not an error}
|
||||
|
||||
# EVIDENCE-OF: R-58570-38916 If N or iOffset are less than zero
|
||||
# SQLITE_ERROR is returned and no data is written.
|
||||
#
|
||||
blob_write_error_test 2.2.2 $B 31 $blob -1 \
|
||||
SQLITE_ERROR {SQL logic error or missing database}
|
||||
blob_write_error_test 2.2.3 $B 20 $blob 10 SQLITE_OK {not an error}
|
||||
blob_write_error_test 2.2.4 $B -1 $blob 10 \
|
||||
SQLITE_ERROR {SQL logic error or missing database}
|
||||
sqlite3_blob_close $B
|
||||
|
||||
# EVIDENCE-OF: R-20958-54138 An attempt to write to an expired BLOB
|
||||
# handle fails with an error code of SQLITE_ABORT.
|
||||
#
|
||||
do_test 2.3 {
|
||||
sqlite3_blob_open db main t2 a 43 0 B
|
||||
execsql { DELETE FROM t2 WHERE b=43 }
|
||||
} {}
|
||||
blob_write_error_test 2.3.1 $B 5 $blob 5 \
|
||||
SQLITE_ABORT {callback requested query abort}
|
||||
do_test 2.3.2 {
|
||||
execsql { SELECT 1, 2, 3 }
|
||||
sqlite3_errcode db
|
||||
} {SQLITE_OK}
|
||||
blob_write_error_test 2.3.3 $B 5 $blob 5 \
|
||||
SQLITE_ABORT {callback requested query abort}
|
||||
sqlite3_blob_close $B
|
||||
|
||||
# EVIDENCE-OF: R-08382-59936 Writes to the BLOB that occurred before the
|
||||
# BLOB handle expired are not rolled back by the expiration of the
|
||||
# handle, though of course those changes might have been overwritten by
|
||||
# the statement that expired the BLOB handle or by other independent
|
||||
# statements.
|
||||
#
|
||||
# 3.1.*: not rolled back,
|
||||
# 3.2.*: overwritten.
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t3(i INTEGER PRIMARY KEY, j TEXT, k TEXT);
|
||||
INSERT INTO t3 VALUES(1, $dots, $dots);
|
||||
INSERT INTO t3 VALUES(2, $dots, $dots);
|
||||
SELECT * FROM t3 WHERE i=1;
|
||||
} {
|
||||
1
|
||||
........................................
|
||||
........................................
|
||||
}
|
||||
sqlite3_blob_open db main t3 j 1 1 B
|
||||
blob_write_error_test 3.1.1 $B 5 $blob 10 SQLITE_OK {not an error}
|
||||
do_execsql_test 3.1.2 {
|
||||
UPDATE t3 SET k = 'xyz' WHERE i=1;
|
||||
SELECT * FROM t3 WHERE i=1;
|
||||
} {
|
||||
1 .....0123456789......................... xyz
|
||||
}
|
||||
blob_write_error_test 3.1.3 $B 15 $blob 10 \
|
||||
SQLITE_ABORT {callback requested query abort}
|
||||
sqlite3_blob_close $B
|
||||
do_execsql_test 3.1.4 {
|
||||
SELECT * FROM t3 WHERE i=1;
|
||||
} {
|
||||
1 .....0123456789......................... xyz
|
||||
}
|
||||
|
||||
sqlite3_blob_open db main t3 j 2 1 B
|
||||
blob_write_error_test 3.2.1 $B 5 $blob 10 SQLITE_OK {not an error}
|
||||
do_execsql_test 3.2.2 {
|
||||
UPDATE t3 SET j = 'xyz' WHERE i=2;
|
||||
SELECT * FROM t3 WHERE i=2;
|
||||
} {
|
||||
2 xyz ........................................
|
||||
}
|
||||
blob_write_error_test 3.2.3 $B 15 $blob 10 \
|
||||
SQLITE_ABORT {callback requested query abort}
|
||||
sqlite3_blob_close $B
|
||||
do_execsql_test 3.2.4 {
|
||||
SELECT * FROM t3 WHERE i=2;
|
||||
} {
|
||||
2 xyz ........................................
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,441 +0,0 @@
|
||||
# 2011 October 28
|
||||
#
|
||||
# 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 e_changes
|
||||
|
||||
# Like [do_execsql_test], except it appends the value returned by
|
||||
# [db changes] to the result of executing the SQL script.
|
||||
#
|
||||
proc do_changes_test {tn sql res} {
|
||||
uplevel [list \
|
||||
do_test $tn "concat \[execsql {$sql}\] \[db changes\]" $res
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-15996-49369 This function returns the number of rows
|
||||
# modified, inserted or deleted by the most recently completed INSERT,
|
||||
# UPDATE or DELETE statement on the database connection specified by the
|
||||
# only parameter.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID;
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
CREATE INDEX i2 ON t2(y);
|
||||
}
|
||||
foreach {tn schema} {
|
||||
1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
}
|
||||
2 {
|
||||
CREATE TABLE t1(a, b, PRIMARY KEY(a, b)) WITHOUT ROWID;
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
}
|
||||
} {
|
||||
reset_db
|
||||
execsql $schema
|
||||
|
||||
# Insert 1 row.
|
||||
do_changes_test 1.$tn.1 { INSERT INTO t1 VALUES(0, 0) } 1
|
||||
|
||||
# Insert 10 rows.
|
||||
do_changes_test 1.$tn.2 {
|
||||
WITH rows(i, j) AS (
|
||||
SELECT 1, 1 UNION ALL SELECT i+1, j+i FROM rows WHERE i<10
|
||||
)
|
||||
INSERT INTO t1 SELECT * FROM rows
|
||||
} 10
|
||||
|
||||
# Modify 5 rows.
|
||||
do_changes_test 1.$tn.3 {
|
||||
UPDATE t1 SET b=b+1 WHERE a<5;
|
||||
} 5
|
||||
|
||||
# Delete 4 rows
|
||||
do_changes_test 1.$tn.4 {
|
||||
DELETE FROM t1 WHERE a>6
|
||||
} 4
|
||||
|
||||
# Check the "on the database connecton specified" part of hte
|
||||
# requirement - changes made by other connections do not show up in
|
||||
# the return value of sqlite3_changes().
|
||||
do_test 1.$tn.5 {
|
||||
sqlite3 db2 test.db
|
||||
execsql { INSERT INTO t1 VALUES(-1, -1) } db2
|
||||
db2 changes
|
||||
} 1
|
||||
do_test 1.$tn.6 {
|
||||
db changes
|
||||
} 4
|
||||
db2 close
|
||||
|
||||
# Test that statements that modify no rows because they hit UNIQUE
|
||||
# constraints set the sqlite3_changes() value to 0. Regardless of
|
||||
# whether or not they are executed inside an explicit transaction.
|
||||
#
|
||||
# 1.$tn.8-9: outside of a transaction
|
||||
# 1.$tn.10-12: inside a transaction
|
||||
#
|
||||
do_changes_test 1.$tn.7 {
|
||||
CREATE UNIQUE INDEX i2 ON t1(a);
|
||||
} 4
|
||||
do_catchsql_test 1.$tn.8 {
|
||||
INSERT INTO t1 VALUES('a', 0), ('b', 0), ('c', 0), (0, 11);
|
||||
} {1 {UNIQUE constraint failed: t1.a}}
|
||||
do_test 1.$tn.9 { db changes } 0
|
||||
do_catchsql_test 1.$tn.10 {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES('a', 0), ('b', 0), ('c', 0), (0, 11);
|
||||
} {1 {UNIQUE constraint failed: t1.a}}
|
||||
do_test 1.$tn.11 { db changes } 0
|
||||
do_changes_test 1.$tn.12 COMMIT 0
|
||||
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-44877-05564 Executing any other type of SQL statement
|
||||
# does not modify the value returned by this function.
|
||||
#
|
||||
reset_db
|
||||
do_changes_test 2.1 { CREATE TABLE t1(x) } 0
|
||||
do_changes_test 2.2 {
|
||||
WITH d(y) AS (SELECT 1 UNION ALL SELECT y+1 FROM d WHERE y<47)
|
||||
INSERT INTO t1 SELECT y FROM d;
|
||||
} 47
|
||||
|
||||
# The statement above set changes() to 47. Check that none of the following
|
||||
# modify this.
|
||||
do_changes_test 2.3 { SELECT count(x) FROM t1 } {47 47}
|
||||
do_changes_test 2.4 { DROP TABLE t1 } 47
|
||||
do_changes_test 2.5 { CREATE TABLE t1(x) } 47
|
||||
do_changes_test 2.6 { ALTER TABLE t1 ADD COLUMN b } 47
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-53938-27527 Only changes made directly by the INSERT,
|
||||
# UPDATE or DELETE statement are considered - auxiliary changes caused
|
||||
# by triggers, foreign key actions or REPLACE constraint resolution are
|
||||
# not counted.
|
||||
#
|
||||
# 3.1.*: triggers
|
||||
# 3.2.*: foreign key actions
|
||||
# 3.3.*: replace constraints
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.1.0 {
|
||||
CREATE TABLE log(x);
|
||||
CREATE TABLE p1(one PRIMARY KEY, two);
|
||||
|
||||
CREATE TRIGGER tr_ai AFTER INSERT ON p1 BEGIN
|
||||
INSERT INTO log VALUES('insert');
|
||||
END;
|
||||
CREATE TRIGGER tr_bd BEFORE DELETE ON p1 BEGIN
|
||||
INSERT INTO log VALUES('delete');
|
||||
END;
|
||||
CREATE TRIGGER tr_au AFTER UPDATE ON p1 BEGIN
|
||||
INSERT INTO log VALUES('update');
|
||||
END;
|
||||
|
||||
}
|
||||
|
||||
do_changes_test 3.1.1 {
|
||||
INSERT INTO p1 VALUES('a', 'A'), ('b', 'B'), ('c', 'C');
|
||||
} 3
|
||||
do_changes_test 3.1.2 {
|
||||
UPDATE p1 SET two = two||two;
|
||||
} 3
|
||||
do_changes_test 3.1.3 {
|
||||
DELETE FROM p1 WHERE one IN ('a', 'c');
|
||||
} 2
|
||||
do_execsql_test 3.1.4 {
|
||||
-- None of the inserts on table log were counted.
|
||||
SELECT count(*) FROM log
|
||||
} 8
|
||||
|
||||
do_execsql_test 3.2.0 {
|
||||
DELETE FROM p1;
|
||||
INSERT INTO p1 VALUES('a', 'A'), ('b', 'B'), ('c', 'C');
|
||||
|
||||
CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET NULL);
|
||||
CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET DEFAULT);
|
||||
CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE CASCADE);
|
||||
INSERT INTO c1 VALUES('a', 'aaa');
|
||||
INSERT INTO c2 VALUES('b', 'bbb');
|
||||
INSERT INTO c3 VALUES('c', 'ccc');
|
||||
|
||||
INSERT INTO p1 VALUES('d', 'D'), ('e', 'E'), ('f', 'F');
|
||||
CREATE TABLE c4(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET NULL);
|
||||
CREATE TABLE c5(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET DEFAULT);
|
||||
CREATE TABLE c6(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE CASCADE);
|
||||
INSERT INTO c4 VALUES('d', 'aaa');
|
||||
INSERT INTO c5 VALUES('e', 'bbb');
|
||||
INSERT INTO c6 VALUES('f', 'ccc');
|
||||
|
||||
PRAGMA foreign_keys = ON;
|
||||
}
|
||||
|
||||
do_changes_test 3.2.1 { DELETE FROM p1 WHERE one = 'a' } 1
|
||||
do_changes_test 3.2.2 { DELETE FROM p1 WHERE one = 'b' } 1
|
||||
do_changes_test 3.2.3 { DELETE FROM p1 WHERE one = 'c' } 1
|
||||
do_execsql_test 3.2.4 {
|
||||
SELECT * FROM c1;
|
||||
SELECT * FROM c2;
|
||||
SELECT * FROM c3;
|
||||
} {{} aaa {} bbb}
|
||||
|
||||
do_changes_test 3.2.5 { UPDATE p1 SET one = 'g' WHERE one = 'd' } 1
|
||||
do_changes_test 3.2.6 { UPDATE p1 SET one = 'h' WHERE one = 'e' } 1
|
||||
do_changes_test 3.2.7 { UPDATE p1 SET one = 'i' WHERE one = 'f' } 1
|
||||
do_execsql_test 3.2.8 {
|
||||
SELECT * FROM c4;
|
||||
SELECT * FROM c5;
|
||||
SELECT * FROM c6;
|
||||
} {{} aaa {} bbb i ccc}
|
||||
|
||||
do_execsql_test 3.3.0 {
|
||||
CREATE TABLE r1(a UNIQUE, b UNIQUE);
|
||||
INSERT INTO r1 VALUES('i', 'i');
|
||||
INSERT INTO r1 VALUES('ii', 'ii');
|
||||
INSERT INTO r1 VALUES('iii', 'iii');
|
||||
INSERT INTO r1 VALUES('iv', 'iv');
|
||||
INSERT INTO r1 VALUES('v', 'v');
|
||||
INSERT INTO r1 VALUES('vi', 'vi');
|
||||
INSERT INTO r1 VALUES('vii', 'vii');
|
||||
}
|
||||
|
||||
do_changes_test 3.3.1 { INSERT OR REPLACE INTO r1 VALUES('i', 1) } 1
|
||||
do_changes_test 3.3.2 { INSERT OR REPLACE INTO r1 VALUES('iv', 'v') } 1
|
||||
do_changes_test 3.3.3 { UPDATE OR REPLACE r1 SET b='v' WHERE a='iii' } 1
|
||||
do_changes_test 3.3.4 { UPDATE OR REPLACE r1 SET b='vi',a='vii' WHERE a='ii' } 1
|
||||
do_execsql_test 3.3.5 {
|
||||
SELECT * FROM r1 ORDER BY a;
|
||||
} {i 1 iii v vii vi}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-09813-48563 The value returned by sqlite3_changes()
|
||||
# immediately after an INSERT, UPDATE or DELETE statement run on a view
|
||||
# is always zero.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.1 {
|
||||
CREATE TABLE log(log);
|
||||
CREATE TABLE t1(x, y);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
CREATE TRIGGER v1_i INSTEAD OF INSERT ON v1 BEGIN
|
||||
INSERT INTO log VALUES('insert');
|
||||
END;
|
||||
CREATE TRIGGER v1_u INSTEAD OF UPDATE ON v1 BEGIN
|
||||
INSERT INTO log VALUES('update'), ('update');
|
||||
END;
|
||||
CREATE TRIGGER v1_d INSTEAD OF DELETE ON v1 BEGIN
|
||||
INSERT INTO log VALUES('delete'), ('delete'), ('delete');
|
||||
END;
|
||||
}
|
||||
|
||||
do_changes_test 4.2.1 { INSERT INTO t1 SELECT * FROM t1 } 3
|
||||
do_changes_test 4.2.2 { INSERT INTO v1 VALUES(1, 2) } 0
|
||||
|
||||
do_changes_test 4.3.1 { INSERT INTO t1 SELECT * FROM t1 } 6
|
||||
do_changes_test 4.3.2 { UPDATE v1 SET y='xyz' WHERE x=1 } 0
|
||||
|
||||
do_changes_test 4.4.1 { INSERT INTO t1 SELECT * FROM t1 } 12
|
||||
do_changes_test 4.4.2 { DELETE FROM v1 WHERE x=5 } 0
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-32918-61474 Before entering a trigger program the value
|
||||
# returned by sqlite3_changes() function is saved. After the trigger
|
||||
# program has finished, the original value is restored.
|
||||
#
|
||||
reset_db
|
||||
db func my_changes my_changes
|
||||
set ::changes [list]
|
||||
proc my_changes {x} {
|
||||
set res [db changes]
|
||||
lappend ::changes $x $res
|
||||
return $res
|
||||
}
|
||||
|
||||
do_execsql_test 5.1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t2(x);
|
||||
INSERT INTO t1 VALUES(1, NULL);
|
||||
INSERT INTO t1 VALUES(2, NULL);
|
||||
INSERT INTO t1 VALUES(3, NULL);
|
||||
CREATE TRIGGER AFTER UPDATE ON t1 BEGIN
|
||||
INSERT INTO t2 VALUES('a'), ('b'), ('c');
|
||||
SELECT my_changes('trigger');
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 5.1.1 {
|
||||
INSERT INTO t2 VALUES('a'), ('b');
|
||||
UPDATE t1 SET b = my_changes('update');
|
||||
SELECT * FROM t1;
|
||||
} {1 2 2 2 3 2}
|
||||
|
||||
# Value is being restored to "2" when the trigger program exits.
|
||||
do_test 5.1.2 {
|
||||
set ::changes
|
||||
} {update 2 trigger 3 update 2 trigger 3 update 2 trigger 3}
|
||||
|
||||
|
||||
reset_db
|
||||
do_execsql_test 5.2.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE log(x);
|
||||
INSERT INTO t1 VALUES(1, 0);
|
||||
INSERT INTO t1 VALUES(2, 0);
|
||||
INSERT INTO t1 VALUES(3, 0);
|
||||
CREATE TRIGGER t1_a_u AFTER UPDATE ON t1 BEGIN
|
||||
INSERT INTO log VALUES(old.b || ' -> ' || new.b || ' c = ' || changes() );
|
||||
END;
|
||||
CREATE TABLE t2(a);
|
||||
INSERT INTO t2 VALUES(1), (2), (3);
|
||||
UPDATE t1 SET b = changes();
|
||||
}
|
||||
do_execsql_test 5.2.1 {
|
||||
SELECT * FROM t1;
|
||||
} {1 3 2 3 3 3}
|
||||
do_execsql_test 5.2.2 {
|
||||
SELECT * FROM log;
|
||||
} {{0 -> 3 c = 3} {0 -> 3 c = 3} {0 -> 3 c = 3}}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-17146-37073 Within a trigger program each INSERT,
|
||||
# UPDATE and DELETE statement sets the value returned by
|
||||
# sqlite3_changes() upon completion as normal. Of course, this value
|
||||
# will not include any changes performed by sub-triggers, as the
|
||||
# sqlite3_changes() value will be saved and restored after each
|
||||
# sub-trigger has run.
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(a, b);
|
||||
CREATE TABLE t3(a, b);
|
||||
CREATE TABLE log(x);
|
||||
|
||||
CREATE TRIGGER t1_i BEFORE INSERT ON t1 BEGIN
|
||||
INSERT INTO t2 VALUES(new.a, new.b), (new.a, new.b);
|
||||
INSERT INTO log VALUES('t2->' || changes());
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t2_i AFTER INSERT ON t2 BEGIN
|
||||
INSERT INTO t3 VALUES(new.a, new.b), (new.a, new.b), (new.a, new.b);
|
||||
INSERT INTO log VALUES('t3->' || changes());
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t1_u AFTER UPDATE ON t1 BEGIN
|
||||
UPDATE t2 SET b=new.b WHERE a=old.a;
|
||||
INSERT INTO log VALUES('t2->' || changes());
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t2_u BEFORE UPDATE ON t2 BEGIN
|
||||
UPDATE t3 SET b=new.b WHERE a=old.a;
|
||||
INSERT INTO log VALUES('t3->' || changes());
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t1_d AFTER DELETE ON t1 BEGIN
|
||||
DELETE FROM t2 WHERE a=old.a AND b=old.b;
|
||||
INSERT INTO log VALUES('t2->' || changes());
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t2_d BEFORE DELETE ON t2 BEGIN
|
||||
DELETE FROM t3 WHERE a=old.a AND b=old.b;
|
||||
INSERT INTO log VALUES('t3->' || changes());
|
||||
END;
|
||||
}
|
||||
|
||||
do_changes_test 6.1 {
|
||||
INSERT INTO t1 VALUES('+', 'o');
|
||||
SELECT * FROM log;
|
||||
} {t3->3 t3->3 t2->2 1}
|
||||
|
||||
do_changes_test 6.2 {
|
||||
DELETE FROM log;
|
||||
UPDATE t1 SET b='*';
|
||||
SELECT * FROM log;
|
||||
} {t3->6 t3->6 t2->2 1}
|
||||
|
||||
do_changes_test 6.3 {
|
||||
DELETE FROM log;
|
||||
DELETE FROM t1;
|
||||
SELECT * FROM log;
|
||||
} {t3->6 t3->0 t2->2 1}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-43399-09409 This means that if the changes() SQL
|
||||
# function (or similar) is used by the first INSERT, UPDATE or DELETE
|
||||
# statement within a trigger, it returns the value as set when the
|
||||
# calling statement began executing.
|
||||
#
|
||||
# EVIDENCE-OF: R-53215-27584 If it is used by the second or subsequent
|
||||
# such statement within a trigger program, the value returned reflects
|
||||
# the number of rows modified by the previous INSERT, UPDATE or DELETE
|
||||
# statement within the same trigger.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.1 {
|
||||
CREATE TABLE q1(t);
|
||||
CREATE TABLE q2(u, v);
|
||||
CREATE TABLE q3(w);
|
||||
|
||||
CREATE TRIGGER q2_insert BEFORE INSERT ON q2 BEGIN
|
||||
|
||||
/* changes() returns value from previous I/U/D in callers context */
|
||||
INSERT INTO q1 VALUES('1:' || changes());
|
||||
|
||||
/* changes() returns value of previous I/U/D in this context */
|
||||
INSERT INTO q3 VALUES(changes()), (2), (3);
|
||||
INSERT INTO q1 VALUES('2:' || changes());
|
||||
INSERT INTO q3 VALUES(changes() + 3), (changes()+4);
|
||||
SELECT 'this does not affect things!';
|
||||
INSERT INTO q1 VALUES('3:' || changes());
|
||||
UPDATE q3 SET w = w+10 WHERE w%2;
|
||||
INSERT INTO q1 VALUES('4:' || changes());
|
||||
DELETE FROM q3;
|
||||
INSERT INTO q1 VALUES('5:' || changes());
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 7.2 {
|
||||
INSERT INTO q2 VALUES('x', 'y');
|
||||
SELECT * FROM q1;
|
||||
} {
|
||||
1:0 2:3 3:2 4:3 5:5
|
||||
}
|
||||
|
||||
do_execsql_test 7.3 {
|
||||
DELETE FROM q1;
|
||||
INSERT INTO q2 VALUES('x', 'y');
|
||||
SELECT * FROM q1;
|
||||
} {
|
||||
1:5 2:3 3:2 4:3 5:5
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -1,213 +0,0 @@
|
||||
# 2011 May 06
|
||||
#
|
||||
# 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 e_totalchanges
|
||||
|
||||
# Like [do_execsql_test], except it appends the value returned by
|
||||
# [db total_changes] to the result of executing the SQL script.
|
||||
#
|
||||
proc do_tc_test {tn sql res} {
|
||||
uplevel [list \
|
||||
do_test $tn "concat \[execsql {$sql}\] \[db total_changes\]" $res
|
||||
]
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX t1_b ON t1(b);
|
||||
CREATE TABLE t2(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID;
|
||||
CREATE INDEX t2_y ON t2(y);
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-65438-26258 This function returns the total number of
|
||||
# rows inserted, modified or deleted by all INSERT, UPDATE or DELETE
|
||||
# statements completed since the database connection was opened,
|
||||
# including those executed as part of trigger programs.
|
||||
#
|
||||
# 1.1.*: different types of I/U/D statements,
|
||||
# 1.2.*: trigger programs.
|
||||
#
|
||||
do_tc_test 1.1.1 {
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
UPDATE t1 SET a = a+1;
|
||||
DELETE FROM t1;
|
||||
} {6}
|
||||
do_tc_test 1.1.2 {
|
||||
DELETE FROM t1
|
||||
} {6}
|
||||
|
||||
do_tc_test 1.1.3 {
|
||||
WITH data(a,b) AS (
|
||||
SELECT 0, 0 UNION ALL SELECT a+1, b+1 FROM data WHERE a<99
|
||||
)
|
||||
INSERT INTO t1 SELECT * FROM data;
|
||||
} {106}
|
||||
|
||||
do_tc_test 1.1.4 {
|
||||
INSERT INTO t2 SELECT * FROM t1 WHERE a<50;
|
||||
UPDATE t2 SET y=y+1;
|
||||
} {206}
|
||||
|
||||
do_tc_test 1.1.5 {
|
||||
DELETE FROM t2 WHERE y<=25
|
||||
} {231}
|
||||
|
||||
do_execsql_test 1.2.1 {
|
||||
DELETE FROM t1;
|
||||
DELETE FROM t2;
|
||||
}
|
||||
sqlite3 db test.db ; # To reset total_changes
|
||||
do_tc_test 1.2.2 {
|
||||
CREATE TABLE log(detail);
|
||||
CREATE TRIGGER t1_after_insert AFTER INSERT ON t1 BEGIN
|
||||
INSERT INTO log VALUES('inserted into t1');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t1_before_delete BEFORE DELETE ON t1 BEGIN
|
||||
INSERT INTO log VALUES('deleting from t1');
|
||||
INSERT INTO log VALUES('here we go!');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t1_after_update AFTER UPDATE ON t1 BEGIN
|
||||
INSERT INTO log VALUES('update');
|
||||
DELETE FROM log;
|
||||
END;
|
||||
|
||||
INSERT INTO t1 VALUES('a', 'b'); -- 1 + 1
|
||||
UPDATE t1 SET b='c'; -- 1 + 1 + 2
|
||||
DELETE FROM t1; -- 1 + 1 + 1
|
||||
} {9}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-61766-15253 Executing any other type of SQL statement
|
||||
# does not affect the value returned by sqlite3_total_changes().
|
||||
do_tc_test 2.1 {
|
||||
INSERT INTO t1 VALUES(1, 2), (3, 4);
|
||||
INSERT INTO t2 VALUES(1, 2), (3, 4);
|
||||
} {15}
|
||||
do_tc_test 2.2 {
|
||||
SELECT count(*) FROM t1;
|
||||
} {2 15}
|
||||
do_tc_test 2.3 {
|
||||
CREATE TABLE t4(a, b);
|
||||
ALTER TABLE t4 ADD COLUMN c;
|
||||
CREATE INDEX i4 ON t4(c);
|
||||
ALTER TABLE t4 RENAME TO t5;
|
||||
ANALYZE;
|
||||
BEGIN;
|
||||
DROP TABLE t2;
|
||||
ROLLBACK;
|
||||
VACUUM;
|
||||
} {15}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-36043-10590 Changes made as part of foreign key
|
||||
# actions are included in the count, but those made as part of REPLACE
|
||||
# constraint resolution are not.
|
||||
#
|
||||
# 3.1.*: foreign key actions
|
||||
# 3.2.*: REPLACE constraints.
|
||||
#
|
||||
sqlite3 db test.db ; # To reset total_changes
|
||||
do_tc_test 3.1.1 {
|
||||
CREATE TABLE p1(c PRIMARY KEY, d);
|
||||
CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET NULL);
|
||||
CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE CASCADE);
|
||||
CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET DEFAULT);
|
||||
|
||||
INSERT INTO p1 VALUES(1, 'one');
|
||||
INSERT INTO p1 VALUES(2, 'two');
|
||||
INSERT INTO p1 VALUES(3, 'three');
|
||||
INSERT INTO p1 VALUES(4, 'four');
|
||||
|
||||
INSERT INTO c1 VALUES(1, 'i');
|
||||
INSERT INTO c2 VALUES(2, 'ii');
|
||||
INSERT INTO c3 VALUES(3, 'iii');
|
||||
PRAGMA foreign_keys = ON;
|
||||
} {7}
|
||||
|
||||
do_tc_test 3.1.2 { DELETE FROM p1 WHERE c=1; } {9}
|
||||
do_tc_test 3.1.3 { DELETE FROM p1 WHERE c=2; } {11}
|
||||
do_tc_test 3.1.4 { DELETE FROM p1 WHERE c=3; } {13}
|
||||
do_tc_test 3.1.5 { DELETE FROM p1 WHERE c=4; } {14} ; # only 1 this time.
|
||||
|
||||
sqlite3 db test.db ; # To reset total_changes
|
||||
do_tc_test 3.1.6 {
|
||||
DROP TABLE c1;
|
||||
DROP TABLE c2;
|
||||
DROP TABLE c3;
|
||||
CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET NULL);
|
||||
CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE CASCADE);
|
||||
CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET DEFAULT);
|
||||
|
||||
INSERT INTO p1 VALUES(1, 'one');
|
||||
INSERT INTO p1 VALUES(2, 'two');
|
||||
INSERT INTO p1 VALUES(3, 'three');
|
||||
INSERT INTO p1 VALUES(4, 'four');
|
||||
|
||||
INSERT INTO c1 VALUES(1, 'i');
|
||||
INSERT INTO c2 VALUES(2, 'ii');
|
||||
INSERT INTO c3 VALUES(3, 'iii');
|
||||
PRAGMA foreign_keys = ON;
|
||||
} {7}
|
||||
|
||||
do_tc_test 3.1.7 { UPDATE p1 SET c=c+4 WHERE c=1; } {9}
|
||||
do_tc_test 3.1.8 { UPDATE p1 SET c=c+4 WHERE c=2; } {11}
|
||||
do_tc_test 3.1.9 { UPDATE p1 SET c=c+4 WHERE c=3; } {13}
|
||||
do_tc_test 3.1.10 { UPDATE p1 SET c=c+4 WHERE c=4; } {14} ; # only 1 this time.
|
||||
|
||||
sqlite3 db test.db ; # To reset total_changes
|
||||
do_tc_test 3.2.1 {
|
||||
CREATE TABLE t3(a UNIQUE, b UNIQUE);
|
||||
INSERT INTO t3 VALUES('one', 'one');
|
||||
INSERT INTO t3 VALUES('two', 'two');
|
||||
INSERT OR REPLACE INTO t3 VALUES('one', 'two');
|
||||
} {3}
|
||||
|
||||
do_tc_test 3.2.2 {
|
||||
INSERT INTO t3 VALUES('three', 'one');
|
||||
UPDATE OR REPLACE t3 SET b='two' WHERE b='one';
|
||||
SELECT * FROM t3;
|
||||
} {three two 5}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-54872-08741 Changes to a view that are intercepted by
|
||||
# INSTEAD OF triggers are not counted.
|
||||
#
|
||||
sqlite3 db test.db ; # To reset total_changes
|
||||
do_tc_test 4.1 {
|
||||
CREATE TABLE t6(x);
|
||||
CREATE VIEW v1 AS SELECT * FROM t6;
|
||||
CREATE TRIGGER v1_tr1 INSTEAD OF INSERT ON v1 BEGIN
|
||||
SELECT 'no-op';
|
||||
END;
|
||||
|
||||
INSERT INTO v1 VALUES('a');
|
||||
INSERT INTO v1 VALUES('b');
|
||||
} {0}
|
||||
do_tc_test 4.2 {
|
||||
CREATE TRIGGER v1_tr2 INSTEAD OF INSERT ON v1 BEGIN
|
||||
INSERT INTO t6 VALUES(new.x);
|
||||
END;
|
||||
|
||||
INSERT INTO v1 VALUES('c');
|
||||
INSERT INTO v1 VALUES('d');
|
||||
} {2}
|
||||
|
||||
|
||||
finish_test
|
||||
-229
@@ -1,229 +0,0 @@
|
||||
# 2011 May 06
|
||||
#
|
||||
# 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 e_wal
|
||||
|
||||
db close
|
||||
testvfs oldvfs -iversion 1
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-58297-14483 WAL databases can be created, read, and
|
||||
# written even if shared memory is unavailable as long as the
|
||||
# locking_mode is set to EXCLUSIVE before the first attempted access.
|
||||
#
|
||||
# EVIDENCE-OF: R-00449-33772 This feature allows WAL databases to be
|
||||
# created, read, and written by legacy VFSes that lack the "version 2"
|
||||
# shared-memory methods xShmMap, xShmLock, xShmBarrier, and xShmUnmap on
|
||||
# the sqlite3_io_methods object.
|
||||
#
|
||||
# 1.1: "create" tests.
|
||||
# 1.2: "read" tests.
|
||||
# 1.3: "write" tests.
|
||||
#
|
||||
# All three done with VFS "oldvfs", which has iVersion==1 and so does
|
||||
# not support shared memory.
|
||||
#
|
||||
sqlite3 db test.db -vfs oldvfs
|
||||
do_execsql_test 1.1.1 {
|
||||
PRAGMA journal_mode = WAL;
|
||||
} {delete}
|
||||
do_execsql_test 1.1.2 {
|
||||
PRAGMA locking_mode = EXCLUSIVE;
|
||||
PRAGMA journal_mode = WAL;
|
||||
} {exclusive wal}
|
||||
do_execsql_test 1.1.3 {
|
||||
CREATE TABLE t1(x, y);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
} {}
|
||||
do_test 1.1.4 {
|
||||
list [file exists test.db-shm] [file exists test.db-wal]
|
||||
} {0 1}
|
||||
|
||||
do_test 1.2.1 {
|
||||
db close
|
||||
sqlite3 db test.db -vfs oldvfs
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} {1 {unable to open database file}}
|
||||
do_test 1.2.2 {
|
||||
execsql { PRAGMA locking_mode = EXCLUSIVE }
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2}
|
||||
do_test 1.2.3 {
|
||||
list [file exists test.db-shm] [file exists test.db-wal]
|
||||
} {0 1}
|
||||
|
||||
do_test 1.3.1 {
|
||||
db close
|
||||
sqlite3 db test.db -vfs oldvfs
|
||||
catchsql { INSERT INTO t1 VALUES(3, 4) }
|
||||
} {1 {unable to open database file}}
|
||||
do_test 1.3.2 {
|
||||
execsql { PRAGMA locking_mode = EXCLUSIVE }
|
||||
execsql { INSERT INTO t1 VALUES(3, 4) }
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2 3 4}
|
||||
do_test 1.3.3 {
|
||||
list [file exists test.db-shm] [file exists test.db-wal]
|
||||
} {0 1}
|
||||
|
||||
# EVIDENCE-OF: R-31969-57825 If EXCLUSIVE locking mode is set prior to
|
||||
# the first WAL-mode database access, then SQLite never attempts to call
|
||||
# any of the shared-memory methods and hence no shared-memory wal-index
|
||||
# is ever created.
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 2.1.1 {
|
||||
PRAGMA locking_mode = EXCLUSIVE;
|
||||
SELECT * FROM t1;
|
||||
} {exclusive 1 2 3 4}
|
||||
do_test 2.1.2 {
|
||||
list [file exists test.db-shm] [file exists test.db-wal]
|
||||
} {0 1}
|
||||
|
||||
# EVIDENCE-OF: R-36328-16367 In that case, the database connection
|
||||
# remains in EXCLUSIVE mode as long as the journal mode is WAL; attempts
|
||||
# to change the locking mode using "PRAGMA locking_mode=NORMAL;" are
|
||||
# no-ops.
|
||||
#
|
||||
do_execsql_test 2.2.1 {
|
||||
PRAGMA locking_mode = NORMAL;
|
||||
SELECT * FROM t1;
|
||||
} {exclusive 1 2 3 4}
|
||||
do_test 2.2.2 {
|
||||
sqlite3 db2 test.db
|
||||
catchsql {SELECT * FROM t1} db2
|
||||
} {1 {database is locked}}
|
||||
db2 close
|
||||
|
||||
# EVIDENCE-OF: R-63522-46088 The only way to change out of EXCLUSIVE
|
||||
# locking mode is to first change out of WAL journal mode.
|
||||
#
|
||||
do_execsql_test 2.3.1 {
|
||||
PRAGMA journal_mode = DELETE;
|
||||
SELECT * FROM t1;
|
||||
} {delete 1 2 3 4}
|
||||
do_test 2.3.2 {
|
||||
sqlite3 db2 test.db
|
||||
catchsql {SELECT * FROM t1} db2
|
||||
} {1 {database is locked}}
|
||||
do_execsql_test 2.3.3 {
|
||||
PRAGMA locking_mode = NORMAL;
|
||||
SELECT * FROM t1;
|
||||
} {normal 1 2 3 4}
|
||||
do_test 2.3.4 {
|
||||
sqlite3 db2 test.db
|
||||
catchsql {SELECT * FROM t1} db2
|
||||
} {0 {1 2 3 4}}
|
||||
db2 close
|
||||
db close
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-57239-11845 If NORMAL locking mode is in effect for the
|
||||
# first WAL-mode database access, then the shared-memory wal-index is
|
||||
# created.
|
||||
#
|
||||
do_test 3.0 {
|
||||
sqlite3 db test.db
|
||||
execsql { PRAGMA journal_mode = WAL }
|
||||
db close
|
||||
} {}
|
||||
do_test 3.1 {
|
||||
sqlite3 db test.db
|
||||
execsql { SELECT * FROM t1 }
|
||||
list [file exists test.db-shm] [file exists test.db-wal]
|
||||
} {1 1}
|
||||
|
||||
# EVIDENCE-OF: R-13779-07711 As long as exactly one connection is using
|
||||
# a shared-memory wal-index, the locking mode can be changed freely
|
||||
# between NORMAL and EXCLUSIVE.
|
||||
#
|
||||
do_execsql_test 3.2.1 {
|
||||
PRAGMA locking_mode = EXCLUSIVE;
|
||||
PRAGMA locking_mode = NORMAL;
|
||||
PRAGMA locking_mode = EXCLUSIVE;
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
} {exclusive normal exclusive}
|
||||
do_test 3.2.2 {
|
||||
sqlite3 db2 test.db
|
||||
catchsql { SELECT * FROM t1 } db2
|
||||
} {1 {database is locked}}
|
||||
|
||||
# EVIDENCE-OF: R-10993-11647 It is only when the shared-memory wal-index
|
||||
# is omitted, when the locking mode is EXCLUSIVE prior to the first
|
||||
# WAL-mode database access, that the locking mode is stuck in EXCLUSIVE.
|
||||
#
|
||||
do_execsql_test 3.2.3 {
|
||||
PRAGMA locking_mode = NORMAL;
|
||||
SELECT * FROM t1;
|
||||
} {normal 1 2 3 4 5 6}
|
||||
do_test 3.2.4 {
|
||||
catchsql { SELECT * FROM t1 } db2
|
||||
} {0 {1 2 3 4 5 6}}
|
||||
|
||||
do_catchsql_test 3.2.5 {
|
||||
PRAGMA locking_mode = EXCLUSIVE;
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
} {1 {database is locked}}
|
||||
|
||||
db2 close
|
||||
|
||||
# EVIDENCE-OF: R-46197-42811 This means that the underlying VFS must
|
||||
# support the "version 2" shared-memory.
|
||||
#
|
||||
# EVIDENCE-OF: R-55316-21772 If the VFS does not support shared-memory
|
||||
# methods, then the attempt to open a database that is already in WAL
|
||||
# mode, or the attempt convert a database into WAL mode, will fail.
|
||||
#
|
||||
db close
|
||||
do_test 3.4.1 {
|
||||
sqlite3 db test.db -vfs oldvfs
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} {1 {unable to open database file}}
|
||||
db close
|
||||
do_test 3.4.2 {
|
||||
forcedelete test.db2
|
||||
sqlite3 db test.db2 -vfs oldvfs
|
||||
catchsql { PRAGMA journal_mode = WAL }
|
||||
} {0 delete}
|
||||
db close
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-22428-28959 To prevent older versions of SQLite from
|
||||
# trying to recover a WAL-mode database (and making matters worse) the
|
||||
# database file format version numbers (bytes 18 and 19 in the database
|
||||
# header) are increased from 1 to 2 in WAL mode.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.1.1 { CREATE TABLE t1(x, y) }
|
||||
do_test 4.1.2 { hexio_read test.db 18 2 } {0101}
|
||||
do_execsql_test 4.1.3 { PRAGMA journal_mode = wAL } {wal}
|
||||
do_test 4.1.4 { hexio_read test.db 18 2 } {0202}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-02535-05811 One can explicitly change out of WAL mode
|
||||
# using a pragma such as this: PRAGMA journal_mode=DELETE;
|
||||
#
|
||||
do_execsql_test 4.2.1 { INSERT INTO t1 VALUES(1, 1); } {}
|
||||
do_test 4.2.2 { file exists test.db-wal } {1}
|
||||
do_execsql_test 4.2.3 { PRAGMA journal_mode = delete } {delete}
|
||||
do_test 4.2.4 { file exists test.db-wal } {0}
|
||||
|
||||
# EVIDENCE-OF: R-60175-02388 Deliberately changing out of WAL mode
|
||||
# changes the database file format version numbers back to 1 so that
|
||||
# older versions of SQLite can once again access the database file.
|
||||
#
|
||||
do_test 4.3 { hexio_read test.db 18 2 } {0101}
|
||||
|
||||
finish_test
|
||||
@@ -50,22 +50,5 @@ do_tblsread_test 1.3 { UPDATE par SET a=? WHERE b=? } {c1 c2 par}
|
||||
do_tblsread_test 1.4 { UPDATE par SET c=? WHERE b=? } {c3 par}
|
||||
do_tblsread_test 1.5 { UPDATE par SET a=?,b=?,c=? WHERE b=? } {c1 c2 c3 par s1}
|
||||
|
||||
ifcapable incrblob {
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE pX(x PRIMARY KEY);
|
||||
CREATE TABLE cX(a INTEGER PRIMARY KEY, b REFERENCES pX);
|
||||
}
|
||||
|
||||
do_catchsql_test 2.1 {
|
||||
INSERT INTO cX VALUES(11, zeroblob(40));
|
||||
} {1 {FOREIGN KEY constraint failed}}
|
||||
|
||||
do_test 2.2 {
|
||||
set stmt [sqlite3_prepare_v2 db "INSERT INTO cX VALUES(11, ?)" -1]
|
||||
sqlite3_bind_zeroblob $stmt 1 45
|
||||
sqlite3_step $stmt
|
||||
sqlite3_finalize $stmt
|
||||
} {SQLITE_CONSTRAINT}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix in5
|
||||
|
||||
do_test in5-1.1 {
|
||||
execsql {
|
||||
@@ -136,51 +135,4 @@ do_test in5-5.3 {
|
||||
}]
|
||||
} {0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# At one point SQLite was removing the DISTINCT keyword from expressions
|
||||
# similar to:
|
||||
#
|
||||
# <expr1> IN (SELECT DISTINCT <expr2> FROM...)
|
||||
#
|
||||
# However, there are a few obscure cases where this is incorrect. For
|
||||
# example, if the SELECT features a LIMIT clause, or if the collation
|
||||
# sequence or affinity used by the DISTINCT does not match the one used
|
||||
# by the IN(...) expression.
|
||||
#
|
||||
do_execsql_test 6.1.1 {
|
||||
CREATE TABLE t1(a COLLATE nocase);
|
||||
INSERT INTO t1 VALUES('one');
|
||||
INSERT INTO t1 VALUES('ONE');
|
||||
}
|
||||
do_execsql_test 6.1.2 {
|
||||
SELECT count(*) FROM t1 WHERE a COLLATE BINARY IN (SELECT DISTINCT a FROM t1)
|
||||
} {1}
|
||||
|
||||
do_execsql_test 6.2.1 {
|
||||
CREATE TABLE t3(a, b);
|
||||
INSERT INTO t3 VALUES(1, 1);
|
||||
INSERT INTO t3 VALUES(1, 2);
|
||||
INSERT INTO t3 VALUES(1, 3);
|
||||
INSERT INTO t3 VALUES(2, 4);
|
||||
INSERT INTO t3 VALUES(2, 5);
|
||||
INSERT INTO t3 VALUES(2, 6);
|
||||
INSERT INTO t3 VALUES(3, 7);
|
||||
INSERT INTO t3 VALUES(3, 8);
|
||||
INSERT INTO t3 VALUES(3, 9);
|
||||
}
|
||||
do_execsql_test 6.2.2 {
|
||||
SELECT count(*) FROM t3 WHERE b IN (SELECT DISTINCT a FROM t3 LIMIT 5);
|
||||
} {3}
|
||||
do_execsql_test 6.2.3 {
|
||||
SELECT count(*) FROM t3 WHERE b IN (SELECT a FROM t3 LIMIT 5);
|
||||
} {2}
|
||||
|
||||
do_execsql_test 6.3.1 {
|
||||
CREATE TABLE x1(a);
|
||||
CREATE TABLE x2(b);
|
||||
INSERT INTO x1 VALUES(1), (1), (2);
|
||||
INSERT INTO x2 VALUES(1), (2);
|
||||
SELECT count(*) FROM x2 WHERE b IN (SELECT DISTINCT a FROM x1 LIMIT 2);
|
||||
} {2}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# 2014-11-10
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
# The focus of this script is testing the "eval.c" loadable extension.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
load_static_extension db eval
|
||||
do_execsql_test misc8-1.0 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
INSERT INTO t1 VALUES(1,2,3),(4,5,6);
|
||||
SELECT quote(eval('SELECT * FROM t1 ORDER BY a','-abc-'));
|
||||
} {'1-abc-2-abc-3-abc-4-abc-5-abc-6'}
|
||||
do_execsql_test misc8-1.1 {
|
||||
SELECT quote(eval('SELECT * FROM t1 ORDER BY a'));
|
||||
} {{'1 2 3 4 5 6'}}
|
||||
do_catchsql_test misc8-1.2 {
|
||||
SELECT quote(eval('SELECT d FROM t1 ORDER BY a'));
|
||||
} {1 {no such column: d}}
|
||||
do_execsql_test misc8-1.3 {
|
||||
INSERT INTO t1 VALUES(7,null,9);
|
||||
SELECT eval('SELECT * FROM t1 ORDER BY a',',');
|
||||
} {1,2,3,4,5,6,7,,9}
|
||||
do_catchsql_test misc8-1.4 {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(10,11,12);
|
||||
SELECT a, coalesce(b, eval('ROLLBACK; SELECT ''bam'';')), c
|
||||
FROM t1 ORDER BY a;
|
||||
} {0 {1 2 3 4 5 6 7 bam 9}}
|
||||
do_catchsql_test misc8-1.5 {
|
||||
INSERT INTO t1 VALUES(10,11,12);
|
||||
SELECT a, coalesce(b, eval('SELECT ''bam''')), c
|
||||
FROM t1
|
||||
ORDER BY rowid;
|
||||
} {0 {1 2 3 4 5 6 7 bam 9 10 11 12}}
|
||||
do_catchsql_test misc8-1.6 {
|
||||
SELECT a, coalesce(b, eval('DELETE FROM t1; SELECT ''bam''')), c
|
||||
FROM t1
|
||||
ORDER BY rowid;
|
||||
} {0 {1 2 3 4 5 6 7 bam {}}}
|
||||
do_catchsql_test misc8-1.7 {
|
||||
INSERT INTO t1 VALUES(1,2,3),(4,5,6),(7,null,9);
|
||||
BEGIN;
|
||||
CREATE TABLE t2(x);
|
||||
SELECT a, coalesce(b, eval('ROLLBACK; SELECT ''bam''')), c
|
||||
FROM t1
|
||||
ORDER BY rowid;
|
||||
} {1 {abort due to ROLLBACK}}
|
||||
|
||||
|
||||
finish_test
|
||||
+42
-44
@@ -33,7 +33,7 @@ proc register_rblob_code {dbname seed} {
|
||||
set ::rcnt $seed
|
||||
proc rblob {n} {
|
||||
set ::rcnt [expr (([set ::rcnt] << 3) + [set ::rcnt] + 456) & 0xFFFFFFFF]
|
||||
set str [format %.8x [expr [set ::rcnt] ^ 0xbdf20da3]]
|
||||
set str [format %.8x [expr [set ::rcnt] ^ 0xbdf20da3]]
|
||||
string range [string repeat [set str] [expr [set n]/4]] 1 [set n]
|
||||
}
|
||||
$dbname func rblob rblob
|
||||
@@ -42,7 +42,7 @@ proc register_rblob_code {dbname seed} {
|
||||
|
||||
# For cases 1.1 and 1.4, the number of pages read using xRead() is 4 on
|
||||
# unix and 9 on windows. The difference is that windows only ever maps
|
||||
# an integer number of OS pages (i.e. creates mappings that are a multiple
|
||||
# an integer number of OS pages (i.e. creates mappings that are a multiple
|
||||
# of 4KB in size). Whereas on unix any sized mapping may be created.
|
||||
#
|
||||
foreach {t mmap_size nRead c2init} {
|
||||
@@ -106,52 +106,50 @@ foreach {t mmap_size nRead c2init} {
|
||||
set ::rcnt 0
|
||||
proc rblob {n} {
|
||||
set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF]
|
||||
set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]]
|
||||
set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]]
|
||||
string range [string repeat $str [expr $n/4]] 1 $n
|
||||
}
|
||||
|
||||
reset_db
|
||||
db func rblob rblob
|
||||
|
||||
ifcapable wal {
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA auto_vacuum = 1;
|
||||
PRAGMA mmap_size = 67108864;
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE t1(a, b, UNIQUE(a, b));
|
||||
INSERT INTO t1 VALUES(rblob(500), rblob(500));
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 2
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 4
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 8
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 16
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 32
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA auto_vacuum = 1;
|
||||
PRAGMA mmap_size = 67108864;
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE t1(a, b, UNIQUE(a, b));
|
||||
INSERT INTO t1 VALUES(rblob(500), rblob(500));
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 2
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 4
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 8
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 16
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 32
|
||||
PRAGMA wal_checkpoint;
|
||||
} {67108864 wal 0 103 103}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
PRAGMA auto_vacuum;
|
||||
SELECT count(*) FROM t1;
|
||||
} {1 32}
|
||||
|
||||
if {[permutation] != "inmemory_journal"} {
|
||||
do_test 2.3 {
|
||||
sqlite3 db2 test.db
|
||||
db2 func rblob rblob
|
||||
db2 eval {
|
||||
DELETE FROM t1 WHERE (rowid%4);
|
||||
PRAGMA wal_checkpoint;
|
||||
}
|
||||
db2 eval {
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 16
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
} {16}
|
||||
|
||||
do_execsql_test 2.4 {
|
||||
PRAGMA wal_checkpoint;
|
||||
} {67108864 wal 0 103 103}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
PRAGMA auto_vacuum;
|
||||
SELECT count(*) FROM t1;
|
||||
} {1 32}
|
||||
|
||||
if {[permutation] != "inmemory_journal"} {
|
||||
do_test 2.3 {
|
||||
sqlite3 db2 test.db
|
||||
db2 func rblob rblob
|
||||
db2 eval {
|
||||
DELETE FROM t1 WHERE (rowid%4);
|
||||
PRAGMA wal_checkpoint;
|
||||
}
|
||||
db2 eval {
|
||||
INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 16
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
} {16}
|
||||
|
||||
do_execsql_test 2.4 {
|
||||
PRAGMA wal_checkpoint;
|
||||
} {0 24 24}
|
||||
db2 close
|
||||
}
|
||||
} {0 24 24}
|
||||
db2 close
|
||||
}
|
||||
|
||||
reset_db
|
||||
@@ -229,7 +227,7 @@ do_test 4.4 {
|
||||
do_execsql_test 4.5 { COMMIT }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Ensure that existing cursors holding xFetch() references are not
|
||||
# Ensure that existing cursors holding xFetch() references are not
|
||||
# confused if those pages are moved to make way for the root page of a
|
||||
# new table or index.
|
||||
#
|
||||
@@ -298,7 +296,7 @@ foreach {tn1 mmap1 mmap2} {
|
||||
sql1 "PRAGMA mmap_size = $mmap1"
|
||||
sql2 "PRAGMA mmap_size = $mmap2"
|
||||
|
||||
do_test $tn1.$tn {
|
||||
do_test $tn1.$tn {
|
||||
for {set i 1} {$i <= 100} {incr i} {
|
||||
if {$i % 2} {
|
||||
set c1 sql1
|
||||
@@ -313,7 +311,7 @@ foreach {tn1 mmap1 mmap2} {
|
||||
UPDATE t2 SET x = (SELECT md5sum(a) FROM t1);
|
||||
}
|
||||
|
||||
set res [$c2 {
|
||||
set res [$c2 {
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT x == (SELECT md5sum(a) FROM t1) FROM t2;
|
||||
PRAGMA integrity_check;
|
||||
|
||||
@@ -95,25 +95,5 @@ do_execsql_test printf2-2.3 {
|
||||
SELECT printf('%s=(%d/%g/%s)',a) FROM t1 ORDER BY a;
|
||||
} {-1=(0/0/) 1=(0/0/) 1.5=(0/0/) abc=(0/0/)}
|
||||
|
||||
# The precision of the %c conversion causes the character to repeat.
|
||||
#
|
||||
do_execsql_test printf2-3.1 {
|
||||
SELECT printf('|%110.100c|','*');
|
||||
} {{| ****************************************************************************************************|}}
|
||||
do_execsql_test printf2-3.2 {
|
||||
SELECT printf('|%-110.100c|','*');
|
||||
} {{|**************************************************************************************************** |}}
|
||||
do_execsql_test printf2-3.3 {
|
||||
SELECT printf('|%9.8c|%-9.8c|','*','*');
|
||||
} {{| ********|******** |}}
|
||||
do_execsql_test printf2-3.4 {
|
||||
SELECT printf('|%8.8c|%-8.8c|','*','*');
|
||||
} {|********|********|}
|
||||
do_execsql_test printf2-3.5 {
|
||||
SELECT printf('|%7.8c|%-7.8c|','*','*');
|
||||
} {|********|********|}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+2
-2
@@ -60,11 +60,11 @@ ifcapable conflict {
|
||||
#
|
||||
do_test rollback-1.5 {
|
||||
sqlite3_step $STMT
|
||||
} {SQLITE_ROW}
|
||||
} {SQLITE_ERROR}
|
||||
|
||||
# Restart the SELECT statement
|
||||
#
|
||||
do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_OK}
|
||||
do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_ABORT}
|
||||
} else {
|
||||
do_test rollback-1.6 { sqlite3_reset $STMT } {SQLITE_OK}
|
||||
}
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
# 2014 November 12
|
||||
#
|
||||
# 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 containst tests to verify that ROLLBACK or ROLLBACK TO
|
||||
# operations interact correctly with ongoing SELECT statements.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix rollback2
|
||||
|
||||
proc int2hex {i} { format %.2X $i }
|
||||
db func int2hex int2hex
|
||||
do_execsql_test 1.0 {
|
||||
SELECT int2hex(0), int2hex(100), int2hex(255)
|
||||
} {00 64 FF}
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(i, h);
|
||||
CREATE INDEX i1 ON t1(h);
|
||||
WITH data(a, b) AS (
|
||||
SELECT 1, int2hex(1)
|
||||
UNION ALL
|
||||
SELECT a+1, int2hex(a+1) FROM data WHERE a<40
|
||||
)
|
||||
INSERT INTO t1 SELECT * FROM data;
|
||||
} {}
|
||||
|
||||
|
||||
# do_rollback_test ID SWITCHES
|
||||
#
|
||||
# where SWITCHES are:
|
||||
#
|
||||
# -setup SQL script to open transaction and begin writing.
|
||||
# -select SELECT to execute after -setup script
|
||||
# -result Expected result of -select statement
|
||||
# -rollback Use this SQL command ("ROLLBACK" or "ROLLBACK TO ...") to
|
||||
# rollback the transaction in the middle of the -select statment
|
||||
# execution.
|
||||
#
|
||||
proc do_rollback_test {tn args} {
|
||||
set A(-setup) ""
|
||||
set A(-select) ""
|
||||
set A(-result) ""
|
||||
set A(-rollback) ROLLBACK
|
||||
|
||||
array set O $args
|
||||
foreach k [array names O] {
|
||||
if {[info exists A($k)]==0} { error "unknown option: $k" }
|
||||
set A($k) $O($k)
|
||||
}
|
||||
|
||||
for {set iRollback 0} 1 {incr iRollback} {
|
||||
catch { db eval ROLLBACK }
|
||||
set res [list]
|
||||
db eval $A(-setup)
|
||||
|
||||
set i 0
|
||||
db eval $A(-select) x {
|
||||
if {$i==$iRollback} { db eval $A(-rollback) }
|
||||
foreach k $x(*) { lappend res $x($k) }
|
||||
incr i
|
||||
}
|
||||
|
||||
do_test $tn.$iRollback [list set {} $res] [list {*}$A(-result)]
|
||||
if {$i < $iRollback} break
|
||||
}
|
||||
}
|
||||
|
||||
do_rollback_test 2.1 -setup {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE (i%2)==1;
|
||||
} -select {
|
||||
SELECT i FROM t1 WHERE (i%2)==0
|
||||
} -result {
|
||||
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40
|
||||
}
|
||||
|
||||
do_rollback_test 2.2 -setup {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE (i%4)==1;
|
||||
SAVEPOINT one;
|
||||
DELETE FROM t1 WHERE (i%2)==1;
|
||||
} -rollback {
|
||||
ROLLBACK TO one;
|
||||
} -select {
|
||||
SELECT i FROM t1 WHERE (i%2)==0
|
||||
} -result {
|
||||
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Try with some index scans
|
||||
#
|
||||
do_eqp_test 3.1 {
|
||||
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
|
||||
} {0 0 0 {SCAN TABLE t1 USING INDEX i1}}
|
||||
do_rollback_test 3.2 -setup {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE (i%2)==1;
|
||||
} -select {
|
||||
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
|
||||
} -result {
|
||||
40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2
|
||||
}
|
||||
do_rollback_test 3.3 -setup {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE (i%4)==1;
|
||||
SAVEPOINT one;
|
||||
DELETE FROM t1 WHERE (i%2)==1;
|
||||
} -rollback {
|
||||
ROLLBACK TO one;
|
||||
} -select {
|
||||
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
|
||||
} -result {
|
||||
40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Now with some index scans that feature overflow keys.
|
||||
#
|
||||
set leader [string repeat "abcdefghij" 70]
|
||||
do_execsql_test 4.1 { UPDATE t1 SET h = $leader || h; }
|
||||
|
||||
do_eqp_test 4.2 {
|
||||
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
|
||||
} {0 0 0 {SCAN TABLE t1 USING INDEX i1}}
|
||||
do_rollback_test 4.3 -setup {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE (i%2)==1;
|
||||
} -select {
|
||||
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
|
||||
} -result {
|
||||
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40
|
||||
}
|
||||
do_rollback_test 4.4 -setup {
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE (i%4)==1;
|
||||
SAVEPOINT one;
|
||||
DELETE FROM t1 WHERE (i%2)==1;
|
||||
} -rollback {
|
||||
ROLLBACK TO one;
|
||||
} -select {
|
||||
SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
|
||||
} -result {
|
||||
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# 2014-11-12
|
||||
#
|
||||
# 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 that errors encountered during a ROLLBACK operation correctly
|
||||
# affect ongoing SQL statements.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix rollbackfault
|
||||
|
||||
|
||||
proc int2hex {i} { format %.2X $i }
|
||||
db func int2hex int2hex
|
||||
do_execsql_test 1.0 {
|
||||
SELECT int2hex(0), int2hex(100), int2hex(255)
|
||||
} {00 64 FF}
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(i, h);
|
||||
CREATE INDEX i1 ON t1(h);
|
||||
WITH data(a, b) AS (
|
||||
SELECT 1, int2hex(1)
|
||||
UNION ALL
|
||||
SELECT a+1, int2hex(a+1) FROM data WHERE a<40
|
||||
)
|
||||
INSERT INTO t1 SELECT * FROM data;
|
||||
} {}
|
||||
|
||||
foreach f {oom ioerr} {
|
||||
do_faultsim_test 1.2 -faults $f* -prep {
|
||||
set sql1 { SELECT i FROM t1 WHERE (i%2)==0 }
|
||||
set sql2 { SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h }
|
||||
set ::s1 [sqlite3_prepare db $sql1 -1 dummy]
|
||||
set ::s2 [sqlite3_prepare db $sql2 -1 dummy]
|
||||
|
||||
for {set i 0} {$i < 10} {incr i} { sqlite3_step $::s1 }
|
||||
for {set i 0} {$i < 3} {incr i} { sqlite3_step $::s2 }
|
||||
|
||||
execsql {
|
||||
BEGIN; DELETE FROM t1 WHERE (i%2)
|
||||
}
|
||||
} -body {
|
||||
execsql { ROLLBACK }
|
||||
} -test {
|
||||
|
||||
set res1 [list]
|
||||
set res2 [list]
|
||||
while {"SQLITE_ROW" == [sqlite3_step $::s1]} {
|
||||
lappend res1 [sqlite3_column_text $::s1 0]
|
||||
}
|
||||
while {"SQLITE_ROW" == [sqlite3_step $::s2]} {
|
||||
lappend res2 [sqlite3_column_text $::s2 0]
|
||||
}
|
||||
set rc1 [sqlite3_finalize $::s1]
|
||||
set rc2 [sqlite3_finalize $::s2]
|
||||
|
||||
catchsql { ROLLBACK }
|
||||
|
||||
if {$rc1=="SQLITE_OK" && $rc2=="SQLITE_OK"
|
||||
&& $res1=="22 24 26 28 30 32 34 36 38 40"
|
||||
&& $res2=="8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40"
|
||||
} {
|
||||
# This is Ok.
|
||||
} elseif {$rc1!="SQLITE_OK" && $rc2!="SQLITE_OK" && $res1=="" &&$res2==""} {
|
||||
# Also Ok.
|
||||
} else {
|
||||
error "statements don't look right"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+1
-1
@@ -315,7 +315,7 @@ ifcapable incrblob {
|
||||
do_test savepoint-5.3.2.3 {
|
||||
set rc [catch {seek $fd 0; read $fd} res]
|
||||
set rc
|
||||
} {0}
|
||||
} {1}
|
||||
do_test savepoint-5.3.3 {
|
||||
catchsql {RELEASE def}
|
||||
} {0 {}}
|
||||
|
||||
@@ -30,7 +30,6 @@ do_test savepoint7-1.1 {
|
||||
db eval {SELECT * FROM t1} {
|
||||
db eval {
|
||||
SAVEPOINT x2;
|
||||
CREATE TABLE IF NOT EXISTS t3(xyz);
|
||||
INSERT INTO t2 VALUES($a,$b,$c);
|
||||
RELEASE x2;
|
||||
}
|
||||
@@ -47,7 +46,7 @@ do_test savepoint7-1.2 {
|
||||
RELEASE x2;
|
||||
}
|
||||
}
|
||||
db eval {SELECT * FROM t2;}
|
||||
db eval {SELECT * FROM t2}
|
||||
} {1 2 3 4 5 6 7 8 9}
|
||||
|
||||
do_test savepoint7-1.3 {
|
||||
@@ -66,7 +65,7 @@ do_test savepoint7-1.3 {
|
||||
# queries in outer contexts.
|
||||
#
|
||||
do_test savepoint7-2.1 {
|
||||
db eval {DELETE FROM t2; SAVEPOINT x1; CREATE TABLE t4(abc);}
|
||||
db eval {DELETE FROM t2; SAVEPOINT x1;}
|
||||
set rc [catch {
|
||||
db eval {SELECT * FROM t1} {
|
||||
db eval {
|
||||
@@ -86,7 +85,6 @@ do_test savepoint7-2.2 {
|
||||
db eval {SELECT * FROM t1} {
|
||||
db eval {
|
||||
SAVEPOINT x2;
|
||||
CREATE TABLE t5(pqr);
|
||||
INSERT INTO t2 VALUES($a,$b,$c);
|
||||
ROLLBACK TO x2;
|
||||
}
|
||||
|
||||
@@ -1,398 +0,0 @@
|
||||
# 2014 November 1
|
||||
#
|
||||
# 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 scanstatus
|
||||
|
||||
ifcapable !scanstatus {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE t2(x, y);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t2 VALUES('a', 'b');
|
||||
INSERT INTO t2 VALUES('c', 'd');
|
||||
INSERT INTO t2 VALUES('e', 'f');
|
||||
}
|
||||
|
||||
proc do_scanstatus_test {tn res} {
|
||||
set stmt [db_last_stmt_ptr db]
|
||||
set idx 0
|
||||
set ret [list]
|
||||
while {1} {
|
||||
set r [sqlite3_stmt_scanstatus $stmt $idx]
|
||||
if {[llength $r]==0} break
|
||||
lappend ret {*}$r
|
||||
incr idx
|
||||
}
|
||||
|
||||
uplevel [list do_test $tn [list set {} $ret] [list {*}$res]]
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 { SELECT count(*) FROM t1, t2; } 6
|
||||
do_scanstatus_test 1.2 {
|
||||
nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN TABLE t1}
|
||||
nLoop 2 nVisit 6 nEst 1048576.0 zName t2 zExplain {SCAN TABLE t2}
|
||||
}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
ANALYZE;
|
||||
SELECT count(*) FROM t1, t2;
|
||||
} 6
|
||||
do_scanstatus_test 1.4 {
|
||||
nLoop 1 nVisit 2 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
|
||||
nLoop 2 nVisit 6 nEst 3.0 zName t2 zExplain {SCAN TABLE t2}
|
||||
}
|
||||
|
||||
do_execsql_test 1.5 { ANALYZE }
|
||||
do_execsql_test 1.6 {
|
||||
SELECT count(*) FROM t1, t2 WHERE t2.rowid>1;
|
||||
} 4
|
||||
do_scanstatus_test 1.7 {
|
||||
nLoop 1 nVisit 2 nEst 2.0 zName t2 zExplain
|
||||
{SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
|
||||
nLoop 2 nVisit 4 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
|
||||
}
|
||||
|
||||
do_execsql_test 1.8 {
|
||||
SELECT count(*) FROM t1, t2 WHERE t2.rowid>1;
|
||||
} 4
|
||||
|
||||
do_scanstatus_test 1.9 {
|
||||
nLoop 2 nVisit 4 nEst 2.0 zName t2 zExplain
|
||||
{SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
|
||||
nLoop 4 nVisit 8 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
|
||||
}
|
||||
|
||||
do_test 1.9 {
|
||||
sqlite3_stmt_scanstatus_reset [db_last_stmt_ptr db]
|
||||
} {}
|
||||
|
||||
do_scanstatus_test 1.10 {
|
||||
nLoop 0 nVisit 0 nEst 2.0 zName t2 zExplain
|
||||
{SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
|
||||
nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try a few different types of scans.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TABLE x1(i INTEGER PRIMARY KEY, j);
|
||||
INSERT INTO x1 VALUES(1, 'one');
|
||||
INSERT INTO x1 VALUES(2, 'two');
|
||||
INSERT INTO x1 VALUES(3, 'three');
|
||||
INSERT INTO x1 VALUES(4, 'four');
|
||||
CREATE INDEX x1j ON x1(j);
|
||||
|
||||
SELECT * FROM x1 WHERE i=2;
|
||||
} {2 two}
|
||||
|
||||
do_scanstatus_test 2.2 {
|
||||
nLoop 1 nVisit 1 nEst 1.0 zName x1
|
||||
zExplain {SEARCH TABLE x1 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.3.1 {
|
||||
SELECT * FROM x1 WHERE j='two'
|
||||
} {2 two}
|
||||
do_scanstatus_test 2.3.2 {
|
||||
nLoop 1 nVisit 1 nEst 10.0 zName x1j
|
||||
zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.4.1 {
|
||||
SELECT * FROM x1 WHERE j<'two'
|
||||
} {4 four 1 one 3 three}
|
||||
do_scanstatus_test 2.4.2 {
|
||||
nLoop 1 nVisit 3 nEst 262144.0 zName x1j
|
||||
zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j<?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.5.1 {
|
||||
SELECT * FROM x1 WHERE j>='two'
|
||||
} {2 two}
|
||||
do_scanstatus_test 2.5.2 {
|
||||
nLoop 1 nVisit 1 nEst 262144.0 zName x1j
|
||||
zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.6.1 {
|
||||
SELECT * FROM x1 WHERE j BETWEEN 'three' AND 'two'
|
||||
} {3 three 2 two}
|
||||
do_scanstatus_test 2.6.2 {
|
||||
nLoop 1 nVisit 2 nEst 16384.0 zName x1j
|
||||
zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>? AND j<?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.7.1 {
|
||||
CREATE TABLE x2(i INTEGER, j, k);
|
||||
INSERT INTO x2 SELECT i, j, i || ' ' || j FROM x1;
|
||||
CREATE INDEX x2j ON x2(j);
|
||||
CREATE INDEX x2ij ON x2(i, j);
|
||||
SELECT * FROM x2 WHERE j BETWEEN 'three' AND 'two'
|
||||
} {3 three {3 three} 2 two {2 two}}
|
||||
|
||||
do_scanstatus_test 2.7.2 {
|
||||
nLoop 1 nVisit 2 nEst 16384.0 zName x2j
|
||||
zExplain {SEARCH TABLE x2 USING INDEX x2j (j>? AND j<?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.8.1 {
|
||||
SELECT * FROM x2 WHERE i=1 AND j='two'
|
||||
}
|
||||
do_scanstatus_test 2.8.2 {
|
||||
nLoop 1 nVisit 0 nEst 8.0 zName x2ij
|
||||
zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.9.1 {
|
||||
SELECT * FROM x2 WHERE i=5 AND j='two'
|
||||
}
|
||||
do_scanstatus_test 2.9.2 {
|
||||
nLoop 1 nVisit 0 nEst 8.0 zName x2ij
|
||||
zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 2.10.1 {
|
||||
SELECT * FROM x2 WHERE i=3 AND j='three'
|
||||
} {3 three {3 three}}
|
||||
do_scanstatus_test 2.10.2 {
|
||||
nLoop 1 nVisit 1 nEst 8.0 zName x2ij
|
||||
zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try with queries that use the OR optimization.
|
||||
#
|
||||
do_execsql_test 3.1 {
|
||||
CREATE TABLE a1(a, b, c, d);
|
||||
CREATE INDEX a1a ON a1(a);
|
||||
CREATE INDEX a1bc ON a1(b, c);
|
||||
|
||||
WITH d(x) AS (SELECT 1 UNION ALL SELECT x+1 AS n FROM d WHERE n<=100)
|
||||
INSERT INTO a1 SELECT x, x, x, x FROM d;
|
||||
}
|
||||
|
||||
do_execsql_test 3.2.1 {
|
||||
SELECT d FROM a1 WHERE (a=4 OR b=13)
|
||||
} {4 13}
|
||||
do_scanstatus_test 3.2.2 {
|
||||
nLoop 1 nVisit 1 nEst 10.0 zName a1a
|
||||
zExplain {SEARCH TABLE a1 USING INDEX a1a (a=?)}
|
||||
nLoop 1 nVisit 1 nEst 10.0 zName a1bc
|
||||
zExplain {SEARCH TABLE a1 USING INDEX a1bc (b=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 3.2.1 {
|
||||
SELECT count(*) FROM a1 WHERE (a BETWEEN 4 AND 12) OR (b BETWEEN 40 AND 60)
|
||||
} {30}
|
||||
do_scanstatus_test 3.2.2 {
|
||||
nLoop 1 nVisit 9 nEst 16384.0 zName a1a
|
||||
zExplain {SEARCH TABLE a1 USING INDEX a1a (a>? AND a<?)}
|
||||
nLoop 1 nVisit 21 nEst 16384.0 zName a1bc
|
||||
zExplain {SEARCH TABLE a1 USING INDEX a1bc (b>? AND b<?)}
|
||||
}
|
||||
|
||||
do_execsql_test 3.3.1 {
|
||||
SELECT count(*) FROM a1 AS x, a1 AS y
|
||||
WHERE (x.a BETWEEN 4 AND 12) AND (y.b BETWEEN 1 AND 10)
|
||||
} {90}
|
||||
do_scanstatus_test 3.2.2 {
|
||||
nLoop 1 nVisit 10 nEst 16384.0 zName a1bc
|
||||
zExplain {SEARCH TABLE a1 AS y USING COVERING INDEX a1bc (b>? AND b<?)}
|
||||
nLoop 10 nVisit 90 nEst 16384.0 zName a1a
|
||||
zExplain {SEARCH TABLE a1 AS x USING COVERING INDEX a1a (a>? AND a<?)}
|
||||
}
|
||||
|
||||
do_execsql_test 3.4.1 {
|
||||
SELECT count(*) FROM a1 WHERE a IN (1, 5, 10, 15);
|
||||
} {4}
|
||||
do_scanstatus_test 3.4.2 {
|
||||
nLoop 1 nVisit 4 nEst 40.0 zName a1a
|
||||
zExplain {SEARCH TABLE a1 USING COVERING INDEX a1a (a=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 3.4.1 {
|
||||
SELECT count(*) FROM a1 WHERE rowid IN (1, 5, 10, 15);
|
||||
} {4}
|
||||
do_scanstatus_test 3.4.2 {
|
||||
nLoop 1 nVisit 4 nEst 4.0 zName a1
|
||||
zExplain {SEARCH TABLE a1 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that scanstatus() data is not available for searches performed
|
||||
# by triggers.
|
||||
#
|
||||
# It is available for searches performed as part of FK processing, but
|
||||
# not FK action processing.
|
||||
#
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE TABLE t2(x PRIMARY KEY, y, z);
|
||||
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
|
||||
SELECT * FROM t2 WHERE x BETWEEN 20 AND 40;
|
||||
END;
|
||||
WITH d(x) AS (SELECT 1 UNION ALL SELECT x+1 AS n FROM d WHERE n<=100)
|
||||
INSERT INTO t2 SELECT x, x*2, x*3 FROM d;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1.1 { INSERT INTO t1 VALUES(1, 2, 3); }
|
||||
do_scanstatus_test 4.1.2 { }
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
CREATE TABLE p1(x PRIMARY KEY);
|
||||
INSERT INTO p1 VALUES(1), (2), (3), (4);
|
||||
CREATE TABLE c1(y REFERENCES p1);
|
||||
INSERT INTO c1 VALUES(1), (2), (3);
|
||||
PRAGMA foreign_keys=on;
|
||||
}
|
||||
do_execsql_test 4.2.1 { DELETE FROM p1 WHERE x=4 }
|
||||
do_scanstatus_test 4.2.2 {
|
||||
nLoop 1 nVisit 1 nEst 1.0 zName sqlite_autoindex_p1_1
|
||||
zExplain {SEARCH TABLE p1 USING INDEX sqlite_autoindex_p1_1 (x=?)}
|
||||
|
||||
nLoop 1 nVisit 3 nEst 524288.0 zName c1 zExplain {SCAN TABLE c1}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Further tests of different scan types.
|
||||
#
|
||||
reset_db
|
||||
proc tochar {i} {
|
||||
set alphabet {a b c d e f g h i j k l m n o p q r s t u v w x y z}
|
||||
return [lindex $alphabet [expr $i % [llength $alphabet]]]
|
||||
}
|
||||
db func tochar tochar
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(0, 1, 'a');
|
||||
INSERT INTO t1 VALUES(1, 0, 'b');
|
||||
INSERT INTO t1 VALUES(2, 1, 'c');
|
||||
INSERT INTO t1 VALUES(3, 0, 'd');
|
||||
INSERT INTO t1 VALUES(4, 1, 'e');
|
||||
INSERT INTO t1 VALUES(5, 0, 'a');
|
||||
INSERT INTO t1 VALUES(6, 1, 'b');
|
||||
INSERT INTO t1 VALUES(7, 0, 'c');
|
||||
INSERT INTO t1 VALUES(8, 1, 'd');
|
||||
INSERT INTO t1 VALUES(9, 0, 'e');
|
||||
CREATE INDEX t1bc ON t1(b, c);
|
||||
|
||||
CREATE TABLE t2(x, y);
|
||||
CREATE INDEX t2xy ON t2(x, y);
|
||||
WITH data(i, x, y) AS (
|
||||
SELECT 0, 0, tochar(0)
|
||||
UNION ALL
|
||||
SELECT i+1, (i+1)%2, tochar(i+1) FROM data WHERE i<500
|
||||
) INSERT INTO t2 SELECT x, y FROM data;
|
||||
|
||||
CREATE TABLE t3(x, y);
|
||||
INSERT INTO t3 SELECT * FROM t2;
|
||||
|
||||
ANALYZE;
|
||||
}
|
||||
|
||||
do_execsql_test 5.1.1 {
|
||||
SELECT count(*) FROM t1 WHERE a IN (SELECT b FROM t1 AS ii)
|
||||
} {2}
|
||||
do_scanstatus_test 5.1.2 {
|
||||
nLoop 1 nVisit 10 nEst 10.0 zName t1bc
|
||||
zExplain {SCAN TABLE t1 AS ii USING COVERING INDEX t1bc}
|
||||
nLoop 1 nVisit 2 nEst 8.0 zName sqlite_autoindex_t1_1
|
||||
zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
|
||||
}
|
||||
|
||||
do_execsql_test 5.2.1 {
|
||||
SELECT count(*) FROM t1 WHERE a IN (0, 1)
|
||||
} {2}
|
||||
do_scanstatus_test 5.2.2 {
|
||||
nLoop 1 nVisit 2 nEst 2.0 zName sqlite_autoindex_t1_1
|
||||
zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
|
||||
}
|
||||
|
||||
do_eqp_test 5.3.1 {
|
||||
SELECT count(*) FROM t2 WHERE y = 'j';
|
||||
} {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}}
|
||||
do_execsql_test 5.3.2 {
|
||||
SELECT count(*) FROM t2 WHERE y = 'j';
|
||||
} {19}
|
||||
do_scanstatus_test 5.3.3 {
|
||||
nLoop 1 nVisit 19 nEst 56.0 zName t2xy zExplain
|
||||
{SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
|
||||
}
|
||||
|
||||
do_eqp_test 5.4.1 {
|
||||
SELECT count(*) FROM t1, t2 WHERE y = c;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING COVERING INDEX t1bc}
|
||||
0 1 1 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
|
||||
}
|
||||
do_execsql_test 5.4.2 {
|
||||
SELECT count(*) FROM t1, t2 WHERE y = c;
|
||||
} {200}
|
||||
do_scanstatus_test 5.4.3 {
|
||||
nLoop 1 nVisit 10 nEst 10.0 zName t1bc
|
||||
zExplain {SCAN TABLE t1 USING COVERING INDEX t1bc}
|
||||
nLoop 10 nVisit 200 nEst 56.0 zName t2xy
|
||||
zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
|
||||
}
|
||||
|
||||
do_eqp_test 5.5.1 {
|
||||
SELECT count(*) FROM t1, t3 WHERE y = c;
|
||||
} {
|
||||
0 0 1 {SCAN TABLE t3}
|
||||
0 1 0 {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)}
|
||||
}
|
||||
do_execsql_test 5.5.2 {
|
||||
SELECT count(*) FROM t1, t3 WHERE y = c;
|
||||
} {200}
|
||||
do_scanstatus_test 5.5.3 {
|
||||
nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN TABLE t3}
|
||||
nLoop 501 nVisit 200 nEst 20.0 zName auto-index zExplain
|
||||
{SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Virtual table scans
|
||||
#
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts4;
|
||||
INSERT INTO ft1 VALUES('a d c f g h e i f c');
|
||||
INSERT INTO ft1 VALUES('g c h b g b f f f g');
|
||||
INSERT INTO ft1 VALUES('h h c c h f a e d d');
|
||||
INSERT INTO ft1 VALUES('e j i j i e b c f g');
|
||||
INSERT INTO ft1 VALUES('g f b g j c h a d f');
|
||||
INSERT INTO ft1 VALUES('j i a e g f a i a c');
|
||||
INSERT INTO ft1 VALUES('f d g g j j c a h g');
|
||||
INSERT INTO ft1 VALUES('b d h a d j j j b i');
|
||||
INSERT INTO ft1 VALUES('j e a b j e c b c i');
|
||||
INSERT INTO ft1 VALUES('a d e f b j j c g d');
|
||||
}
|
||||
do_execsql_test 6.1.1 {
|
||||
SELECT count(*) FROM ft1 WHERE ft1 MATCH 'd'
|
||||
} {6}
|
||||
do_scanstatus_test 6.1.2 {
|
||||
nLoop 1 nVisit 6 nEst 24.0 zName ft1 zExplain
|
||||
{SCAN TABLE ft1 VIRTUAL TABLE INDEX 3:}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -273,23 +273,4 @@ do_execsql_test skipscan1-6.3 {
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=1;
|
||||
} {~/ANY/}
|
||||
|
||||
# If the sqlite_stat1 entry includes the "noskipscan" token, then never use
|
||||
# skipscan with that index.
|
||||
#
|
||||
do_execsql_test skipscan1-7.1 {
|
||||
UPDATE sqlite_stat1 SET stat='500000 125000 1 sz=100';
|
||||
ANALYZE sqlite_master;
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=1;
|
||||
} {/ANY/}
|
||||
do_execsql_test skipscan1-7.2 {
|
||||
UPDATE sqlite_stat1 SET stat='500000 125000 1 noskipscan sz=100';
|
||||
ANALYZE sqlite_master;
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=1;
|
||||
} {~/ANY/}
|
||||
do_execsql_test skipscan1-7.3 {
|
||||
UPDATE sqlite_stat1 SET stat='500000 125000 1 sz=100 noskipscan';
|
||||
ANALYZE sqlite_master;
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=1;
|
||||
} {~/ANY/}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -141,60 +141,5 @@ do_execsql_test 2.2 {
|
||||
} {/INDEX good .bb=. AND aa=. AND dd>. AND dd<../}
|
||||
|
||||
|
||||
# Create a table containing 100 rows. Column "a" contains a copy of the
|
||||
# rowid value - sequentially increasing integers from 1 to 100. Column
|
||||
# "b" contains the value of (a % 5). Columns "c" and "d" both contain
|
||||
# constant values (i.e. the same for every row).
|
||||
#
|
||||
# Then create a second table t2. t2 is the same as t3 except for the
|
||||
# order in which the indexes are created.
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t3(a, b, c, d);
|
||||
CREATE INDEX t3_ba ON t3(b, a, c);
|
||||
CREATE INDEX t3_a ON t3(a);
|
||||
|
||||
WITH d(a, b) AS (
|
||||
SELECT 1, 1
|
||||
UNION ALL
|
||||
SELECT a+1, (a+1) % 5 FROM d WHERE a<100
|
||||
)
|
||||
INSERT INTO t3 SELECT a, b, 'c', 'd' FROM d;
|
||||
|
||||
CREATE TABLE t2(a, b, c, d);
|
||||
CREATE INDEX t2_a ON t2(a);
|
||||
CREATE INDEX t2_ba ON t2(b, a, c);
|
||||
INSERT INTO t2 SELECT * FROM t3;
|
||||
|
||||
ANALYZE;
|
||||
SELECT * FROM sqlite_stat1;
|
||||
} {
|
||||
t2 t2_ba {100 20 1 1}
|
||||
t2 t2_a {100 1}
|
||||
t3 t3_a {100 1}
|
||||
t3 t3_ba {100 20 1 1}
|
||||
}
|
||||
|
||||
# Use index "t3_a", as (a=?) is expected to match only a single row.
|
||||
#
|
||||
do_eqp_test 3.1 {
|
||||
SELECT * FROM t3 WHERE a = ? AND c = ?
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX t3_a (a=?)}
|
||||
}
|
||||
|
||||
# The same query on table t2. This should use index "t2_a", for the
|
||||
# same reason. At one point though, it was mistakenly using a skip-scan.
|
||||
#
|
||||
do_eqp_test 3.2 {
|
||||
SELECT * FROM t2 WHERE a = ? AND c = ?
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2_a (a=?)}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -62,6 +62,7 @@ foreach {tn script} {
|
||||
|
||||
do_execsql_test $tn.2.4 { PRAGMA integrity_check } {ok}
|
||||
|
||||
breakpoint
|
||||
do_execsql_test $tn.3 {
|
||||
PRAGMA cache_size = 5;
|
||||
WITH r(x,y) AS (
|
||||
|
||||
+1
-17
@@ -11,6 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the CREATE TABLE statement.
|
||||
#
|
||||
# $Id: table.test,v 1.53 2009/06/05 17:09:12 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -772,21 +773,4 @@ do_catchsql_test table-16.7 {
|
||||
INSERT INTO t16 DEFAULT VALUES;
|
||||
} {1 {unknown function: group_concat()}}
|
||||
|
||||
# Ticket [https://www.sqlite.org/src/info/094d39a4c95ee4abbc417f04214617675ba15c63]
|
||||
# describes a assertion fault that occurs on a CREATE TABLE .. AS SELECT statement.
|
||||
# the following test verifies that the problem has been fixed.
|
||||
#
|
||||
do_execsql_test table-17.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a TEXT);
|
||||
INSERT INTO t1(a) VALUES(1),(2);
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(x TEXT, y TEXT);
|
||||
INSERT INTO t2(x,y) VALUES(3,4);
|
||||
DROP TABLE IF EXISTS t3;
|
||||
CREATE TABLE t3 AS
|
||||
SELECT a AS p, coalesce(y,a) AS q FROM t1 LEFT JOIN t2 ON a=x;
|
||||
SELECT p, q, '|' FROM t3 ORDER BY p;
|
||||
} {1 1 | 2 2 |}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -40,7 +40,6 @@ db function force_rollback force_rollback
|
||||
do_test tkt-f7772-1.2 {
|
||||
catchsql {
|
||||
BEGIN IMMEDIATE;
|
||||
CREATE TABLE xyzzy(abc);
|
||||
SELECT x, force_rollback(), EXISTS(SELECT 1 FROM t3 WHERE w=x) FROM t2;
|
||||
}
|
||||
} {1 {abort due to ROLLBACK}}
|
||||
@@ -68,7 +67,7 @@ do_test tkt-f7772-2.2 {
|
||||
catchsql {
|
||||
SELECT x, force_rollback(), EXISTS(SELECT 1 FROM t3 WHERE w=x) FROM t2
|
||||
}
|
||||
} {1 {abort due to ROLLBACK}}
|
||||
} {1 {callback requested query abort}}
|
||||
do_test tkt-f7772-2.3 {
|
||||
sqlite3_get_autocommit db
|
||||
} {1}
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ do_test trans3-1.4 {
|
||||
db eval {SELECT * FROM t1}
|
||||
} {1 2 3 4}
|
||||
do_test trans3-1.5 {
|
||||
db eval {BEGIN; CREATE TABLE xyzzy(abc);}
|
||||
db eval BEGIN
|
||||
db eval {INSERT INTO t1 VALUES(5);}
|
||||
set ::ecode {}
|
||||
set x [catch {
|
||||
|
||||
@@ -32,7 +32,6 @@ ifcapable {!trigger} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
set ::testprefix trigger9
|
||||
|
||||
proc has_rowdata {sql} {
|
||||
expr {[lsearch [execsql "explain $sql"] RowData]>=0}
|
||||
@@ -221,36 +220,4 @@ ifcapable compound {
|
||||
} {2}
|
||||
}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 4.1 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE log(x);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
CREATE VIEW v1 AS SELECT a, b FROM t1;
|
||||
|
||||
CREATE TRIGGER tr1 INSTEAD OF DELETE ON v1 BEGIN
|
||||
INSERT INTO log VALUES('delete');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER tr2 INSTEAD OF UPDATE ON v1 BEGIN
|
||||
INSERT INTO log VALUES('update');
|
||||
END;
|
||||
|
||||
CREATE TRIGGER tr3 INSTEAD OF INSERT ON v1 BEGIN
|
||||
INSERT INTO log VALUES('insert');
|
||||
END;
|
||||
}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
DELETE FROM v1 WHERE rowid=1;
|
||||
} {}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
UPDATE v1 SET a=b WHERE rowid=2;
|
||||
} {}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -604,19 +604,5 @@ do_test update-14.4 {
|
||||
|
||||
} ;# ifcapable {trigger}
|
||||
|
||||
# Ticket [https://www.sqlite.org/src/tktview/43107840f1c02] on 2014-10-29
|
||||
# An assertion fault on UPDATE
|
||||
#
|
||||
do_execsql_test update-15.1 {
|
||||
CREATE TABLE t15(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t15(a,b) VALUES(10,'abc'),(20,'def'),(30,'ghi');
|
||||
ALTER TABLE t15 ADD COLUMN c;
|
||||
CREATE INDEX t15c ON t15(c);
|
||||
INSERT INTO t15(a,b)
|
||||
VALUES(5,'zyx'),(15,'wvu'),(25,'tsr'),(35,'qpo');
|
||||
UPDATE t15 SET c=printf("y%d",a) WHERE c IS NULL;
|
||||
SELECT a,b,c,'|' FROM t15 ORDER BY a;
|
||||
} {5 zyx y5 | 10 abc y10 | 15 wvu y15 | 20 def y20 | 25 tsr y25 | 30 ghi y30 | 35 qpo y35 |}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -185,7 +185,8 @@ do_execsql_test without_rowid5-5.9 {
|
||||
# EVIDENCE-OF: R-12643-30541 The incremental blob I/O mechanism does not
|
||||
# work for WITHOUT ROWID tables.
|
||||
#
|
||||
# EVIDENCE-OF: R-40134-30296 Table zTable is a WITHOUT ROWID table
|
||||
# EVIDENCE-OF: R-25760-33257 The sqlite3_blob_open() interface will fail
|
||||
# for a WITHOUT ROWID table.
|
||||
#
|
||||
do_execsql_test without_rowid5-6.1 {
|
||||
CREATE TABLE b1(a INTEGER PRIMARY KEY, b BLOB) WITHOUT ROWID;
|
||||
|
||||
+4
-5
@@ -39,7 +39,6 @@ int main(int argc, char **argv){
|
||||
int nSample;
|
||||
i64 iVal;
|
||||
const char *zSep;
|
||||
int iRow = 0;
|
||||
|
||||
if( argc!=2 ){
|
||||
fprintf(stderr, "Usage: %s DATABASE-FILE\n", argv[0]);
|
||||
@@ -61,13 +60,13 @@ int main(int argc, char **argv){
|
||||
}
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
if( zIdx==0 || strcmp(zIdx, (const char*)sqlite3_column_text(pStmt,0))!=0 ){
|
||||
if( zIdx ) printf("\n**************************************"
|
||||
"**************\n\n");
|
||||
if( zIdx ) printf("\n");
|
||||
sqlite3_free(zIdx);
|
||||
zIdx = sqlite3_mprintf("%s", sqlite3_column_text(pStmt,0));
|
||||
iRow = 0;
|
||||
printf("%s:\n", zIdx);
|
||||
}else{
|
||||
printf(" -----------------------------------------------------------\n");
|
||||
}
|
||||
printf("%s sample %d ------------------------------------\n", zIdx, ++iRow);
|
||||
printf(" nEq = %s\n", sqlite3_column_text(pStmt,1));
|
||||
printf(" nLt = %s\n", sqlite3_column_text(pStmt,2));
|
||||
printf(" nDLt = %s\n", sqlite3_column_text(pStmt,3));
|
||||
|
||||
-123
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
** A utility program to translate SQLite varints into decimal and decimal
|
||||
** integers into varints.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 i64;
|
||||
typedef unsigned __int64 u64;
|
||||
#else
|
||||
typedef long long int i64;
|
||||
typedef unsigned long long int u64;
|
||||
#endif
|
||||
|
||||
static int hexValue(char c){
|
||||
if( c>='0' && c<='9' ) return c - '0';
|
||||
if( c>='a' && c<='f' ) return c - 'a' + 10;
|
||||
if( c>='A' && c<='F' ) return c - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char toHex(unsigned char c){
|
||||
return "0123456789abcdef"[c&0xf];
|
||||
}
|
||||
|
||||
static int putVarint(unsigned char *p, u64 v){
|
||||
int i, j, n;
|
||||
unsigned char buf[10];
|
||||
if( v & (((u64)0xff000000)<<32) ){
|
||||
p[8] = (unsigned char)v;
|
||||
v >>= 8;
|
||||
for(i=7; i>=0; i--){
|
||||
p[i] = (unsigned char)((v & 0x7f) | 0x80);
|
||||
v >>= 7;
|
||||
}
|
||||
return 9;
|
||||
}
|
||||
n = 0;
|
||||
do{
|
||||
buf[n++] = (unsigned char)((v & 0x7f) | 0x80);
|
||||
v >>= 7;
|
||||
}while( v!=0 );
|
||||
buf[0] &= 0x7f;
|
||||
for(i=0, j=n-1; j>=0; j--, i++){
|
||||
p[i] = buf[j];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int i;
|
||||
u64 x;
|
||||
u64 uX = 0;
|
||||
i64 iX;
|
||||
int n;
|
||||
unsigned char zHex[20];
|
||||
|
||||
if( argc==1 ){
|
||||
fprintf(stderr,
|
||||
"Usage:\n"
|
||||
" %s HH HH HH ... Convert varint to decimal\n"
|
||||
" %s DDDDD Convert decimal to varint\n"
|
||||
" Add '+' or '-' before DDDDD to disambiguate.\n",
|
||||
argv[0], argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if( argc>2
|
||||
|| (strlen(argv[1])==2 && hexValue(argv[1][0])>=0 && hexValue(argv[1][1])>=0)
|
||||
){
|
||||
/* Hex to decimal */
|
||||
for(i=1; i<argc && i<9; i++){
|
||||
if( strlen(argv[i])!=2 ){
|
||||
fprintf(stderr, "Not a hex byte: %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
x = (hexValue(argv[i][0])<<4) + hexValue(argv[i][1]);
|
||||
uX = (uX<<7) + (x&0x7f);
|
||||
if( (x&0x80)==0 ) break;
|
||||
}
|
||||
if( i==9 && i<argc ){
|
||||
if( strlen(argv[i])!=2 ){
|
||||
fprintf(stderr, "Not a hex byte: %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
x = (hexValue(argv[i][0])<<4) + hexValue(argv[i][1]);
|
||||
uX = (uX<<8) + x;
|
||||
}
|
||||
i++;
|
||||
if( i<argc ){
|
||||
fprintf(stderr, "Extra arguments: %s...\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
}else{
|
||||
char *z = argv[1];
|
||||
int sign = 1;
|
||||
if( z[0]=='+' ) z++;
|
||||
else if( z[0]=='-' ){ z++; sign = -1; }
|
||||
uX = 0;
|
||||
while( z[0] ){
|
||||
if( z[0]<'0' || z[0]>'9' ){
|
||||
fprintf(stderr, "Not a decimal number: %s", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
uX = uX*10 + z[0] - '0';
|
||||
z++;
|
||||
}
|
||||
if( sign<0 ){
|
||||
memcpy(&iX, &uX, 8);
|
||||
iX = -iX;
|
||||
memcpy(&uX, &iX, 8);
|
||||
}
|
||||
}
|
||||
n = putVarint(zHex, uX);
|
||||
printf("%lld =", (i64)uX);
|
||||
for(i=0; i<n; i++){
|
||||
printf(" %c%c", toHex(zHex[i]>>4), toHex(zHex[i]&0x0f));
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user