Compare commits

..

3 Commits

Author SHA1 Message Date
dan 003533f724 Dynamically resize the node hash table used by the rtree module.
FossilOrigin-Name: f94f3da5de2b1085ea1967ca8961a923e79f5a1181b9507a2f4c9e29e47cbe29
2023-04-27 19:27:55 +00:00
dan 6fe63748a9 Fix some problems with the rtree module and existing tests on this branch.
FossilOrigin-Name: 50e8a30be1a8d4af42a2c58bdffcf3c4eae00450f0bb9ec39548d5a52d2a68ee
2023-04-26 20:41:00 +00:00
drh dd8bb7d912 Hold the RTREE node cache open and defer writes until the very end of the
INSERT statement, for a 20x performance improvement on the test script
identified at [forum:/forumpost/6b8bca17bb884ef3|forum post 6b8bca17bb884ef3].  However, there are still bugs and tests will crash.

FossilOrigin-Name: b35cb7458fe16390f3b1f0b2acfd3d51fabd6bf9c5f176a44d8b3cc932f74149
2023-04-24 21:08:11 +00:00
54 changed files with 788 additions and 3318 deletions
+6 -9
View File
@@ -984,7 +984,6 @@ static int fts5StructureDecode(
*/
static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
fts5StructureMakeWritable(pRc, ppStruct);
assert( (ppStruct!=0 && (*ppStruct)!=0) || (*pRc)!=SQLITE_OK );
if( *pRc==SQLITE_OK ){
Fts5Structure *pStruct = *ppStruct;
int nLevel = pStruct->nLevel;
@@ -4635,9 +4634,6 @@ static void fts5SecureDeleteOverflow(
pLeaf = 0;
}else if( bDetailNone ){
break;
}else if( iNext>=pLeaf->szLeaf || iNext<4 ){
p->rc = FTS5_CORRUPT;
break;
}else{
int nShift = iNext - 4;
int nPg;
@@ -4692,6 +4688,7 @@ static void fts5SecureDeleteOverflow(
*/
static void fts5DoSecureDelete(
Fts5Index *p,
Fts5Structure *pStruct,
Fts5SegIter *pSeg
){
const int bDetailNone = (p->pConfig->eDetail==FTS5_DETAIL_NONE);
@@ -4809,7 +4806,7 @@ static void fts5DoSecureDelete(
for(iIdx=0, iKeyOff=0; iIdx<nIdx; iKey++){
u32 iVal = 0;
iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
if( (iKeyOff+iVal)>(u32)iStart ) break;
if( (iKeyOff+iVal)>iStart ) break;
iKeyOff += iVal;
}
@@ -4849,11 +4846,11 @@ static void fts5DoSecureDelete(
}
}
}else if( iStart==4 ){
int iPgno;
assert_nc( pSeg->iLeafPgno>pSeg->iTermLeafPgno );
/* The entry being removed may be the only position list in
** its doclist. */
int iPgno = pSeg->iLeafPgno-1;
for(iPgno=pSeg->iLeafPgno-1; iPgno>pSeg->iTermLeafPgno; iPgno-- ){
Fts5Data *pPg = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, iPgno));
int bEmpty = (pPg && pPg->nn==4);
@@ -4937,7 +4934,7 @@ static void fts5FlushSecureDelete(
i64 iRowid
){
const int f = FTS5INDEX_QUERY_SKIPHASH;
int nTerm = (int)strlen(zTerm);
int nTerm = strlen(zTerm);
Fts5Iter *pIter = 0; /* Used to find term instance */
fts5MultiIterNew(p, pStruct, f, 0, (const u8*)zTerm, nTerm, -1, 0, &pIter);
@@ -4952,7 +4949,7 @@ static void fts5FlushSecureDelete(
&& iRowid==fts5MultiIterRowid(pIter)
){
Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
fts5DoSecureDelete(p, pSeg);
fts5DoSecureDelete(p, pStruct, pSeg);
}
}
-99
View File
@@ -1,99 +0,0 @@
# 2023 April 30
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5corrupt7
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
sqlite3_fts5_may_be_corrupt 1
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
}
set doc [string repeat "a b " 30]
do_execsql_test 1.1 {
BEGIN;
INSERT INTO t1(rowid, x) VALUES(123, $doc);
INSERT INTO t1(rowid, x) VALUES(124, $doc);
COMMIT;
}
execsql_pp {
SELECT id, fts5_decode(id, block), quote(block) FROM t1_data
}
set rows [db eval { SELECT rowid FROM t1_data }]
db_save_and_close
foreach r $rows {
db_restore_and_reopen
proc edit_block {b} {
binary scan $b c* in
set out [lreplace $in 0 1 255 255]
binary format c* $out
}
db func edit_block edit_block
do_execsql_test 1.2.$r.1 {
UPDATE t1_data SET block = edit_block(block) WHERE rowid=$r;
}
do_execsql_test 1.2.$r.2 {
INSERT INTO t1(t1, rank) VALUES('secure-delete', 1);
}
do_test 1.2.$r.3 {
catchsql { DELETE FROM t1 WHERE rowid=123; }
catchsql { DELETE FROM t1 WHERE rowid=124; }
set {} {}
} {}
db close
}
foreach r $rows {
set r 137438953475
db_restore_and_reopen
proc edit_block {b} {
binary scan $b c* in
set out [lreplace $in end end 127]
binary format c* $out
}
db func edit_block edit_block
do_execsql_test 1.2.$r.1 {
UPDATE t1_data SET block = edit_block(block) WHERE rowid=$r;
}
do_execsql_test 1.2.$r.2 {
INSERT INTO t1(t1, rank) VALUES('secure-delete', 1);
}
do_test 1.2.$r.3 {
catchsql { DELETE FROM t1 WHERE rowid=124; }
catchsql { DELETE FROM t1 WHERE rowid=123; }
set {} {}
} {}
db close
}
finish_test
+5 -19
View File
@@ -148,9 +148,9 @@ static char* toBase64( u8 *pIn, int nbIn, char *pOut ){
}
/* Skip over text which is not base64 numeral(s). */
static char * skipNonB64( char *s, int nc ){
static char * skipNonB64( char *s ){
char c;
while( nc-- > 0 && (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s;
while( (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s;
return s;
}
@@ -159,7 +159,7 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
while( ncIn>0 && *pIn!=PAD_CHAR ){
static signed char nboi[] = { 0, 0, 1, 2, 3 };
char *pUse = skipNonB64(pIn, ncIn);
char *pUse = skipNonB64(pIn);
unsigned long qv = 0L;
int nti, nbo, nac;
ncIn -= (pUse - pIn);
@@ -219,16 +219,9 @@ static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
sqlite3_result_error(context, "blob expanded to base64 too big", -1);
return;
}
bBuf = (u8*)sqlite3_value_blob(av[0]);
if( !bBuf ){
if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
goto memFail;
}
sqlite3_result_text(context,"",-1,SQLITE_STATIC);
break;
}
cBuf = sqlite3_malloc(nc);
if( !cBuf ) goto memFail;
bBuf = (u8*)sqlite3_value_blob(av[0]);
nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf);
sqlite3_result_text(context, cBuf, nc, sqlite3_free);
break;
@@ -241,16 +234,9 @@ static void base64(sqlite3_context *context, int na, sqlite3_value *av[]){
}else if( nb<1 ){
nb = 1;
}
cBuf = (char *)sqlite3_value_text(av[0]);
if( !cBuf ){
if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
goto memFail;
}
sqlite3_result_zeroblob(context, 0);
break;
}
bBuf = sqlite3_malloc(nb);
if( !bBuf ) goto memFail;
cBuf = (char *)sqlite3_value_text(av[0]);
nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf);
sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
break;
+5 -19
View File
@@ -140,9 +140,9 @@ static u8 base85DigitValue( char c ){
#define B85_DARK_MAX 80
static char * skipNonB85( char *s, int nc ){
static char * skipNonB85( char *s ){
char c;
while( nc-- > 0 && (c = *s) && !IS_B85(c) ) ++s;
while( (c = *s) && !IS_B85(c) ) ++s;
return s;
}
@@ -212,7 +212,7 @@ static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){
if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn;
while( ncIn>0 ){
static signed char nboi[] = { 0, 0, 1, 2, 3, 4 };
char *pUse = skipNonB85(pIn, ncIn);
char *pUse = skipNonB85(pIn);
unsigned long qv = 0L;
int nti, nbo;
ncIn -= (pUse - pIn);
@@ -297,16 +297,9 @@ static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){
sqlite3_result_error(context, "blob expanded to base85 too big", -1);
return;
}
bBuf = (u8*)sqlite3_value_blob(av[0]);
if( !bBuf ){
if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
goto memFail;
}
sqlite3_result_text(context,"",-1,SQLITE_STATIC);
break;
}
cBuf = sqlite3_malloc(nc);
if( !cBuf ) goto memFail;
bBuf = (u8*)sqlite3_value_blob(av[0]);
nc = (int)(toBase85(bBuf, nb, cBuf, "\n") - cBuf);
sqlite3_result_text(context, cBuf, nc, sqlite3_free);
break;
@@ -319,16 +312,9 @@ static void base85(sqlite3_context *context, int na, sqlite3_value *av[]){
}else if( nb<1 ){
nb = 1;
}
cBuf = (char *)sqlite3_value_text(av[0]);
if( !cBuf ){
if( SQLITE_NOMEM==sqlite3_errcode(sqlite3_context_db_handle(context)) ){
goto memFail;
}
sqlite3_result_zeroblob(context, 0);
break;
}
bBuf = sqlite3_malloc(nb);
if( !bBuf ) goto memFail;
cBuf = (char *)sqlite3_value_text(av[0]);
nb = (int)(fromBase85(cBuf, nc, bBuf) - bBuf);
sqlite3_result_blob(context, bBuf, nb, sqlite3_free);
break;
-202
View File
@@ -1,202 +0,0 @@
/*
** 2023-04-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.
**
******************************************************************************
**
** This SQLite extension implements a the random_json(SEED) and
** random_json5(SEED) functions. Given a numeric SEED value, these
** routines generate pseudo-random JSON or JSON5, respectively. The
** same value is always generated for the same seed.
**
** These SQL functions are intended for testing. They do not have any
** practical real-world use, that we know of.
**
** COMPILE:
**
** gcc --shared -fPIC -o randomjson.so -I. ext/misc/randomjson.c
**
** USING FROM THE CLI:
**
** .load ./randomjson
** SELECT random_json(1);
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdlib.h>
/* Pseudo-random number generator */
typedef struct Prng {
unsigned int x, y;
} Prng;
/* Reseed the PRNG */
static void prngSeed(Prng *p, unsigned int iSeed){
p->x = iSeed | 1;
p->y = iSeed;
}
/* Extract a random number */
static unsigned int prngInt(Prng *p){
p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
p->y = p->y*1103515245 + 12345;
return p->x ^ p->y;
}
static const char *azJsonAtoms[] = {
/* JSON /* JSON-5 */
"0", "0",
"1", "1",
"-1", "-1",
"2", "+2",
"3", "3",
"2.5", "2.5",
"0.75", ".75",
"-4.0e2", "-4.e2",
"5.0e-3", "+5e-3",
"0", "0x0",
"512", "0x200",
"256", "+0x100",
"-2748", "-0xabc",
"true", "true",
"false", "false",
"null", "null",
"9.0e999", "Infinity",
"-9.0e999", "-Infinity",
"9.0e999", "+Infinity",
"null", "NaN",
"-0.0005123", "-0.0005123",
"4.35e-3", "+4.35e-3",
"\"gem\\\"hay\"", "\"gem\\\"hay\"",
"\"icy'joy\"", "'icy\\'joy\'",
"\"keylog\"", "\"key\\\nlog\"",
"\"mix\\\\\\tnet\"", "\"mix\\\\\\tnet\"",
"{}", "{}",
"[]", "[]",
"[]", "[/*empty*/]",
"{}", "{//empty\n}",
"\"ask\"", "\"ask\"",
"\"bag\"", "\"bag\"",
"\"can\"", "\"can\"",
"\"day\"", "\"day\"",
"\"end\"", "'end'",
"\"fly\"", "\"fly\"",
"\"\"", "\"\"",
};
static const char *azJsonTemplate[] = {
/* JSON JSON-5 */
"{\"a\":%,\"b\":%,\"c\":%}", "{a:%,b:%,c:%}",
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"e\":%}", "{a:%,b:%,c:%,d:%,e:%}",
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,\"\":%}",
"{\"d\":%}", "{d:%}",
"{\"eeee\":%, \"ffff\":%}", "{eeee:% /*and*/, ffff:%}",
"{\"$g\":%,\"_h_\":%}", "{$g:%,_h_:%,}",
"{\"x\":%,\n \"y\":%}", "{\"x\":%,\n \"y\":%}",
"{\"a b c d\":%,\"e\":%,\"f\":%,\"x\":%,\"y\":%}",
"{\"a b c d\":%,e:%,f:%,x:%,y:%}",
"{\"Z\":%}", "{Z:%,}",
"[%]", "[%,]",
"[%,%]", "[%,%]",
"[%,%,%]", "[%,%,%,]",
"[%,%,%,%]", "[%,%,%,%]",
"[%,%,%,%,%]", "[%,%,%,%,%]",
};
#define count(X) (sizeof(X)/sizeof(X[0]))
#define STRSZ 10000
static void jsonExpand(
const char *zSrc,
char *zDest,
Prng *p,
int eType, /* 0 for JSON, 1 for JSON5 */
unsigned int r /* Growth probability 0..1000. 0 means no growth */
){
unsigned int i, j, k;
const char *z;
size_t n;
j = 0;
if( zSrc==0 ){
k = prngInt(p)%(count(azJsonTemplate)/2);
k = k*2 + eType;
zSrc = azJsonTemplate[k];
}
if( strlen(zSrc)>=STRSZ/10 ) r = 0;
for(i=0; zSrc[i]; i++){
if( zSrc[i]!='%' ){
if( j<STRSZ ) zDest[j++] = zSrc[i];
continue;
}
if( r==0 || (r<1000 && (prngInt(p)%1000)<=r) ){
/* Fill in without values without any new % */
k = prngInt(p)%(count(azJsonAtoms)/2);
k = k*2 + eType;
z = azJsonAtoms[k];
}else{
/* Add new % terms */
k = prngInt(p)%(count(azJsonTemplate)/2);
k = k*2 + eType;
z = azJsonTemplate[k];
}
n = strlen(z);
if( j+n<STRSZ ){
memcpy(&zDest[j], z, n);
j += n;
}
}
zDest[STRSZ-1] = 0;
if( j<STRSZ ) zDest[j] = 0;
}
static void randJsonFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
unsigned int iSeed;
int eType = *(int*)sqlite3_user_data(context);
Prng prng;
char z1[STRSZ+1], z2[STRSZ+1];
iSeed = (unsigned int)sqlite3_value_int(argv[0]);
prngSeed(&prng, iSeed);
jsonExpand(0, z2, &prng, eType, 1000);
jsonExpand(z2, z1, &prng, eType, 1000);
jsonExpand(z1, z2, &prng, eType, 100);
jsonExpand(z2, z1, &prng, eType, 0);
sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_randomjson_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
static int cOne = 1;
static int cZero = 0;
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "random_json", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
&cZero, randJsonFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "random_json5", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
&cOne, randJsonFunc, 0, 0);
}
return rc;
}
+47 -138
View File
@@ -1,5 +1,5 @@
/*
** 2015-08-18, 2023-04-28
** 2015-08-18
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -12,19 +12,7 @@
**
** This file demonstrates how to create a table-valued-function using
** a virtual table. This demo implements the generate_series() function
** which gives the same results as the eponymous function in PostgreSQL,
** within the limitation that its arguments are signed 64-bit integers.
**
** Considering its equivalents to generate_series(start,stop,step): A
** value V[n] sequence is produced for integer n ascending from 0 where
** ( V[n] == start + n * step && sgn(V[n] - stop) * sgn(step) >= 0 )
** for each produced value (independent of production time ordering.)
**
** All parameters must be either integer or convertable to integer.
** The start parameter is required.
** The stop parameter defaults to (1<<32)-1 (aka 4294967295 or 0xffffffff)
** The step parameter defaults to 1 and 0 is treated as 1.
**
** which gives similar results to the eponymous function in PostgreSQL.
** Examples:
**
** SELECT * FROM generate_series(0,100,5);
@@ -40,14 +28,6 @@
**
** Integers 20 through 29.
**
** SELECT * FROM generate_series(0,-100,-5);
**
** Integers 0 -5 -10 ... -100.
**
** SELECT * FROM generate_series(0,-1);
**
** Empty sequence.
**
** HOW IT WORKS
**
** The generate_series "function" is really a virtual table with the
@@ -60,9 +40,6 @@
** step HIDDEN
** );
**
** The virtual table also has a rowid, logically equivalent to n+1 where
** "n" is the ascending integer in the aforesaid production definition.
**
** Function arguments in queries against this virtual table are translated
** into equality constraints against successive hidden columns. In other
** words, the following pairs of queries are equivalent to each other:
@@ -95,96 +72,9 @@
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <limits.h>
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return that member of a generate_series(...) sequence whose 0-based
** index is ix. The 0th member is given by smBase. The sequence members
** progress per ix increment by smStep.
*/
static sqlite3_int64 genSeqMember(sqlite3_int64 smBase,
sqlite3_int64 smStep,
sqlite3_uint64 ix){
if( ix>=(sqlite3_uint64)LLONG_MAX ){
/* Get ix into signed i64 range. */
ix -= (sqlite3_uint64)LLONG_MAX;
smBase += LLONG_MAX * smStep;
}
return smBase + ((sqlite3_int64)ix)*smStep;
}
typedef unsigned char u8;
typedef struct SequenceSpec {
sqlite3_int64 iBase; /* Starting value ("start") */
sqlite3_int64 iTerm; /* Given terminal value ("stop") */
sqlite3_int64 iStep; /* Increment ("step") */
sqlite3_uint64 uSeqIndexMax; /* maximum sequence index (aka "n") */
sqlite3_uint64 uSeqIndexNow; /* Current index during generation */
sqlite3_int64 iValueNow; /* Current value during generation */
u8 isNotEOF; /* Sequence generation not exhausted */
u8 isReversing; /* Sequence is being reverse generated */
} SequenceSpec;
/*
** Prepare a SequenceSpec for use in generating an integer series
** given initialized iBase, iTerm and iStep values. Sequence is
** initialized per given isReversing. Other members are computed.
*/
void setupSequence( SequenceSpec *pss ){
pss->uSeqIndexMax = 0;
pss->isNotEOF = 0;
if( pss->iTerm < pss->iBase ){
sqlite3_uint64 nuspan = (sqlite3_uint64)(pss->iBase-pss->iTerm);
if( pss->iStep<0 ){
pss->isNotEOF = 1;
if( nuspan==ULONG_MAX ){
pss->uSeqIndexMax = ( pss->iStep>LLONG_MIN )? nuspan/-pss->iStep : 1;
}else if( pss->iStep>LLONG_MIN ){
pss->uSeqIndexMax = nuspan/-pss->iStep;
}
}
}else if( pss->iTerm > pss->iBase ){
sqlite3_uint64 puspan = (sqlite3_uint64)(pss->iTerm-pss->iBase);
if( pss->iStep>0 ){
pss->isNotEOF = 1;
pss->uSeqIndexMax = puspan/pss->iStep;
}
}else if( pss->iTerm == pss->iBase ){
pss->isNotEOF = 1;
pss->uSeqIndexMax = 0;
}
pss->uSeqIndexNow = (pss->isReversing)? pss->uSeqIndexMax : 0;
pss->iValueNow = (pss->isReversing)
? genSeqMember(pss->iBase, pss->iStep, pss->uSeqIndexMax)
: pss->iBase;
}
/*
** Progress sequence generator to yield next value, if any.
** Leave its state to either yield next value or be at EOF.
** Return whether there is a next value, or 0 at EOF.
*/
int progressSequence( SequenceSpec *pss ){
if( !pss->isNotEOF ) return 0;
if( pss->isReversing ){
if( pss->uSeqIndexNow > 0 ){
pss->uSeqIndexNow--;
pss->iValueNow -= pss->iStep;
}else{
pss->isNotEOF = 0;
}
}else{
if( pss->uSeqIndexNow < pss->uSeqIndexMax ){
pss->uSeqIndexNow++;
pss->iValueNow += pss->iStep;
}else{
pss->isNotEOF = 0;
}
}
return pss->isNotEOF;
}
/* series_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
@@ -193,7 +83,12 @@ int progressSequence( SequenceSpec *pss ){
typedef struct series_cursor series_cursor;
struct series_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
SequenceSpec ss; /* (this) Derived class data */
int isDesc; /* True to count down rather than up */
sqlite3_int64 iRowid; /* The rowid */
sqlite3_int64 iValue; /* Current value ("value") */
sqlite3_int64 mnValue; /* Mimimum value ("start") */
sqlite3_int64 mxValue; /* Maximum value ("stop") */
sqlite3_int64 iStep; /* Increment ("step") */
};
/*
@@ -275,7 +170,12 @@ static int seriesClose(sqlite3_vtab_cursor *cur){
*/
static int seriesNext(sqlite3_vtab_cursor *cur){
series_cursor *pCur = (series_cursor*)cur;
progressSequence( & pCur->ss );
if( pCur->isDesc ){
pCur->iValue -= pCur->iStep;
}else{
pCur->iValue += pCur->iStep;
}
pCur->iRowid++;
return SQLITE_OK;
}
@@ -291,10 +191,10 @@ static int seriesColumn(
series_cursor *pCur = (series_cursor*)cur;
sqlite3_int64 x = 0;
switch( i ){
case SERIES_COLUMN_START: x = pCur->ss.iBase; break;
case SERIES_COLUMN_STOP: x = pCur->ss.iTerm; break;
case SERIES_COLUMN_STEP: x = pCur->ss.iStep; break;
default: x = pCur->ss.iValueNow; break;
case SERIES_COLUMN_START: x = pCur->mnValue; break;
case SERIES_COLUMN_STOP: x = pCur->mxValue; break;
case SERIES_COLUMN_STEP: x = pCur->iStep; break;
default: x = pCur->iValue; break;
}
sqlite3_result_int64(ctx, x);
return SQLITE_OK;
@@ -307,7 +207,7 @@ static int seriesColumn(
*/
static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
series_cursor *pCur = (series_cursor*)cur;
*pRowid = ((sqlite3_int64)pCur->ss.uSeqIndexNow + 1);
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
@@ -317,10 +217,14 @@ static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
*/
static int seriesEof(sqlite3_vtab_cursor *cur){
series_cursor *pCur = (series_cursor*)cur;
return !pCur->ss.isNotEOF;
if( pCur->isDesc ){
return pCur->iValue < pCur->mnValue;
}else{
return pCur->iValue > pCur->mxValue;
}
}
/* True to cause run-time checking of the start=, stop=, and/or step=
/* True to cause run-time checking of the start=, stop=, and/or step=
** parameters. The only reason to do this is for testing the
** constraint checking logic for virtual tables in the SQLite core.
*/
@@ -331,7 +235,7 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
/*
** This method is called to "rewind" the series_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to seriesColumn() or seriesRowid() or
** once prior to any call to seriesColumn() or seriesRowid() or
** seriesEof().
**
** The query plan selected by seriesBestIndex is passed in the idxNum
@@ -351,7 +255,7 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
** (so that seriesEof() will return true) if the table is empty.
*/
static int seriesFilter(
sqlite3_vtab_cursor *pVtabCursor,
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStrUnused,
int argc, sqlite3_value **argv
){
@@ -359,41 +263,46 @@ static int seriesFilter(
int i = 0;
(void)idxStrUnused;
if( idxNum & 1 ){
pCur->ss.iBase = sqlite3_value_int64(argv[i++]);
pCur->mnValue = sqlite3_value_int64(argv[i++]);
}else{
pCur->ss.iBase = 0;
pCur->mnValue = 0;
}
if( idxNum & 2 ){
pCur->ss.iTerm = sqlite3_value_int64(argv[i++]);
pCur->mxValue = sqlite3_value_int64(argv[i++]);
}else{
pCur->ss.iTerm = 0xffffffff;
pCur->mxValue = 0xffffffff;
}
if( idxNum & 4 ){
pCur->ss.iStep = sqlite3_value_int64(argv[i++]);
if( pCur->ss.iStep==0 ){
pCur->ss.iStep = 1;
}else if( pCur->ss.iStep<0 ){
pCur->iStep = sqlite3_value_int64(argv[i++]);
if( pCur->iStep==0 ){
pCur->iStep = 1;
}else if( pCur->iStep<0 ){
pCur->iStep = -pCur->iStep;
if( (idxNum & 16)==0 ) idxNum |= 8;
}
}else{
pCur->ss.iStep = 1;
pCur->iStep = 1;
}
for(i=0; i<argc; i++){
if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
/* If any of the constraints have a NULL value, then return no rows.
** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
pCur->ss.iBase = 1;
pCur->ss.iTerm = 0;
pCur->ss.iStep = 1;
pCur->mnValue = 1;
pCur->mxValue = 0;
break;
}
}
if( idxNum & 8 ){
pCur->ss.isReversing = pCur->ss.iStep > 0;
pCur->isDesc = 1;
pCur->iValue = pCur->mxValue;
if( pCur->iStep>0 ){
pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
}
}else{
pCur->ss.isReversing = pCur->ss.iStep < 0;
pCur->isDesc = 0;
pCur->iValue = pCur->mnValue;
}
setupSequence( &pCur->ss );
pCur->iRowid = 1;
return SQLITE_OK;
}
+5 -5
View File
@@ -1772,14 +1772,14 @@ static sqlite3_module geopolyModule = {
rtreeRowid, /* xRowid - read data */
geopolyUpdate, /* xUpdate - write data */
rtreeBeginTransaction, /* xBegin - begin transaction */
rtreeEndTransaction, /* xSync - sync transaction */
rtreeEndTransaction, /* xCommit - commit transaction */
rtreeEndTransaction, /* xRollback - rollback transaction */
rtreeCommit, /* xSync - sync transaction */
rtreeCommit, /* xCommit - commit transaction */
rtreeRollback, /* xRollback - rollback transaction */
geopolyFindFunction, /* xFindFunction - function overloading */
rtreeRename, /* xRename - rename the table */
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
rtreeCacheWrite, /* xRelease */
rtreeCacheAbandon, /* xRollbackTo */
rtreeShadowName /* xShadowName */
};
+278 -43
View File
@@ -116,6 +116,7 @@ typedef struct RtreeMatchArg RtreeMatchArg;
typedef struct RtreeGeomCallback RtreeGeomCallback;
typedef union RtreeCoord RtreeCoord;
typedef struct RtreeSearchPoint RtreeSearchPoint;
typedef struct RtreeGlobal RtreeGlobal;
/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
#define RTREE_MAX_DIMENSIONS 5
@@ -123,11 +124,8 @@ typedef struct RtreeSearchPoint RtreeSearchPoint;
/* Maximum number of auxiliary columns */
#define RTREE_MAX_AUX_COLUMN 100
/* Size of hash table Rtree.aHash. This hash table is not expected to
** ever contain very many entries, so a fixed number of buckets is
** used.
*/
#define HASHSIZE 97
/* Initial size of hash table Rtree.aHash. */
#define INITIAL_HASHSIZE 97
/* The xBestIndex method of this virtual table requires an estimate of
** the number of rows in the virtual table to calculate the costs of
@@ -139,6 +137,16 @@ typedef struct RtreeSearchPoint RtreeSearchPoint;
#define RTREE_DEFAULT_ROWEST 1048576
#define RTREE_MIN_ROWEST 100
/*
** There is one instance of this structure for each database handle (sqlite3*)
** that the rtree extension is registered with. It is used to allow the
** rtreecheck() function to locate the Rtree structure it is operating on.
*/
struct RtreeGlobal {
Rtree *pGlobalRtree; /* List of all Rtree structures for this db */
int nGlobalRef; /* Number of pointers to this structure */
};
/*
** An rtree virtual-table object.
*/
@@ -195,7 +203,12 @@ struct Rtree {
/* Statement for writing to the "aux:" fields, if there are any */
sqlite3_stmt *pWriteAux;
RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
int nHashSize; /* Number of hash buckets */
int nHashEntry; /* Number of entries in hash table */
RtreeNode **aHash; /* Hash table of in-memory nodes. */
RtreeGlobal *pGlobal; /* Database-wide object */
Rtree *pGlobalNext; /* Next in RtreeGlobal.pGlobalNext */
};
/* Possible values for Rtree.eCoordType: */
@@ -221,7 +234,10 @@ struct Rtree {
** Set the Rtree.bCorrupt flag
*/
#ifdef SQLITE_DEBUG
# define RTREE_IS_CORRUPT(X) ((X)->bCorrupt = 1)
static void rtreeIsCorrupt(Rtree *pRtree){
pRtree->bCorrupt = 1;
}
# define RTREE_IS_CORRUPT(X) rtreeIsCorrupt(X)
#else
# define RTREE_IS_CORRUPT(X)
#endif
@@ -355,12 +371,17 @@ struct RtreeConstraint {
/*
** An rtree structure node.
**
** bDel:
** This node is not in the hash table. It should be freed when its
** ref-count reaches 0.
*/
struct RtreeNode {
RtreeNode *pParent; /* Parent node */
i64 iNode; /* The node number */
int nRef; /* Number of references to this node */
int isDirty; /* True if the node needs to be written to disk */
u8 bDel;
u8 isDirty; /* True if the node needs to be written to disk */
u8 *zData; /* Content of the node, as should be on disk */
RtreeNode *pNext; /* Next node in this hash collision chain */
};
@@ -621,8 +642,8 @@ static void nodeZero(Rtree *pRtree, RtreeNode *p){
** Given a node number iNode, return the corresponding key to use
** in the Rtree.aHash table.
*/
static unsigned int nodeHash(i64 iNode){
return ((unsigned)iNode) % HASHSIZE;
static unsigned int nodeHash(Rtree *pRtree, i64 iNode){
return ((unsigned)iNode) % pRtree->nHashSize;
}
/*
@@ -631,7 +652,7 @@ static unsigned int nodeHash(i64 iNode){
*/
static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){
RtreeNode *p;
for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext);
for(p=pRtree->aHash[nodeHash(pRtree, iNode)]; p&&p->iNode!=iNode; p=p->pNext);
return p;
}
@@ -641,9 +662,35 @@ static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){
static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){
int iHash;
assert( pNode->pNext==0 );
iHash = nodeHash(pNode->iNode);
assert( pNode->pParent==0 || pNode->nRef>0 );
assert( pNode->bDel==0 );
if( pRtree->nHashEntry>pRtree->nHashSize ){
int nNew = pRtree->nHashSize * 2;
RtreeNode **aNew = (RtreeNode**)sqlite3_malloc64(sizeof(RtreeNode*)*nNew);
if( aNew ){
int ii;
memset(aNew, 0, sizeof(RtreeNode*)*nNew);
for(ii=0; ii<pRtree->nHashSize; ii++){
RtreeNode *p, *pNext;
for(p=pRtree->aHash[ii]; p; p=pNext){
int iBucket = p->iNode % nNew;
pNext = p->pNext;
p->pNext = aNew[iBucket];
aNew[iBucket] = p;
}
}
sqlite3_free(pRtree->aHash);
pRtree->aHash = aNew;
pRtree->nHashSize = nNew;
}
}
iHash = nodeHash(pRtree, pNode->iNode);
pNode->pNext = pRtree->aHash[iHash];
pRtree->aHash[iHash] = pNode;
pRtree->nHashEntry++;
}
/*
@@ -652,10 +699,11 @@ static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){
static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){
RtreeNode **pp;
if( pNode->iNode!=0 ){
pp = &pRtree->aHash[nodeHash(pNode->iNode)];
pp = &pRtree->aHash[nodeHash(pRtree, pNode->iNode)];
for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); }
*pp = pNode->pNext;
pNode->pNext = 0;
pRtree->nHashEntry--;
}
}
@@ -675,6 +723,7 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
pRtree->nNodeRef++;
pNode->pParent = pParent;
pNode->isDirty = 1;
pNode->bDel = 1;
nodeReference(pParent);
}
return pNode;
@@ -707,12 +756,20 @@ static int nodeAcquire(
** increase its reference count and return it.
*/
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
if( pParent && pParent!=pNode->pParent ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
assert( pNode->pParent==0 || pNode->nRef>0 );
if( pNode->nRef==0 ){
pNode->pParent = pParent;
nodeReference(pParent);
}else{
if( pParent && pParent!=pNode->pParent ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
}
if( pNode->nRef==0 ) pRtree->nNodeRef++;
pNode->nRef++;
*ppNode = pNode;
if( iNode==1 ) pRtree->iDepth = readInt16(pNode->zData);
return SQLITE_OK;
}
@@ -747,13 +804,13 @@ static int nodeAcquire(
if( !pNode ){
rc = SQLITE_NOMEM;
}else{
pNode->pParent = pParent;
pNode->zData = (u8 *)&pNode[1];
pNode->nRef = 1;
pRtree->nNodeRef++;
pNode->iNode = iNode;
pNode->isDirty = 0;
pNode->pNext = 0;
pNode->bDel = 0;
rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
pRtree->iNodeSize, 0);
}
@@ -786,6 +843,7 @@ static int nodeAcquire(
if( rc==SQLITE_OK ){
if( pNode!=0 ){
pNode->pParent = pParent;
nodeReference(pParent);
nodeHashInsert(pRtree, pNode);
}else{
@@ -879,6 +937,7 @@ static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){
rc = sqlite3_reset(p);
sqlite3_bind_null(p, 2);
if( pNode->iNode==0 && rc==SQLITE_OK ){
pNode->bDel = 0;
pNode->iNode = sqlite3_last_insert_rowid(pRtree->db);
nodeHashInsert(pRtree, pNode);
}
@@ -886,6 +945,58 @@ static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){
return rc;
}
/*
** Write all dirty nodes out to disk.
*/
static int rtreeFlushCache(Rtree *pRtree){
int i;
int rc = SQLITE_OK;
i64 iLIR = sqlite3_last_insert_rowid(pRtree->db);
for(i=0; i<pRtree->nHashSize && rc==SQLITE_OK; i++){
RtreeNode *pNode;
for(pNode=pRtree->aHash[i]; pNode; pNode=pNode->pNext){
if( pNode->isDirty ){
rc = nodeWrite(pRtree, pNode);
if( rc ) break;
}
}
}
sqlite3_set_last_insert_rowid(pRtree->db, iLIR);
return rc;
}
/*
** Scan the hash table. Verify that every hash table entry has nRef==0
** and remove them. Any dirty pages are written if writeDirty is true.
*/
static int rtreeResetHashTable(Rtree *pRtree, int writeDirty){
int i;
int rc = SQLITE_OK;
for(i=0; i<pRtree->nHashSize; i++){
RtreeNode *pNode = pRtree->aHash[i];
RtreeNode *pNext;
if( pNode==0 ) continue;
while( 1 /*exit-by-break*/ ){
pNext = pNode->pNext;
if( pNode->isDirty && writeDirty ){
rc = nodeWrite(pRtree, pNode);
if( rc ) writeDirty = 0;
}
if( pNode->nRef==0 ){
sqlite3_free(pNode);
}else{
pNode->isDirty = 0;
pNode->bDel = 1;
}
if( pNext==0 ) break;
pNode = pNext;
}
pRtree->aHash[i] = 0;
}
pRtree->nHashEntry = 0;
return rc;
}
/*
** Release a reference to a node. If the node is dirty and the reference
** count drops to zero, the node data is written to the database.
@@ -903,12 +1014,18 @@ static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){
}
if( pNode->pParent ){
rc = nodeRelease(pRtree, pNode->pParent);
pNode->pParent = 0;
}
if( pNode->bDel ){
sqlite3_free(pNode);
}
#if 0
if( rc==SQLITE_OK ){
rc = nodeWrite(pRtree, pNode);
}
nodeHashDelete(pRtree, pNode);
sqlite3_free(pNode);
#endif
}
}
return rc;
@@ -1016,6 +1133,7 @@ static void rtreeRelease(Rtree *pRtree){
pRtree->inWrTrans = 0;
assert( pRtree->nCursor==0 );
nodeBlobReset(pRtree);
rtreeResetHashTable(pRtree, 0);
assert( pRtree->nNodeRef==0 || pRtree->bCorrupt );
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
@@ -1027,6 +1145,15 @@ static void rtreeRelease(Rtree *pRtree){
sqlite3_finalize(pRtree->pDeleteParent);
sqlite3_finalize(pRtree->pWriteAux);
sqlite3_free(pRtree->zReadAuxSql);
sqlite3_free(pRtree->aHash);
/* Remove this object from the global list. */
if( pRtree->pGlobal ){
Rtree **pp;
for(pp=&pRtree->pGlobal->pGlobalRtree;*pp!=pRtree;pp=&(*pp)->pGlobalNext);
*pp = pRtree->pGlobalNext;
}
sqlite3_free(pRtree);
}
}
@@ -1128,6 +1255,11 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
sqlite3_free(pCsr);
pRtree->nCursor--;
nodeBlobReset(pRtree);
if( pRtree->inWrTrans==0 && pRtree->nCursor==0 ){
/* If this was the last open cursor, and there is no write-transaction,
** discard the contents of the node-cache. */
rtreeResetHashTable(pRtree, 0);
}
return SQLITE_OK;
}
@@ -2567,7 +2699,7 @@ static int updateMapping(
for(p=pNode; p; p=p->pParent){
if( p==pChild ) return SQLITE_CORRUPT_VTAB;
}
if( pChild ){
if( pChild && pChild->nRef>0 ){
nodeRelease(pRtree, pChild->pParent);
nodeReference(pNode);
pChild->pParent = pNode;
@@ -2982,7 +3114,7 @@ static int rtreeInsertCell(
int rc = SQLITE_OK;
if( iHeight>0 ){
RtreeNode *pChild = nodeHashLookup(pRtree, pCell->iRowid);
if( pChild ){
if( pChild && pChild->nRef>0 ){
nodeRelease(pRtree, pChild->pParent);
nodeReference(pNode);
pChild->pParent = pNode;
@@ -3226,6 +3358,11 @@ static int rtreeUpdate(
int rc = SQLITE_OK;
RtreeCell cell; /* New cell to insert if nData>1 */
int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
i64 iLIR = sqlite3_last_insert_rowid(pRtree->db);
#ifdef SQLITE_DEBUG
int nNodeRefSave = pRtree->nNodeRef;
#endif
if( pRtree->nNodeRef ){
/* Unable to write to the btree while another cursor is reading from it,
@@ -3357,6 +3494,8 @@ static int rtreeUpdate(
}
constraint:
sqlite3_set_last_insert_rowid(pRtree->db, iLIR);
assert( pRtree->nNodeRef==nNodeRefSave );
rtreeRelease(pRtree);
return rc;
}
@@ -3375,10 +3514,35 @@ static int rtreeBeginTransaction(sqlite3_vtab *pVtab){
** Called when a transaction completes (either by COMMIT or ROLLBACK).
** The sqlite3_blob object should be released at this point.
*/
static int rtreeEndTransaction(sqlite3_vtab *pVtab){
static int rtreeCommit(sqlite3_vtab *pVtab){
int rc = SQLITE_OK;
Rtree *pRtree = (Rtree *)pVtab;
i64 iLIR = sqlite3_last_insert_rowid(pRtree->db);
pRtree->inWrTrans = 0;
nodeBlobReset(pRtree);
rc = rtreeResetHashTable(pRtree, 1);
sqlite3_set_last_insert_rowid(pRtree->db, iLIR);
return rc;
}
static int rtreeRollback(sqlite3_vtab *pVtab){
Rtree *pRtree = (Rtree *)pVtab;
pRtree->inWrTrans = 0;
nodeBlobReset(pRtree);
rtreeResetHashTable(pRtree, 0);
return SQLITE_OK;
}
/*
** Called at the end of a statement to ensure that the cache
** has been cleared and that all changes have been written.
*/
static int rtreeCacheWrite(sqlite3_vtab *pVtab, int n){
UNUSED_PARAMETER(n);
return rtreeFlushCache((Rtree*)pVtab);
}
static int rtreeCacheAbandon(sqlite3_vtab *pVtab, int n){
UNUSED_PARAMETER(n);
rtreeResetHashTable((Rtree*)pVtab, 0);
return SQLITE_OK;
}
@@ -3421,11 +3585,13 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){
Rtree *pRtree = (Rtree *)pVtab;
u8 iwt = pRtree->inWrTrans;
int rc = SQLITE_OK;
UNUSED_PARAMETER(iSavepoint);
rc = rtreeFlushCache(pRtree);
pRtree->inWrTrans = 0;
nodeBlobReset(pRtree);
pRtree->inWrTrans = iwt;
return SQLITE_OK;
return rc;
}
/*
@@ -3494,14 +3660,14 @@ static sqlite3_module rtreeModule = {
rtreeRowid, /* xRowid - read data */
rtreeUpdate, /* xUpdate - write data */
rtreeBeginTransaction, /* xBegin - begin transaction */
rtreeEndTransaction, /* xSync - sync transaction */
rtreeEndTransaction, /* xCommit - commit transaction */
rtreeEndTransaction, /* xRollback - rollback transaction */
rtreeCommit, /* xSync - sync transaction */
rtreeCommit, /* xCommit - commit transaction */
rtreeRollback, /* xRollback - rollback transaction */
0, /* xFindFunction - function overloading */
rtreeRename, /* xRename - rename the table */
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
rtreeCacheWrite, /* xRelease */
rtreeCacheAbandon, /* xRollbackTo */
rtreeShadowName /* xShadowName */
};
@@ -3733,11 +3899,12 @@ static int rtreeInit(
char **pzErr, /* OUT: Error message, if any */
int isCreate /* True for xCreate, false for xConnect */
){
RtreeGlobal *pGlobal = (RtreeGlobal*)pAux;
int rc = SQLITE_OK;
Rtree *pRtree;
int nDb; /* Length of string argv[1] */
int nName; /* Length of string argv[2] */
int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32);
int eCoordType = 0;
sqlite3_str *pSql;
char *zSql;
int ii = 4;
@@ -3751,6 +3918,13 @@ static int rtreeInit(
"Auxiliary rtree columns must be last" /* 4 */
};
eCoordType = RTREE_COORD_INT32;
#ifndef SQLITE_RTREE_INT_ONLY
if( sqlite3_stricmp("rtree", argv[0])==0 ){
eCoordType = RTREE_COORD_REAL32;
}
#endif
assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
@@ -3775,6 +3949,15 @@ static int rtreeInit(
memcpy(pRtree->zDb, argv[1], nDb);
memcpy(pRtree->zName, argv[2], nName);
pRtree->aHash = (RtreeNode**)sqlite3_malloc64(
sizeof(RtreeNode*) * INITIAL_HASHSIZE
);
if( pRtree->aHash==0 ){
rc = SQLITE_NOMEM;
goto rtreeInit_fail;
}
memset(pRtree->aHash, 0, sizeof(RtreeNode*)*INITIAL_HASHSIZE);
pRtree->nHashSize = INITIAL_HASHSIZE;
/* Create/Connect to the underlying relational database schema. If
** that is successful, call sqlite3_declare_vtab() to configure
@@ -3834,6 +4017,11 @@ static int rtreeInit(
goto rtreeInit_fail;
}
/* Link this rtree into the global list */
pRtree->pGlobal = pGlobal;
pRtree->pGlobalNext = pGlobal->pGlobalRtree;
pGlobal->pGlobalRtree = pRtree;
*ppVtab = (sqlite3_vtab *)pRtree;
return SQLITE_OK;
@@ -3940,6 +4128,7 @@ struct RtreeCheck {
sqlite3 *db; /* Database handle */
const char *zDb; /* Database containing rtree table */
const char *zTab; /* Name of rtree table */
Rtree *pRtree; /* Rtree object (may be NULL) */
int bInt; /* True for rtree_i32 table */
int nDim; /* Number of dimensions for this rtree tbl */
sqlite3_stmt *pGetNode; /* Statement used to retrieve nodes */
@@ -4035,6 +4224,21 @@ static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
*/
static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
u8 *pRet = 0; /* Return value */
if( pCheck->pRtree ){
RtreeNode *pNode = nodeHashLookup(pCheck->pRtree, iNode);
if( pNode ){
int nNode = pCheck->pRtree->iNodeSize;
pRet = (u8*)sqlite3_malloc64(nNode);
if( pRet==0 ){
pCheck->rc = SQLITE_NOMEM;
}else{
memcpy(pRet, pNode->zData, nNode);
*pnNode = nNode;
}
return pRet;
}
}
if( pCheck->rc==SQLITE_OK && pCheck->pGetNode==0 ){
pCheck->pGetNode = rtreeCheckPrepare(pCheck,
@@ -4264,6 +4468,7 @@ static void rtreeCheckCount(RtreeCheck *pCheck, const char *zTbl, i64 nExpect){
*/
static int rtreeCheckTable(
sqlite3 *db, /* Database handle to access db through */
RtreeGlobal *pGlobal,
const char *zDb, /* Name of db ("main", "temp" etc.) */
const char *zTab, /* Name of rtree table to check */
char **pzReport /* OUT: sqlite3_malloc'd report text */
@@ -4272,12 +4477,19 @@ static int rtreeCheckTable(
sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */
int bEnd = 0; /* True if transaction should be closed */
int nAux = 0; /* Number of extra columns. */
Rtree *pRtree = 0;
/* Initialize the context object */
memset(&check, 0, sizeof(check));
check.db = db;
check.zDb = zDb;
check.zTab = zTab;
for(pRtree=pGlobal->pGlobalRtree; pRtree; pRtree=pRtree->pGlobalNext){
if( sqlite3_stricmp(zDb, pRtree->zDb) ) continue;
if( sqlite3_stricmp(zTab, pRtree->zName) ) continue;
break;
}
check.pRtree = pRtree;
/* If there is not already an open transaction, open one now. This is
** to ensure that the queries run as part of this integrity-check operate
@@ -4379,6 +4591,8 @@ static void rtreecheck(
"wrong number of arguments to function rtreecheck()", -1
);
}else{
sqlite3 *db = sqlite3_context_db_handle(ctx);
RtreeGlobal *pGlobal = (RtreeGlobal*)sqlite3_user_data(ctx);
int rc;
char *zReport = 0;
const char *zDb = (const char*)sqlite3_value_text(apArg[0]);
@@ -4389,7 +4603,7 @@ static void rtreecheck(
}else{
zTab = (const char*)sqlite3_value_text(apArg[1]);
}
rc = rtreeCheckTable(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport);
rc = rtreeCheckTable(db, pGlobal, zDb, zTab, &zReport);
if( rc==SQLITE_OK ){
sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT);
}else{
@@ -4404,33 +4618,47 @@ static void rtreecheck(
# include "geopoly.c"
#endif
/*
** The argument passed to this function is an RtreeGlobal structure.
** Decrement its reference count. Free the structure if it reaches 0.
*/
static void rtreeDestroyGlobal(void *p){
RtreeGlobal *pGlobal = (RtreeGlobal*)p;
assert( pGlobal->nGlobalRef>0 );
if( 0==(--pGlobal->nGlobalRef) ){
sqlite3_free(pGlobal);
}
}
/*
** Register the r-tree module with database handle db. This creates the
** virtual table module "rtree" and the debugging/analysis scalar
** function "rtreenode".
*/
int sqlite3RtreeInit(sqlite3 *db){
RtreeGlobal *pGlobal = 0;
const int utf8 = SQLITE_UTF8;
int rc;
rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0);
pGlobal = (RtreeGlobal*)sqlite3_malloc(sizeof(*pGlobal));
if( pGlobal==0 ) return SQLITE_NOMEM;
memset(pGlobal, 0, sizeof(*pGlobal));
pGlobal->nGlobalRef++;
rc = sqlite3_create_function_v2(db, "rtreecheck",
-1, utf8, pGlobal, rtreecheck, 0, 0, rtreeDestroyGlobal
);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0);
pGlobal->nGlobalRef++;
rc = sqlite3_create_module_v2(db, "rtree",
&rtreeModule, pGlobal, rtreeDestroyGlobal
);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "rtreecheck", -1, utf8, 0,rtreecheck, 0,0);
}
if( rc==SQLITE_OK ){
#ifdef SQLITE_RTREE_INT_ONLY
void *c = (void *)RTREE_COORD_INT32;
#else
void *c = (void *)RTREE_COORD_REAL32;
#endif
rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0);
}
if( rc==SQLITE_OK ){
void *c = (void *)RTREE_COORD_INT32;
rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0);
pGlobal->nGlobalRef++;
rc = sqlite3_create_module_v2(db, "rtree_i32",
&rtreeModule, pGlobal, rtreeDestroyGlobal
);
}
#ifdef SQLITE_ENABLE_GEOPOLY
if( rc==SQLITE_OK ){
@@ -4438,6 +4666,13 @@ int sqlite3RtreeInit(sqlite3 *db){
}
#endif
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0);
}
return rc;
}
+7
View File
@@ -756,4 +756,11 @@ do_execsql_test 20.4 {
SELECT * FROM t1 JOIN t0 ON true RIGHT JOIN rt0 ON x0>a WHERE x0 = 0;
} {- - 0 0.0 0.0}
reset_db
do_execsql_test 21.0 {
CREATE VIRTUAL TABLE rt0 USING rtree(id, x0, x1);
INSERT INTO rt0 VALUES(5, 10, 10);
SELECT last_insert_rowid();
} {5}
finish_test
+24
View File
@@ -41,6 +41,30 @@ proc scksum {db dbname} {
return [md5 $txt]
}
proc do_diff_test {tn setup} {
reset_db
forcedelete test.db2
execsql { ATTACH 'test.db2' AS aux }
execsql $setup
sqlite3session S db main
foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
S attach $tbl
S diff aux $tbl
}
set C [S changeset]
S delete
sqlite3 db2 test.db2
sqlite3changeset_apply db2 $C ""
uplevel do_test $tn.1 [list {execsql { PRAGMA integrity_check } db2}] ok
db2 close
set cksum [scksum db main]
uplevel do_test $tn.2 [list {scksum db aux}] [list $cksum]
}
# Ensure that the diff produced by comparing the current contents of [db]
# with itself is empty.
proc do_empty_diff_test {tn} {
-52
View File
@@ -52,7 +52,6 @@ proc do_conflict_test {tn args} {
proc bgerror {args} { set ::background_error $args }
sqlite3session S db main
S object_config rowid 1
foreach t $O(-tables) { S attach $t }
execsql $O(-sql)
@@ -82,7 +81,6 @@ proc changeset_from_sql {sql {dbname main}} {
}
set rc [catch {
sqlite3session S db $dbname
S object_config rowid 1
db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
S attach $name
}
@@ -140,7 +138,6 @@ proc do_then_apply_sql {args} {
proc xConflict args { incr ::n_conflict ; return "OMIT" }
set rc [catch {
sqlite3session S db $dbname
S object_config rowid 1
db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
S attach $name
}
@@ -165,8 +162,6 @@ proc do_then_apply_sql {args} {
proc do_iterator_test {tn tbl_list sql res} {
sqlite3session S db main
S object_config rowid 1
if {[llength $tbl_list]==0} { S attach * }
foreach t $tbl_list {S attach $t}
@@ -176,7 +171,6 @@ proc do_iterator_test {tn tbl_list sql res} {
foreach v $res { lappend r $v }
set x [list]
# set ::c [S changeset] ; execsql_pp { SELECT quote($::c) }
sqlite3session_foreach c [S changeset] { lappend x $c }
uplevel do_test $tn [list [list set {} $x]] [list $r]
@@ -251,49 +245,3 @@ proc number_name {n} {
if {$txt==""} {set txt zero}
return $txt
}
proc scksum {db dbname} {
if {$dbname=="temp"} {
set master sqlite_temp_master
} else {
set master $dbname.sqlite_master
}
set alltab [$db eval "SELECT name FROM $master WHERE type='table'"]
set txt [$db eval "SELECT * FROM $master ORDER BY type,name,sql"]
foreach tab $alltab {
set cols [list]
db eval "PRAGMA $dbname.table_info = $tab" x {
lappend cols "quote($x(name))"
}
set cols [join $cols ,]
append txt [db eval "SELECT $cols FROM $dbname.$tab ORDER BY $cols"]
}
return [md5 $txt]
}
proc do_diff_test {tn setup} {
reset_db
forcedelete test.db2
execsql { ATTACH 'test.db2' AS aux }
execsql $setup
sqlite3session S db main
S object_config rowid 1
foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
S attach $tbl
S diff aux $tbl
}
set C [S changeset]
S delete
sqlite3 db2 test.db2
sqlite3changeset_apply db2 $C ""
uplevel do_test $tn.1 [list {execsql { PRAGMA integrity_check } db2}] ok
db2 close
set cksum [scksum db main]
uplevel do_test $tn.2 [list {scksum db aux}] [list $cksum]
}
-76
View File
@@ -84,7 +84,6 @@ proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} {
db eval BEGIN
sqlite3session S1 db main
S1 object_config rowid 1
S1 attach *
execsql $sql1 db
set c1 [S1 changeset]
@@ -92,7 +91,6 @@ proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} {
if {$i==1} {
sqlite3session S2 db2 main
S2 object_config rowid 1
S2 attach *
execsql $sql2 db2
set c2 [S2 changeset]
@@ -102,7 +100,6 @@ proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} {
foreach sql [split $sql2 ";"] {
if {[string is space $sql]} continue
sqlite3session S2 db2 main
S2 object_config rowid 1
S2 attach *
execsql $sql db2
lappend c2 [S2 changeset]
@@ -344,79 +341,6 @@ do_rebase_test 2.2.3 {
OMIT
} { SELECT * FROM t2 WHERE z='B' } { 1 one B }
reset_db
do_execsql_test 2.3.0 {
CREATE TABLE t1 (b TEXT);
INSERT INTO t1(rowid, b) VALUES(1, 'one');
INSERT INTO t1(rowid, b) VALUES(2, 'two');
INSERT INTO t1(rowid, b) VALUES(3, 'three');
}
do_rebase_test 2.3.1 {
UPDATE t1 SET b = 'two.1' WHERE rowid=2
} {
UPDATE t1 SET b = 'two.2' WHERE rowid=2;
} {
OMIT
} { SELECT rowid, * FROM t1 } {1 one 2 two.1 3 three}
do_rebase_test 2.3.2 {
UPDATE t1 SET b = 'two.1' WHERE rowid=2
} {
UPDATE t1 SET b = 'two.2' WHERE rowid=2;
} {
REPLACE
} { SELECT rowid, * FROM t1 } {1 one 2 two.2 3 three}
do_rebase_test 2.3.3 {
DELETE FROM t1 WHERE rowid=3
} {
DELETE FROM t1 WHERE rowid=3;
} {
OMIT
} { SELECT rowid, * FROM t1 } {1 one 2 two}
do_rebase_test 2.3.4 {
DELETE FROM t1 WHERE rowid=1
} {
UPDATE t1 SET b='one.2' WHERE rowid=1
} {
OMIT
} { SELECT rowid, * FROM t1 } {2 two 3 three}
do_rebase_test 2.3.6 {
UPDATE t1 SET b='three.1' WHERE rowid=3
} {
DELETE FROM t1 WHERE rowid=3;
} {
OMIT
} { SELECT rowid, * FROM t1 } {1 one 2 two 3 three.1}
do_rebase_test 2.3.7 {
UPDATE t1 SET b='three.1' WHERE rowid=3
} {
DELETE FROM t1 WHERE rowid=3;
} {
REPLACE
} { SELECT rowid, * FROM t1 } {1 one 2 two}
do_rebase_test 2.3.8 {
INSERT INTO t1(rowid, b) VALUES(4, 'four.1')
} {
INSERT INTO t1(rowid, b) VALUES(4, 'four.2');
} {
REPLACE
} { SELECT rowid, * FROM t1 } {1 one 2 two 3 three 4 four.2}
do_rebase_test 2.3.9 {
INSERT INTO t1(rowid, b) VALUES(4, 'four.1')
} {
INSERT INTO t1(rowid, b) VALUES(4, 'four.2');
} {
OMIT
} { SELECT rowid, * FROM t1 } {1 one 2 two 3 three 4 four.1}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
-281
View File
@@ -1,281 +0,0 @@
# 2011 Mar 16
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The focus of this file is testing the session module.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}
set testprefix sessionrowid
do_execsql_test 0.0 {
CREATE TABLE t1(a, b);
}
foreach {tn rowid bEmpty} {
1 0 1
2 1 0
3 -1 1
} {
do_test 0.$tn {
sqlite3session S db main
if {$rowid>=0} { S object_config rowid $rowid }
S attach t1
execsql { INSERT INTO t1 VALUES(1, 2); }
expr [string length [S changeset]]==0
} $bEmpty
S delete
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 1.0 {
CREATE TABLE t1(a, b);
}
do_iterator_test 1.1 t1 {
INSERT INTO t1 VALUES('i', 'one');
} {
{INSERT t1 0 X.. {} {i 1 t i t one}}
}
do_execsql_test 1.2 {
SELECT rowid, * FROM t1
} {1 i one}
do_iterator_test 1.3 t1 {
UPDATE t1 SET b='two'
} {
{UPDATE t1 0 X.. {i 1 {} {} t one} {{} {} {} {} t two}}
}
do_iterator_test 1.4 t1 {
DELETE FROM t1;
} {
{DELETE t1 0 X.. {i 1 t i t two} {}}
}
do_iterator_test 1.5 t1 {
INSERT INTO t1(rowid, a, b) VALUES(14, 'hello', 'world');
INSERT INTO t1(rowid, a, b) VALUES(NULL, 'yes', 'no');
INSERT INTO t1(rowid, a, b) VALUES(-123, 'ii', 'iii');
} {
{INSERT t1 0 X.. {} {i -123 t ii t iii}}
{INSERT t1 0 X.. {} {i 15 t yes t no}}
{INSERT t1 0 X.. {} {i 14 t hello t world}}
}
do_iterator_test 1.6 t1 {
UPDATE t1 SET a='deluxe' WHERE rowid=14;
DELETE FROM t1 WHERE rowid=-123;
INSERT INTO t1 VALUES('x', 'xi');
} {
{DELETE t1 0 X.. {i -123 t ii t iii} {}}
{UPDATE t1 0 X.. {i 14 t hello {} {}} {{} {} t deluxe {} {}}}
{INSERT t1 0 X.. {} {i 16 t x t xi}}
}
#-------------------------------------------------------------------------
reset_db
forcedelete test.db2
sqlite3 db2 test.db2
do_execsql_test 2.0 {
CREATE TABLE t1(a, b);
}
do_execsql_test -db db2 2.0.1 {
CREATE TABLE t1(a, b);
}
proc xConflict {args} {
puts "CONFLICT!"
return "OMIT"
}
do_test 2.1 {
set C [changeset_from_sql {
INSERT INTO t1 VALUES('abc', 'def');
}]
sqlite3changeset_apply db2 $C xConflict
execsql { SELECT * FROM t1 } db2
} {abc def}
do_test 2.2 {
set C [changeset_from_sql {
UPDATE t1 SET b='hello'
}]
sqlite3changeset_apply db2 $C xConflict
execsql { SELECT * FROM t1 } db2
} {abc hello}
do_test 2.3 {
set C [changeset_from_sql {
DELETE FROM t1 WHERE b='hello'
}]
sqlite3changeset_apply db2 $C xConflict
execsql { SELECT * FROM t1 } db2
} {}
do_test 2.4 {
do_then_apply_sql {
INSERT INTO t1 VALUES('i', 'one');
INSERT INTO t1 VALUES('ii', 'two');
INSERT INTO t1 VALUES('iii', 'three');
INSERT INTO t1 VALUES('iv', 'four');
}
compare_db db db2
} {}
do_test 2.5 {
do_then_apply_sql {
DELETE FROM t1 WHERE a='ii';
UPDATE t1 SET b='THREE' WHERE a='iii';
UPDATE t1 SET a='III' WHERE a='iii';
INSERT INTO t1 VALUES('v', 'five');
}
compare_db db db2
} {}
do_execsql_test 2.6 {SELECT * FROM t1} {i one III THREE iv four v five}
do_execsql_test -db db2 2.7 {SELECT * FROM t1} {i one III THREE iv four v five}
#-------------------------------------------------------------------------
db2 close
reset_db
forcedelete test.db2
sqlite3 db2 test.db2
set init_sql {
CREATE TABlE t4(a, b);
CREATE INDEX t4a ON t4(a);
CREATE UNIQUE INDEX t4b ON t4(b);
}
do_execsql_test 3.0 $init_sql
do_execsql_test -db db2 3.0a $init_sql
do_execsql_test -db db2 3.1 {
INSERT INTO t4(rowid, a, b) VALUES(43, 'hello', 'world');
}
do_conflict_test 3.2 -sql {
INSERT INTO t4(rowid, a, b) VALUES(43, 'abc', 'def');
} -tables t4 -conflicts {
{INSERT t4 CONFLICT {i 43 t abc t def} {i 43 t hello t world}}
}
do_execsql_test -db db2 3.3 {
SELECT * FROM t4
} {hello world}
do_execsql_test 3.4 { DELETE FROM t4 }
do_conflict_test 3.5 -sql {
INSERT INTO t4(rowid, a, b) VALUES(43, 'abc', 'def');
} -tables t4 -conflicts {
{INSERT t4 CONFLICT {i 43 t abc t def} {i 43 t hello t world}}
} -policy REPLACE
do_execsql_test -db db2 3.6 {
SELECT * FROM t4
} {abc def}
do_execsql_test 3.7 { DELETE FROM t4 }
do_conflict_test 3.8 -sql {
INSERT INTO t4(rowid, a, b) VALUES(45, 'xyz', 'def');
} -tables t4 -conflicts {
{INSERT t4 CONSTRAINT {i 45 t xyz t def}}
}
do_execsql_test -db db2 3.9 {
SELECT * FROM t4
} {abc def}
do_execsql_test -db db 3.10a { DELETE FROM t4 }
do_execsql_test -db db2 3.10b { DELETE FROM t4 }
do_execsql_test -db db 3.11a {
INSERT INTO t4(rowid, a, b) VALUES(111, 'one', 'one');
INSERT INTO t4(rowid, a, b) VALUES(222, 'two', 'two');
}
do_execsql_test -db db2 3.11b {
INSERT INTO t4(rowid, a, b) VALUES(111, 'one', 'blip');
}
do_conflict_test 3.12 -sql {
DELETE FROM t4 WHERE a='one';
} -tables t4 -conflicts {
{DELETE t4 DATA {i 111 t one t one} {i 111 t one t blip}}
}
do_execsql_test -db db2 3.13 {
SELECT * FROM t4
} {one blip}
do_conflict_test 3.14 -sql {
DELETE FROM t4 WHERE a='two';
} -tables t4 -conflicts {
{DELETE t4 NOTFOUND {i 222 t two t two}}
}
do_execsql_test -db db2 3.15 {
SELECT * FROM t4
} {one blip}
do_execsql_test -db db 3.16a { DELETE FROM t4 }
do_execsql_test -db db2 3.16b { DELETE FROM t4 }
do_execsql_test -db db 3.17a {
INSERT INTO t4(rowid, a, b) VALUES(111, 'one', 'one');
INSERT INTO t4(rowid, a, b) VALUES(222, 'two', 'two');
}
do_execsql_test -db db2 3.17b {
INSERT INTO t4(rowid, a, b) VALUES(111, 'one', 'blip');
}
do_conflict_test 3.18 -sql {
UPDATE t4 SET b='xyz' WHERE a='one'
} -tables t4 -conflicts {
{UPDATE t4 DATA {i 111 {} {} t one} {{} {} {} {} t xyz} {i 111 t one t blip}}
}
do_execsql_test -db db2 3.19 {
SELECT * FROM t4
} {one blip}
do_conflict_test 3.20 -sql {
UPDATE t4 SET b='123' WHERE a='two'
} -tables t4 -conflicts {
{UPDATE t4 NOTFOUND {i 222 {} {} t two} {{} {} {} {} t 123}}
}
do_execsql_test -db db2 3.21 {
SELECT * FROM t4
} {one blip}
#--------------------------------------------------------------------------
breakpoint
do_diff_test 4.0 {
CREATE TABLE t1(x, y);
CREATE TABLE aux.t1(x, y);
INSERT INTO t1 VALUES(1, 2);
}
do_diff_test 4.1 {
CREATE TABLE t1(x, y);
CREATE TABLE aux.t1(x, y);
INSERT INTO aux.t1 VALUES(1, 2);
}
do_diff_test 4.2 {
CREATE TABLE t1(x, y);
CREATE TABLE aux.t1(x, y);
INSERT INTO t1(rowid, x, y) VALUES(413, 'hello', 'there');
INSERT INTO aux.t1(rowid, x, y) VALUES(413, 'hello', 'world');
}
finish_test
+7 -7
View File
@@ -113,17 +113,17 @@ do_execsql_test 3.0 {
do_test 3.1 {
sqlite3session S db main
S object_config size -1
S object_config_size -1
} 1
do_test 3.2.1 { S object_config size 0 } 0
do_test 3.2.2 { S object_config size -1 } 0
do_test 3.2.3 { S object_config size 1 } 1
do_test 3.2.4 { S object_config size -1 } 1
do_test 3.2.1 { S object_config_size 0 } 0
do_test 3.2.2 { S object_config_size -1 } 0
do_test 3.2.3 { S object_config_size 1 } 1
do_test 3.2.4 { S object_config_size -1 } 1
do_test 3.3 { S attach t1 } {}
do_test 3.4 { S object_config size 1 } {SQLITE_MISUSE}
do_test 3.4 { S object_config size -1 } {1}
do_test 3.4 { S object_config_size 1 } {SQLITE_MISUSE}
do_test 3.4 { S object_config_size -1 } {1}
S delete
+72 -181
View File
@@ -25,8 +25,6 @@ typedef struct SessionInput SessionInput;
# endif
#endif
#define SESSIONS_ROWID "_rowid_"
static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE;
typedef struct SessionHook SessionHook;
@@ -48,7 +46,6 @@ struct sqlite3_session {
int bEnable; /* True if currently recording */
int bIndirect; /* True if all changes are indirect */
int bAutoAttach; /* True to auto-attach tables */
int bImplicitPK; /* True to handle tables with implicit PK */
int rc; /* Non-zero if an error has occurred */
void *pFilterCtx; /* First argument to pass to xTableFilter */
int (*xTableFilter)(void *pCtx, const char *zTab);
@@ -125,7 +122,6 @@ struct SessionTable {
char *zName; /* Local name of table */
int nCol; /* Number of columns in table zName */
int bStat1; /* True if this is sqlite_stat1 */
int bRowid; /* True if this table uses rowid for PK */
const char **azCol; /* Column names */
u8 *abPK; /* Array of primary key flags */
int nEntry; /* Total number of entries in hash table */
@@ -518,7 +514,6 @@ static unsigned int sessionHashAppendType(unsigned int h, int eType){
*/
static int sessionPreupdateHash(
sqlite3_session *pSession, /* Session object that owns pTab */
i64 iRowid,
SessionTable *pTab, /* Session table handle */
int bNew, /* True to hash the new.* PK */
int *piHash, /* OUT: Hash value */
@@ -527,53 +522,48 @@ static int sessionPreupdateHash(
unsigned int h = 0; /* Hash value to return */
int i; /* Used to iterate through columns */
if( pTab->bRowid ){
assert( pTab->nCol-1==pSession->hook.xCount(pSession->hook.pCtx) );
h = sessionHashAppendI64(h, iRowid);
}else{
assert( *pbNullPK==0 );
assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) );
for(i=0; i<pTab->nCol; i++){
if( pTab->abPK[i] ){
int rc;
int eType;
sqlite3_value *pVal;
assert( *pbNullPK==0 );
assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) );
for(i=0; i<pTab->nCol; i++){
if( pTab->abPK[i] ){
int rc;
int eType;
sqlite3_value *pVal;
if( bNew ){
rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal);
}else{
rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal);
}
if( rc!=SQLITE_OK ) return rc;
if( bNew ){
rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal);
}else{
rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal);
}
if( rc!=SQLITE_OK ) return rc;
eType = sqlite3_value_type(pVal);
h = sessionHashAppendType(h, eType);
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
i64 iVal;
if( eType==SQLITE_INTEGER ){
iVal = sqlite3_value_int64(pVal);
}else{
double rVal = sqlite3_value_double(pVal);
assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
memcpy(&iVal, &rVal, 8);
}
h = sessionHashAppendI64(h, iVal);
}else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
const u8 *z;
int n;
if( eType==SQLITE_TEXT ){
z = (const u8 *)sqlite3_value_text(pVal);
}else{
z = (const u8 *)sqlite3_value_blob(pVal);
}
n = sqlite3_value_bytes(pVal);
if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM;
h = sessionHashAppendBlob(h, n, z);
eType = sqlite3_value_type(pVal);
h = sessionHashAppendType(h, eType);
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
i64 iVal;
if( eType==SQLITE_INTEGER ){
iVal = sqlite3_value_int64(pVal);
}else{
assert( eType==SQLITE_NULL );
assert( pTab->bStat1==0 || i!=1 );
*pbNullPK = 1;
double rVal = sqlite3_value_double(pVal);
assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
memcpy(&iVal, &rVal, 8);
}
h = sessionHashAppendI64(h, iVal);
}else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
const u8 *z;
int n;
if( eType==SQLITE_TEXT ){
z = (const u8 *)sqlite3_value_text(pVal);
}else{
z = (const u8 *)sqlite3_value_blob(pVal);
}
n = sqlite3_value_bytes(pVal);
if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM;
h = sessionHashAppendBlob(h, n, z);
}else{
assert( eType==SQLITE_NULL );
assert( pTab->bStat1==0 || i!=1 );
*pbNullPK = 1;
}
}
}
@@ -856,7 +846,6 @@ static int sessionMergeUpdate(
*/
static int sessionPreupdateEqual(
sqlite3_session *pSession, /* Session object that owns SessionTable */
i64 iRowid, /* Rowid value if pTab->bRowid */
SessionTable *pTab, /* Table associated with change */
SessionChange *pChange, /* Change to compare to */
int op /* Current pre-update operation */
@@ -864,11 +853,6 @@ static int sessionPreupdateEqual(
int iCol; /* Used to iterate through columns */
u8 *a = pChange->aRecord; /* Cursor used to scan change record */
if( pTab->bRowid ){
if( a[0]!=SQLITE_INTEGER ) return 0;
return sessionGetI64(&a[1])==iRowid;
}
assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );
for(iCol=0; iCol<pTab->nCol; iCol++){
if( !pTab->abPK[iCol] ){
@@ -1013,8 +997,7 @@ static int sessionTableInfo(
int *pnCol, /* OUT: number of columns */
const char **pzTab, /* OUT: Copy of zThis */
const char ***pazCol, /* OUT: Array of column names for table */
u8 **pabPK, /* OUT: Array of booleans - true for PK col */
int *pbRowid /* OUT: True if only PK is a rowid */
u8 **pabPK /* OUT: Array of booleans - true for PK col */
){
char *zPragma;
sqlite3_stmt *pStmt;
@@ -1026,7 +1009,6 @@ static int sessionTableInfo(
u8 *pAlloc = 0;
char **azCol = 0;
u8 *abPK = 0;
int bRowid = 0; /* Set to true to use rowid as PK */
assert( pazCol && pabPK );
@@ -1071,15 +1053,10 @@ static int sessionTableInfo(
}
nByte = nThis + 1;
bRowid = (pbRowid!=0);
while( SQLITE_ROW==sqlite3_step(pStmt) ){
nByte += sqlite3_column_bytes(pStmt, 1);
nDbCol++;
if( sqlite3_column_int(pStmt, 5) ) bRowid = 0;
}
if( nDbCol==0 ) bRowid = 0;
nDbCol += bRowid;
nByte += strlen(SESSIONS_ROWID);
rc = sqlite3_reset(pStmt);
if( rc==SQLITE_OK ){
@@ -1101,14 +1078,6 @@ static int sessionTableInfo(
}
i = 0;
if( bRowid ){
size_t nName = strlen(SESSIONS_ROWID);
memcpy(pAlloc, SESSIONS_ROWID, nName+1);
azCol[i] = (char*)pAlloc;
pAlloc += nName+1;
abPK[i] = 1;
i++;
}
while( SQLITE_ROW==sqlite3_step(pStmt) ){
int nName = sqlite3_column_bytes(pStmt, 1);
const unsigned char *zName = sqlite3_column_text(pStmt, 1);
@@ -1120,6 +1089,7 @@ static int sessionTableInfo(
i++;
}
rc = sqlite3_reset(pStmt);
}
/* If successful, populate the output variables. Otherwise, zero them and
@@ -1136,7 +1106,6 @@ static int sessionTableInfo(
if( pzTab ) *pzTab = 0;
sessionFree(pSession, azCol);
}
if( pbRowid ) *pbRowid = bRowid;
sqlite3_finalize(pStmt);
return rc;
}
@@ -1158,8 +1127,7 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
u8 *abPK;
assert( pTab->azCol==0 || pTab->abPK==0 );
pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb,
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK,
(pSession->bImplicitPK ? &pTab->bRowid : 0)
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK
);
if( pSession->rc==SQLITE_OK ){
int i;
@@ -1231,7 +1199,6 @@ static int sessionUpdateMaxSize(
){
i64 nNew = 2;
if( pC->op==SQLITE_INSERT ){
if( pTab->bRowid ) nNew += 9;
if( op!=SQLITE_DELETE ){
int ii;
for(ii=0; ii<pTab->nCol; ii++){
@@ -1248,11 +1215,7 @@ static int sessionUpdateMaxSize(
}else{
int ii;
u8 *pCsr = pC->aRecord;
if( pTab->bRowid ){
nNew += 9;
pCsr += 9;
}
for(ii=0; ii<(pTab->nCol-pTab->bRowid); ii++){
for(ii=0; ii<pTab->nCol; ii++){
int bChanged = 1;
int nOld = 0;
int eType;
@@ -1336,7 +1299,6 @@ static int sessionUpdateMaxSize(
*/
static void sessionPreupdateOneChange(
int op, /* One of SQLITE_UPDATE, INSERT, DELETE */
i64 iRowid,
sqlite3_session *pSession, /* Session object pTab is attached to */
SessionTable *pTab /* Table that change applies to */
){
@@ -1352,7 +1314,7 @@ static void sessionPreupdateOneChange(
/* Check the number of columns in this xPreUpdate call matches the
** number of columns in the table. */
if( (pTab->nCol-pTab->bRowid)!=pSession->hook.xCount(pSession->hook.pCtx) ){
if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){
pSession->rc = SQLITE_SCHEMA;
return;
}
@@ -1385,16 +1347,14 @@ static void sessionPreupdateOneChange(
/* Calculate the hash-key for this change. If the primary key of the row
** includes a NULL value, exit early. Such changes are ignored by the
** session module. */
rc = sessionPreupdateHash(
pSession, iRowid, pTab, op==SQLITE_INSERT, &iHash, &bNull
);
rc = sessionPreupdateHash(pSession, pTab, op==SQLITE_INSERT, &iHash, &bNull);
if( rc!=SQLITE_OK ) goto error_out;
if( bNull==0 ){
/* Search the hash table for an existing record for this row. */
SessionChange *pC;
for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){
if( sessionPreupdateEqual(pSession, iRowid, pTab, pC, op) ) break;
if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break;
}
if( pC==0 ){
@@ -1409,7 +1369,7 @@ static void sessionPreupdateOneChange(
/* Figure out how large an allocation is required */
nByte = sizeof(SessionChange);
for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
for(i=0; i<pTab->nCol; i++){
sqlite3_value *p = 0;
if( op!=SQLITE_INSERT ){
TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p);
@@ -1424,9 +1384,6 @@ static void sessionPreupdateOneChange(
rc = sessionSerializeValue(0, p, &nByte);
if( rc!=SQLITE_OK ) goto error_out;
}
if( pTab->bRowid ){
nByte += 9; /* Size of rowid field - an integer */
}
/* Allocate the change object */
pC = (SessionChange *)sessionMalloc64(pSession, nByte);
@@ -1443,12 +1400,7 @@ static void sessionPreupdateOneChange(
** required values and encodings have already been cached in memory.
** It is not possible for an OOM to occur in this block. */
nByte = 0;
if( pTab->bRowid ){
pC->aRecord[0] = SQLITE_INTEGER;
sessionPutI64(&pC->aRecord[1], iRowid);
nByte = 9;
}
for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
for(i=0; i<pTab->nCol; i++){
sqlite3_value *p = 0;
if( op!=SQLITE_INSERT ){
pSession->hook.xOld(pSession->hook.pCtx, i, &p);
@@ -1563,10 +1515,9 @@ static void xPreUpdate(
pSession->rc = sessionFindTable(pSession, zName, &pTab);
if( pTab ){
assert( pSession->rc==SQLITE_OK );
assert( op==SQLITE_UPDATE || iKey1==iKey2 );
sessionPreupdateOneChange(op, iKey1, pSession, pTab);
sessionPreupdateOneChange(op, pSession, pTab);
if( op==SQLITE_UPDATE ){
sessionPreupdateOneChange(SQLITE_INSERT, iKey2, pSession, pTab);
sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab);
}
}
}
@@ -1605,7 +1556,6 @@ static void sessionPreupdateHooks(
typedef struct SessionDiffCtx SessionDiffCtx;
struct SessionDiffCtx {
sqlite3_stmt *pStmt;
int bRowid;
int nOldOff;
};
@@ -1614,17 +1564,17 @@ struct SessionDiffCtx {
*/
static int sessionDiffOld(void *pCtx, int iVal, sqlite3_value **ppVal){
SessionDiffCtx *p = (SessionDiffCtx*)pCtx;
*ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff+p->bRowid);
*ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff);
return SQLITE_OK;
}
static int sessionDiffNew(void *pCtx, int iVal, sqlite3_value **ppVal){
SessionDiffCtx *p = (SessionDiffCtx*)pCtx;
*ppVal = sqlite3_column_value(p->pStmt, iVal+p->bRowid);
*ppVal = sqlite3_column_value(p->pStmt, iVal);
return SQLITE_OK;
}
static int sessionDiffCount(void *pCtx){
SessionDiffCtx *p = (SessionDiffCtx*)pCtx;
return (p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt)) - p->bRowid;
return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt);
}
static int sessionDiffDepth(void *pCtx){
(void)pCtx;
@@ -1703,16 +1653,14 @@ static char *sessionExprCompareOther(
static char *sessionSelectFindNew(
const char *zDb1, /* Pick rows in this db only */
const char *zDb2, /* But not in this one */
int bRowid,
const char *zTbl, /* Table name */
const char *zExpr
){
const char *zSel = (bRowid ? SESSIONS_ROWID ", *" : "*");
char *zRet = sqlite3_mprintf(
"SELECT %s FROM \"%w\".\"%w\" WHERE NOT EXISTS ("
"SELECT * FROM \"%w\".\"%w\" WHERE NOT EXISTS ("
" SELECT 1 FROM \"%w\".\"%w\" WHERE %s"
")",
zSel, zDb1, zTbl, zDb2, zTbl, zExpr
zDb1, zTbl, zDb2, zTbl, zExpr
);
return zRet;
}
@@ -1726,9 +1674,7 @@ static int sessionDiffFindNew(
char *zExpr
){
int rc = SQLITE_OK;
char *zStmt = sessionSelectFindNew(
zDb1, zDb2, pTab->bRowid, pTab->zName, zExpr
);
char *zStmt = sessionSelectFindNew(zDb1, zDb2, pTab->zName,zExpr);
if( zStmt==0 ){
rc = SQLITE_NOMEM;
@@ -1739,10 +1685,8 @@ static int sessionDiffFindNew(
SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx;
pDiffCtx->pStmt = pStmt;
pDiffCtx->nOldOff = 0;
pDiffCtx->bRowid = pTab->bRowid;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
i64 iRowid = (pTab->bRowid ? sqlite3_column_int64(pStmt, 0) : 0);
sessionPreupdateOneChange(op, iRowid, pSession, pTab);
sessionPreupdateOneChange(op, pSession, pTab);
}
rc = sqlite3_finalize(pStmt);
}
@@ -1752,27 +1696,6 @@ static int sessionDiffFindNew(
return rc;
}
/*
** Return a comma-separated list of the fully-qualified (with both database
** and table name) column names from table pTab. e.g.
**
** "main"."t1"."a", "main"."t1"."b", "main"."t1"."c"
*/
static char *sessionAllCols(
const char *zDb,
SessionTable *pTab
){
int ii;
char *zRet = 0;
for(ii=0; ii<pTab->nCol; ii++){
zRet = sqlite3_mprintf("%z%s\"%w\".\"%w\".\"%w\"",
zRet, (zRet ? ", " : ""), zDb, pTab->zName, pTab->azCol[ii]
);
if( !zRet ) break;
}
return zRet;
}
static int sessionDiffFindModified(
sqlite3_session *pSession,
SessionTable *pTab,
@@ -1787,13 +1710,11 @@ static int sessionDiffFindModified(
if( zExpr2==0 ){
rc = SQLITE_NOMEM;
}else{
char *z1 = sessionAllCols(pSession->zDb, pTab);
char *z2 = sessionAllCols(zFrom, pTab);
char *zStmt = sqlite3_mprintf(
"SELECT %s,%s FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)",
z1, z2, pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2
"SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)",
pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2
);
if( zStmt==0 || z1==0 || z2==0 ){
if( zStmt==0 ){
rc = SQLITE_NOMEM;
}else{
sqlite3_stmt *pStmt;
@@ -1804,15 +1725,12 @@ static int sessionDiffFindModified(
pDiffCtx->pStmt = pStmt;
pDiffCtx->nOldOff = pTab->nCol;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
i64 iRowid = (pTab->bRowid ? sqlite3_column_int64(pStmt, 0) : 0);
sessionPreupdateOneChange(SQLITE_UPDATE, iRowid, pSession, pTab);
sessionPreupdateOneChange(SQLITE_UPDATE, pSession, pTab);
}
rc = sqlite3_finalize(pStmt);
}
sqlite3_free(zStmt);
}
sqlite3_free(zStmt);
sqlite3_free(z1);
sqlite3_free(z2);
}
return rc;
@@ -1851,12 +1769,9 @@ int sqlite3session_diff(
int bHasPk = 0;
int bMismatch = 0;
int nCol; /* Columns in zFrom.zTbl */
int bRowid = 0;
u8 *abPK;
const char **azCol = 0;
rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK,
pSession->bImplicitPK ? &bRowid : 0
);
rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
if( rc==SQLITE_OK ){
if( pTo->nCol!=nCol ){
bMismatch = 1;
@@ -2507,7 +2422,6 @@ static int sessionSelectStmt(
int bIgnoreNoop,
const char *zDb, /* Database name */
const char *zTab, /* Table name */
int bRowid,
int nCol, /* Number of columns in table */
const char **azCol, /* Names of table columns */
u8 *abPK, /* PRIMARY KEY array */
@@ -2516,7 +2430,7 @@ static int sessionSelectStmt(
int rc = SQLITE_OK;
char *zSql = 0;
const char *zSep = "";
const char *zCols = bRowid ? SESSIONS_ROWID ", *" : "*";
const char *zCols = "*";
int nSql = -1;
int i;
@@ -2535,6 +2449,7 @@ static int sessionSelectStmt(
zCols = "tbl, ?2, stat";
}else{
for(i=0; i<nCol; i++){
if( abPK[i] ){
sessionAppendStr(&pkfield, zSep, &rc);
sessionAppendStr(&pkvar, zSep, &rc);
@@ -2741,18 +2656,10 @@ static int sessionGenerateChangeset(
sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */
int nRewind = buf.nBuf; /* Initial size of write buffer */
int nNoop; /* Size of buffer after writing tbl header */
int bRowid = 0;
/* Check the table schema is still Ok. */
rc = sessionTableInfo(
0, db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK,
(pSession->bImplicitPK ? &bRowid : 0)
);
if( rc==SQLITE_OK && (
pTab->nCol!=nCol
|| pTab->bRowid!=bRowid
|| memcmp(abPK, pTab->abPK, nCol)
)){
rc = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK);
if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){
rc = SQLITE_SCHEMA;
}
@@ -2762,7 +2669,7 @@ static int sessionGenerateChangeset(
/* Build and compile a statement to execute: */
if( rc==SQLITE_OK ){
rc = sessionSelectStmt(
db, 0, pSession->zDb, zName, bRowid, nCol, azCol, abPK, &pSel
db, 0, pSession->zDb, zName, nCol, azCol, abPK, &pSel
);
}
@@ -2846,8 +2753,8 @@ int sqlite3session_changeset(
int rc;
if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE;
rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset);
assert( 1 || rc || pnChangeset==0
rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset);
assert( rc || pnChangeset==0
|| pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize
);
return rc;
@@ -2964,19 +2871,6 @@ int sqlite3session_object_config(sqlite3_session *pSession, int op, void *pArg){
break;
}
case SQLITE_SESSION_OBJCONFIG_ROWID: {
int iArg = *(int*)pArg;
if( iArg>=0 ){
if( pSession->pTable ){
rc = SQLITE_MISUSE;
}else{
pSession->bImplicitPK = (iArg!=0);
}
}
*(int*)pArg = pSession->bImplicitPK;
break;
}
default:
rc = SQLITE_MISUSE;
}
@@ -3966,7 +3860,6 @@ struct SessionApplyCtx {
u8 bRebaseStarted; /* If table header is already in rebase */
u8 bRebase; /* True to collect rebase information */
u8 bIgnoreNoop; /* True to ignore no-op conflicts */
int bRowid;
};
/* Number of prepared UPDATE statements to cache. */
@@ -4217,9 +4110,8 @@ static int sessionSelectRow(
const char *zTab, /* Table name */
SessionApplyCtx *p /* Session changeset-apply context */
){
/* TODO */
return sessionSelectStmt(db, p->bIgnoreNoop,
"main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect
"main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect
);
}
@@ -4915,7 +4807,6 @@ static int sessionChangesetApply(
sApply.bStat1 = 0;
sApply.bDeferConstraints = 1;
sApply.bRebaseStarted = 0;
sApply.bRowid = 0;
memset(&sApply.constraints, 0, sizeof(SessionBuffer));
/* If an xFilter() callback was specified, invoke it now. If the
@@ -4935,8 +4826,8 @@ static int sessionChangesetApply(
int i;
sqlite3changeset_pk(pIter, &abPK, 0);
rc = sessionTableInfo(0, db, "main", zNew,
&sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK, &sApply.bRowid
rc = sessionTableInfo(0,
db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
);
if( rc!=SQLITE_OK ) break;
for(i=0; i<sApply.nCol; i++){
+10 -23
View File
@@ -80,20 +80,16 @@ int sqlite3session_create(
void sqlite3session_delete(sqlite3_session *pSession);
/*
** CAPI3REF: Configure a Session Object
** CAPIREF: Conigure a Session Object
** METHOD: sqlite3_session
**
** This method is used to configure a session object after it has been
** created. At present the only valid values for the second parameter are
** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID].
** created. At present the only valid value for the second parameter is
** [SQLITE_SESSION_OBJCONFIG_SIZE].
**
*/
int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
/*
** CAPI3REF: Options for sqlite3session_object_config
** Arguments for sqlite3session_object_config()
**
** The following values may passed as the the 2nd parameter to
** The following values may passed as the the 4th parameter to
** sqlite3session_object_config().
**
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
@@ -109,21 +105,12 @@ int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
**
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
** the first table has been attached to the session object.
**
** <dt>SQLITE_SESSION_OBJCONFIG_ROWID <dd>
** This option is used to set, clear or query the flag that enables
** collection of data for tables with no explicit PRIMARY KEY.
**
** Normally, tables with no explicit PRIMARY KEY are simply ignored
** by the sessions module. However, if this flag is set, it behaves
** as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted
** as their leftmost columns.
**
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
** the first table has been attached to the session object.
*/
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
#define SQLITE_SESSION_OBJCONFIG_ROWID 2
int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
/*
*/
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
/*
** CAPI3REF: Enable Or Disable A Session Object
+6 -20
View File
@@ -76,11 +76,9 @@ int sql_exec_changeset(
){
sqlite3_session *pSession = 0;
int rc;
int val = 1;
/* Create a new session object */
rc = sqlite3session_create(db, "main", &pSession);
sqlite3session_object_config(pSession, SQLITE_SESSION_OBJCONFIG_ROWID, &val);
/* Configure the session object to record changes to all tables */
if( rc==SQLITE_OK ) rc = sqlite3session_attach(pSession, NULL);
@@ -262,7 +260,7 @@ static int SQLITE_TCLAPI test_session_cmd(
{ "diff", 2, "FROMDB TBL", }, /* 8 */
{ "memory_used", 0, "", }, /* 9 */
{ "changeset_size", 0, "", }, /* 10 */
{ "object_config", 2, "OPTION INTEGER", }, /* 11 */
{ "object_config_size", 1, "INTEGER", }, /* 11 */
{ 0 }
};
int iSub;
@@ -381,27 +379,15 @@ static int SQLITE_TCLAPI test_session_cmd(
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize));
break;
}
case 11: { /* object_config */
struct ObjConfOpt {
const char *zName;
int opt;
} aOpt[] = {
{ "size", SQLITE_SESSION_OBJCONFIG_SIZE },
{ "rowid", SQLITE_SESSION_OBJCONFIG_ROWID },
{ 0, 0 }
};
size_t sz = sizeof(aOpt[0]);
case 11: {
int rc;
int iArg;
int iOpt;
if( Tcl_GetIndexFromObjStruct(interp,objv[2],aOpt,sz,"option",0,&iOpt) ){
if( Tcl_GetIntFromObj(interp, objv[2], &iArg) ){
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, objv[3], &iArg) ){
return TCL_ERROR;
}
rc = sqlite3session_object_config(pSession, aOpt[iOpt].opt, &iArg);
rc = sqlite3session_object_config(
pSession, SQLITE_SESSION_OBJCONFIG_SIZE, &iArg
);
if( rc!=SQLITE_OK ){
extern const char *sqlite3ErrName(int);
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
-5
View File
@@ -1537,9 +1537,6 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
Full docs: https://sqlite.org/c3ref/db_config.html
Returns capi.SQLITE_MISUSE if op is not a valid operation ID.
The variants which take `(int, int*)` arguments treat a
missing or falsy pointer argument as 0.
*/
capi.sqlite3_db_config = function(pDb, op, ...args){
if(!this.s){
@@ -1568,8 +1565,6 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
case capi.SQLITE_DBCONFIG_ENABLE_VIEW:
case capi.SQLITE_DBCONFIG_LEGACY_FILE_FORMAT:
case capi.SQLITE_DBCONFIG_TRUSTED_SCHEMA:
case capi.SQLITE_DBCONFIG_STMT_SCANSTATUS:
case capi.SQLITE_DBCONFIG_REVERSE_SCANORDER:
return this.ip(pDb, op, args[0], args[1] || 0);
case capi.SQLITE_DBCONFIG_LOOKASIDE:
return this.pii(pDb, op, args[0], args[1], args[2]);
+8 -7
View File
@@ -353,6 +353,7 @@ const installOpfsVfs = function callee(options){
state.opIds.xClose = i++;
state.opIds.xDelete = i++;
state.opIds.xDeleteNoWait = i++;
state.opIds.xFileControl = i++;
state.opIds.xFileSize = i++;
state.opIds.xLock = i++;
state.opIds.xOpen = i++;
@@ -717,9 +718,12 @@ const installOpfsVfs = function callee(options){
return capi.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
},
xFileControl: function(pFile, opId, pArg){
/*mTimeStart('xFileControl');
mTimeEnd();*/
return capi.SQLITE_NOTFOUND;
mTimeStart('xFileControl');
const rc = (capi.SQLITE_FCNTL_SYNC===opId)
? opRun('xSync', pFile, 0)
: capi.SQLITE_NOTFOUND;
mTimeEnd();
return rc;
},
xFileSize: function(pFile,pSz64){
mTimeStart('xFileSize');
@@ -775,11 +779,8 @@ const installOpfsVfs = function callee(options){
return rc;
},
xSync: function(pFile,flags){
mTimeStart('xSync');
++metrics.xSync.count;
const rc = opRun('xSync', pFile, flags);
mTimeEnd();
return rc;
return 0; // impl'd in xFileControl()
},
xTruncate: function(pFile,sz64){
mTimeStart('xTruncate');
-4
View File
@@ -567,8 +567,6 @@ const char * sqlite3_wasm_enum_json(void){
DefInt(SQLITE_DBCONFIG_ENABLE_VIEW);
DefInt(SQLITE_DBCONFIG_LEGACY_FILE_FORMAT);
DefInt(SQLITE_DBCONFIG_TRUSTED_SCHEMA);
DefInt(SQLITE_DBCONFIG_STMT_SCANSTATUS);
DefInt(SQLITE_DBCONFIG_REVERSE_SCANORDER);
DefInt(SQLITE_DBCONFIG_MAX);
} _DefGroup;
@@ -1547,8 +1545,6 @@ int sqlite3_wasm_db_config_ip(sqlite3 *pDb, int op, int arg1, int* pArg2){
case SQLITE_DBCONFIG_ENABLE_VIEW:
case SQLITE_DBCONFIG_LEGACY_FILE_FORMAT:
case SQLITE_DBCONFIG_TRUSTED_SCHEMA:
case SQLITE_DBCONFIG_STMT_SCANSTATUS:
case SQLITE_DBCONFIG_REVERSE_SCANORDER:
return sqlite3_db_config(pDb, op, arg1, pArg2);
default: return SQLITE_MISUSE;
}
+5 -4
View File
@@ -23,7 +23,7 @@
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<fieldset id='ui-controls' class='hidden'>
<legend>Options</legend>
@@ -68,9 +68,10 @@
<ul>
<li>Control-click the flags to (de)select multiple flags.</li>
<li>The <tt>--big-transactions</tt> flag is important for two
of the bigger tests. Without it, those tests create many
thousands of implicit transactions, reducing the affected
tests to an absolute crawl, in particular with OPFS.
of the bigger tests. Without it, those tests create a
combined total of 140k implicit transactions, reducing their
speed to an absolute crawl, especially when WASMFS is
activated.
</li>
<li>The easiest way to try different optimization levels is,
from this directory:
+49 -61
View File
@@ -1,5 +1,5 @@
C Give\sCLI\squoted\sargs\shex\sescapes\s(as\sdocumented.)
D 2023-05-02T19:33:27.498
C Dynamically\sresize\sthe\snode\shash\stable\sused\sby\sthe\srtree\smodule.
D 2023-04-27T19:27:55.114
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -92,7 +92,7 @@ F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b7292
F ext/fts5/fts5_config.c 46af0b3c3c3f00bfc5bdd307434d7c5f0fa0678a034dd48345cd83b20068efbd
F ext/fts5/fts5_expr.c 7d298d76ea010c339b26ca47f6f69e9aef520ea46c083deaa4e83e87cf0e94b1
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
F ext/fts5/fts5_index.c d1eaca422cd3ab52adbe94f2a1ff6b3a4bea2960c6fa33a03f57499204ec36e0
F ext/fts5/fts5_index.c 17dca8e874df04182bc45063dc0b761acc242b91f1264d2257b7e37bd4e4c2ad
F ext/fts5/fts5_main.c b4dba04a36aaf9b8e8cef0100b6dbb422cc74753eacc11d6401cac7a87c0f38d
F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
@@ -137,7 +137,6 @@ F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36
F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
F ext/fts5/test/fts5corrupt5.test 550d0884c14424f9acad051a741f1dd99ec9342277d938e91ff3daf9123d1209
F ext/fts5/test/fts5corrupt6.test bf8eeae07825b088b9665d9d8e4accbd8dc9bf3cb85b6c64cf6c9e18ccc420a4
F ext/fts5/test/fts5corrupt7.test f3e68673af2514e31dd67a2ed163f7f597252ab683dec155b8db0cdc0b668342
F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
@@ -272,8 +271,8 @@ F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f23
F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 9642c7a194a2a25dca7ad3e36af24a0a46d7702168c4ad7e59c9f9b0e16a3824
F ext/misc/base64.c a71b131e50300c654a66c469a25b62874481f3d1cb3beb56aca9a68edd812e0d
F ext/misc/base85.c 073054111988db593ef5fdb87ab8c459df1ea0c3aaaddf0f5bfa3d72b7e6280a
F ext/misc/base64.c e83a915fcb94c9332e9a92aa4c3beafe2552bd3da2813fc5fff31918cca0b834
F ext/misc/base85.c 77dfd5813d23ea561d0348f922583888e78f8eaeb2b9a4a28226d092389890b8
F ext/misc/basexx.c 5e859e1820620aa8080fb9145eb47089de426ae808f6abb01a8e12921c3a8e67
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
@@ -302,12 +301,11 @@ F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d
F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691
F ext/misc/prefixes.c 0f4f8cff5aebc00a7e3ac4021fd59cfe1a8e17c800ceaf592859ecb9cbc38196
F ext/misc/qpvtab.c 09738419e25f603a35c0ac8bd0a04daab794f48d08a9bc07a6085b9057b99009
F ext/misc/randomjson.c 7dd13664155319d47b9facc0d8dbf45e13062966a47168e54e3f26d48240d7ea
F ext/misc/regexp.c f50ab59bfa8934b7ed98de069d2c74c187f2ef523fb09e85f8840f6459a90942
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
F ext/misc/series.c 37d27377684d3ea14177540d2f2767163197611eaba905790c96abd4ab552cd3
F ext/misc/series.c 8d79354f2c3d46b95ee21272a07cf0bcabb58d1f2b06d9e7b8a31dca1dacb3e5
F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
F ext/misc/shathree.c 543af7ce71d391cd3a9ab6924a6a1124efc63211fd0f2e240dc4b56077ba88ac
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
@@ -401,10 +399,10 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/geopoly.c 971e0b5bd9adaf0811feb8c0842a310811159da10319eb0e74fdb42bf26b99ca
F ext/rtree/rtree.c 925888f7672b326fc2a29b3a212ec3ae4aa2331507ecccfaf7f0ac0335020330
F ext/rtree/geopoly.c 398b966772d81b9e6cd05caaf94f5d9d38b26f4245d4f0908b41c60024298412
F ext/rtree/rtree.c 92def73e587b2daaff1c8b2c50c5ca0c0e543222f4d0e926ce0479454bd2b673
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test d47f58832145fcfed9067bc457ca8664962196c4566c17a1ebd679367db55d11
F ext/rtree/rtree1.test 96271886cb39b680ed8c0a8dc0dd341e52a368bbd54d461a433e7aecd0556a2a
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
F ext/rtree/rtree3.test 272594f88c344e973864008bbe4c71fd3a41a264c097d568593ee7886d83d409
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
@@ -451,12 +449,12 @@ F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
F ext/session/sessionB.test c4fb7f8a688787111606e123a555f18ee04f65bb9f2a4bb2aa71d55ce4e6d02c
F ext/session/sessionC.test f8a5508bc059ae646e5ec9bdbca66ad24bc92fe99fda5790ac57e1f59fce2fdf
F ext/session/sessionD.test f5c6a762d00bc6ca9d561695c322ba8ecca2bed370486707ef37cf565d2f6c73
F ext/session/sessionD.test 4f91d0ca8afc4c3969c72c9f0b5ea9527e21de29039937d0d973f821e8470724
F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
F ext/session/sessionG.test 3efe388282d641b65485b5462e67851002cd91a282dc95b685d085eb8efdad0a
F ext/session/sessionH.test 71bbff6b1abb2c4ac62b84dee53273c37e0b21e5fde3aed80929403e091ef859
F ext/session/session_common.tcl e5598096425486b363718e2cda48ee85d660c96b4f8ea9d9d7a4c3ef514769da
F ext/session/session_common.tcl db0dda567c75950604072251744e9a6ad5795a3009963c44eb8510f23a8cda64
F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8be518b62d6cbdef88b3
F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
@@ -467,14 +465,13 @@ F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2
F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
F ext/session/sessionnoop2.test 5c9a882219e54711c98dccd2fd81392f189a59325e4fb5d8ed25e33a0c2f0ba2
F ext/session/sessionrebase.test 702378bdcb5062f1106e74457beca8797d09c113a81768734a58b197b5b334e2
F ext/session/sessionrowid.test 6323ba831721205fd729929745038fd54e9d128c66c654b8d0b26853095a321c
F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
F ext/session/sessionsize.test 6f644aff31c7f1e4871e9ff3542766e18da68fc7e587b83a347ea9820a002dd8
F ext/session/sessionstat1.test b039e38e2ba83767b464baf39b297cc0b1cc6f3292255cb467ea7e12d0d0280c
F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
F ext/session/sqlite3session.c d14d3043d4e04b080090d92b46e7b01ed25f49985161c8cb4fba05eefaf85850
F ext/session/sqlite3session.h 653e9d49c4edae231df8a4c8d69c2145195aedb32462d4b44229dbee7d2680fb
F ext/session/test_session.c 5285482f83cd92b4c1fe12fcf88210566a18312f4f2aa110f6399dae46aeccbb
F ext/session/sqlite3session.c 1795263b72c1a17e48e95a131a69543af3fa31aa8e81271c7c5cb0911f063604
F ext/session/sqlite3session.h c367c3043dbb57f69cca35258ebbeadb24e8738980b1a1ae1e281c1b0fac3989
F ext/session/test_session.c b55a669a2150eb7c491b8b42c69a3eed9bc895cf5fea371a2c813b9618f72163
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
@@ -494,14 +491,14 @@ F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057af
F ext/wasm/api/sqlite3-api-cleanup.js cc21e3486da748463e02bbe51e2464c6ac136587cdfd5aa00cd0b5385f6ca808
F ext/wasm/api/sqlite3-api-glue.js f1b2dcb944de5138bb5bd9a1559d2e76a4f3ec25260963d709e8237476688803
F ext/wasm/api/sqlite3-api-oo1.js 2691a34a741015127b210954a1b9586764d3ff0c8a20f00fd15c00f339ecc79f
F ext/wasm/api/sqlite3-api-prologue.js 17f4ec398ba34c5c666fea8e8c4eb82064a35b302f2f2eb355283cd8d3f68ed5
F ext/wasm/api/sqlite3-api-prologue.js 461ffa5a95f4c1935b3970a58790d3cdca62b16e9b9a6a8d993a2a47d7561f51
F ext/wasm/api/sqlite3-api-worker1.js 40a5b1813fcbe789f23ae196c833432c8c83e7054d660194ddfc51eab1c5b9bf
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 70914ae97784d3028150bbf252e07a423056c42cc345903c81b5fae661ce512f
F ext/wasm/api/sqlite3-v-helper.js e5c202a9ecde9ef818536d3f5faf26c03a1a9f5192b1ddea8bdabf30d75ef487
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 89640e4874a60cb2d973306b272384ffb45c7915375c7bb0355c7586f88dc39c
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 14130dc3f0830cd994162684eee3c42615aa3bca15950d2a7b48fe5c4b6e657f
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 12a096d8e58a0af0589142bae5a3c27a0c7e19846755a1a37d2c206352fbedda
F ext/wasm/api/sqlite3-wasm.c c42413ca9f3e64c424b2bbfc5decf639670ca38bc8f7afb7760d5379398c9307
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js 2710a06a59620c6bf7ce298ab1fb6c9ce825b9f9379728b74c486db6613beecc
F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
@@ -535,7 +532,7 @@ F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
F ext/wasm/scratchpad-wasmfs-main.js 4c140457f4d6da9d646a49addd91edb6e9ad1643c6c48e3258b5bce24725dc18
F ext/wasm/speedtest1-wasmfs.html 7a301f4f5b6ad4f5d37fd6e7ca03a2f5d5547fd289da60a39075a93d7646d354
F ext/wasm/speedtest1-worker.html 82869822e641c1bef3ec0cd2d7d2b6a42d0b4f68a7b160fb2e1dd0b523940a9b
F ext/wasm/speedtest1-worker.html fe6b36a63de1012bb9fb4d2fb888b6de9c589c21b0aa3ae054459b0093e077bf
F ext/wasm/speedtest1-worker.js 13b57c4a41729678a1194014afec2bd5b94435dcfc8d1039dfa9a533ac819ee1
F ext/wasm/speedtest1.html ff048b4a623aa192e83e143e48f1ce2a899846dd42c023fdedc8772b6e3f07da
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
@@ -574,9 +571,9 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 6ffb0a22c19e2f9110be0964d0731d2ef1c67b5f7fabfbaeb7b9dabc4b7740ca
F src/btree.c 1949007d2792cf761799348b3760c8489d1964c49efa9e52591aa1f2fcdbc96f
F src/btree.c 37292454e4f5cd148b3c661770df44e28060f2cefd227ad979bf9b5f155db11b
F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
F src/btreeInt.h a9ae91868acc4b3146d47ae2a072aac2cf41ecb7386015752160c8e1a212d9f2
F src/btreeInt.h a3268a60cbc91f578001f44ba40aae9c1b8aecbb0d2c095dd7fc54b0872ea4b8
F src/build.c 8357d6ca9a8c9afc297c431df28bc2af407b47f3ef2311875276c944b30c4d54
F src/callback.c 4cd7225b26a97f7de5fee5ae10464bed5a78f2adefe19534cc2095b3a8ca484a
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
@@ -585,20 +582,20 @@ F src/date.c f21815ca7172ce073db3163ac54c8d9f2841077165c1a6123b4d1c376a0c7ec7
F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387
F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
F src/delete.c a9c6d3f51c0a31e9b831e0a0580a98d702904b42d216fee530940e40dec34873
F src/expr.c 871cfd80c516ee39d90414b2d3da2b5bc9c9e21fe87b7eb787ea7ae4b6461758
F src/expr.c 6353f4d92d9f67ec3466d8e6978cd31a45e34cb755c4d11e689077f03f7c0a15
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 03c134cc8bffe54835f742ddea0b72ebfc8f6b32773d175c71b8afeea6cb5c83
F src/func.c d187be57a886ddf4e6b7ef584a494361899be3df5eee6d4a747b68ff4aff4122
F src/global.c bd0892ade7289f6e20bff44c07d06371f2ff9b53cea359e7854b9b72f65adc30
F src/global.c 428d2580a1cdf5dbe1f356d1feab83710ae0cc862ece0fb57bc8259e43838c74
F src/hash.c c6af5f96a7a76d000f07c5402c48c318c2566beecdee9e78b9d9f60ce7119565
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h b638809e083b601b618df877b2e89cb87c2a47a01f4def10be4c4ebb54664ac7
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c a8de1db43335fc4946370a7a7e47d89975ad678ddb15078a150e993ba2fb37d4
F src/json.c 2cbf343884b0f0e7b4c39f8cb8a2dbf4fb49d92161aff4c76a20996d799cbe18
F src/json.c edae65fe1f66ce8b1e7fa6eb036a3d8cf525dacd91d58f12068e80a81ac34f61
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c be5af440f3192c58681b5d43167dbca3ccbfce394d89faa22378a14264781136
F src/main.c 035be2e9ba2a0fc1701a8ab1880af3001a968a24556433538a6c073558ee4341
F src/main.c 09bc5191f75dc48fc4dfddda143cb864c0c3dbc3297eb9a9c8e01fea58ff847d
F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -607,7 +604,7 @@ F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
F src/memdb.c 559c42e61eb70cd6d4bc692b042497133c6d96c09a3d514d92f3dac72268e223
F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
@@ -620,7 +617,7 @@ F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c 1b3ddb7814c4bf37f494c04d2ab30c1ced5b2c927267e1930ce7cd388787a96d
F src/os_win.c 2b2411279f7b24f927591561303fc5871845732df42641cbf695c23640b16975
F src/os_win.c 295fe45f18bd86f2477f4cd79f3377c6f883ceb941b1f46808665c73747f2345
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 9d36ddedc842e993c88c222ed914822dbd6f8ece3c648fde04468637012a034a
F src/pager.h f82e9844166e1585f5786837ddc7709966138ced17f568c16af7ccf946c2baa3
@@ -636,11 +633,11 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 3e53e02ce87c9582bd7e7d22f13f4094a271678d9dc72820fa257a2abb5e4032
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c f879cef11c462a2c37a8c906932781e384c3bb32042c355a704a043029c90d27
F src/shell.c.in 2c462effd2cc970bd528c7dd5bc740b4ea24dac62c8269f00aed1901335ba39b
F src/sqlite.h.in d6b0b83b2deab8f92ef7cc6f6fb94fa59d21c59f7b55f4c693bfff161ce42238
F src/shell.c.in e4762c17316110d4b65afac3572a4d134539a4178ac2afe4821de23f509a728f
F src/sqlite.h.in 4fff9c6cc5d4cbba9532a668112efb6dc469c425e1a2196664d7c07d508363ef
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
F src/sqliteInt.h ef0268eeba1449170d5967493a3f6b720344cd6f461c3430299c00d51da74d9d
F src/sqliteInt.h bf15f7db635d2e64a227bbf86845bc19755dbd932021a6461d6dd15b0da2cfd3
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -703,15 +700,15 @@ F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
F src/update.c 3f4fb5ad7c9b48d7911974d6579192bb3a6c27f46140b6cbb9139cc8a77b8691
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c d4bcb560471cd94e6e17d448311f8d5bf81a7e5276295a53501058ef1b95dd1a
F src/util.c b1d8d87c4c8c77e70f48c43f91444fd66d91532693573b70b837afd572010176
F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd
F src/vdbe.c 94d5520d2a287216c47e6fb641ee88ffd934b0d40c235d693d38bcd0e0750357
F src/vdbe.c a6c52ba65e8ceb574fe0eda62af84e6c50c176ffc5f310c613425f7ab2b1484b
F src/vdbe.h 637ae853b7d42ae3951034cc63ab7c8af837861f79504cdb5399552fcd89a884
F src/vdbeInt.h a4147a4ddf613cb1bcb555ace9e9e74a9c099d65facd88155f191b1fb4d74cfb
F src/vdbeapi.c b4982cde547054c4f7341198db3c3008a48e1eb028f757601bf5bf2fc026cbcf
F src/vdbeapi.c 1a95162e26d5eda3b7b46fbe4fcbc33eb7f801529d66fc2e14c52094a5523339
F src/vdbeaux.c 6ee48db408d4c297a363f1e31145c09793a580e7c508bb36063dd017d67117a2
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
F src/vdbemem.c 1cac4028c0dabbf1f3259f107440e2780e05ac9fe419e9709e6eb4e166ba714b
F src/vdbemem.c 1d9a0f37b0097fbb53f0d7ba081f7181b83cee2c6f46364706ea0c3896bd8ec0
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac
@@ -720,7 +717,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 3f4ac276a60bda76f9f1f6f1c2c38599bacd4987e5efcd3f7fed2647bf97280a
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c f69d94f34e1c523cd9b66041e4afe015cad29888617f3c09a2a5bc36018917d0
F src/where.c ef9e644d1d76e86f68c941eb05d30a98fc0811eeef2a110906d81fedde81b6bf
F src/whereInt.h e25203e5bfee149f5f1225ae0166cfb4f1e65490c998a024249e98bb0647377c
F src/wherecode.c 85790d7e5365ac41085713331ce52e4343586ad3d37d218ffe00572357baa62b
F src/whereexpr.c 1dfda1695e4480c24248157df55bb4d66c732dc8d14ac16b4f076bb15de93d63
@@ -1230,7 +1227,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
F test/join.test aea7a4f55b2d9eb8ef3434ea78f55b15bd688ab6136a11105c9c52f77424f199
F test/join.test ed1daf99958fed1b9f017e56bae2bb6b49339a1ec0b70b9e8f7259960c6bf387
F test/join2.test 8561fe82ce434ac96de91544072e578dc2cadddf2d9bc9cd802f866a9b92502e
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -1245,24 +1242,18 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test 705157cf9b9b7c207caf960812a7d0e4dc1dd45aa5fb2b563f12df59088645f3
F test/joinH.test 15f501b33d848521964afde9865a92aeca79c8c41fa84dc4dc3f865c9ed8c868
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
F test/jrnlmode.test 9b5bc01dac22223cb60ec2d5f97acf568d73820794386de5634dcadbea9e1946
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json/README.md 506af1f54574b524106acb50d1a341ab5ddfa6d83fe25095007892b07e663e85
F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f
F test/json/json-q1.txt 335a7c8ab291d354f33b7decc9559e99a2823d4142291c4be7aa339a631f3c2d
F test/json/json-speed-check.sh 8b7babf530faa58bd59d6d362cec8e9036a68c5457ff46f3b1f1511d21af6737 x
F test/json101.test ff8024cbb8092e723237648cea9bdbd51f31476b5015a4df3a5ecc8a5efda837
F test/json102.test 13dc9e7b7f359ecb861e02f9bd7019f7342a63d1c354273b0a8f3904050560a8
F test/json101.test c7707ee623c57a24845ef260d4388a6fade1eb294e450caadd7f1d9ced19dea7
F test/json102.test 327e77275f338c028faefa2da5164daf6b142a165e3015ff2a6e4251ddc6a0ac
F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
F test/json104.test a502dc01853aada95d721b3b275afbe2dc18fffdac1fea6e96fb20c13586bbb5
F test/json105.test 11670a4387f4308ae0318cadcbd6a918ea7edcd19fbafde020720a073952675d
F test/json501.test f71710f60fa45b19dc336fbaac9e8362f70f80cf81badefdb845ed3f7c7c2ccc
F test/json502.test 66d150cc098674b8bf4354526a8dd411b926f43ca892306bcb3b6d3f93fef7be
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c feb4358fb022da8ebd098c45811f2f6507688bb6c43aa72b3e840df19026317b
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
@@ -1325,7 +1316,7 @@ F test/minmax.test fe638b55d77d2375531a8f549b338eafcd9adfbd2f72df37ed77d9b26ca0a
F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87
F test/misc1.test 8d138a4926ab90617c1aa29ce26e7785ae2b83a4d3a195d543b7374e05589dd1
F test/misc1.test 9955e70cab5e284d77e358cfa1f1dd43f5e4bc00a421018581b0fbd62206a6a1
F test/misc2.test 71e746af479119386ac2ed7ab7d81d99970e75b49ffd3e8efffee100b4b5f350
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
@@ -1500,8 +1491,8 @@ F test/sharedA.test 64bdd21216dda2c6a3bd3475348ccdc108160f34682c97f2f51c19fc0e21
F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 300b77328aaafb9f3e7a53a26e4162fbf92181d92251d259ff105a2275ff998d
F test/shell2.test 09a202f57e7cd99788537f763e0845796a173fcea06a0d199a08d69446fe1daf
F test/shell1.test 291c5c4b313adbe44d847af78b730a3bbfa1598c450e09ffe5601170bf7f28e7
F test/shell2.test 35c0c19d3198ee7669a748c1aedcce27a776ee575cc76128f8fcf665b79672f7
F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
F test/shell4.test 9abd0c12a7e20a4c49e84d5be208d2124fa6c09e728f56f1f4bee0f02853935f
F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
@@ -1573,7 +1564,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test 54f27eacd054aa528a8b6e3331192c484104f30aaee351ad035f2b39a00f87c4
F test/tabfunc01.test 668e5e39108ce84b2f24e402f9382daecc0417edb9c78c6c8f58170584e80c91
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -2068,11 +2059,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P aac8ac631de5c5b439c48c13f5fd271d76c11b1a5fd0919dfe4506ef7725f5ab
R 61a0707faa27c9f2a615e39c3eb91b1c
T *branch * cli-hex-escape
T *sym-cli-hex-escape *
T -sym-trunk *
U larrybr
Z fb17004bd6ff087d69821cbf74a7ae8f
P 50e8a30be1a8d4af42a2c58bdffcf3c4eae00450f0bb9ec39548d5a52d2a68ee
R ef7db804b2d3b6c0c526bc82af548b3d
U dan
Z 41e485964a37c8d7a0bf6a892dd19281
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
90e434a6ae370a35109802fc336b98298d345f3d23125ef2cc68c31d8e69bb50
f94f3da5de2b1085ea1967ca8961a923e79f5a1181b9507a2f4c9e29e47cbe29
+1 -1
View File
@@ -7628,7 +7628,7 @@ static int pageFreeArray(
}
}
if( j>=nFree ){
if( nFree>=(int)(sizeof(aOfst)/sizeof(aOfst[0])) ){
if( nFree>=sizeof(aOfst)/sizeof(aOfst[0]) ){
for(j=0; j<nFree; j++){
freeSpace(pPg, aOfst[j], aAfter[j]-aOfst[j]);
}
+1 -1
View File
@@ -172,7 +172,7 @@
** byte are used. The integer consists of all bytes that have bit 8 set and
** the first byte with bit 8 clear. The most significant byte of the integer
** appears first. A variable-length integer may not be more than 9 bytes long.
** As a special case, all 8 bits of the 9th byte are used as data. This
** As a special case, all 8 bytes of the 9th byte are used as data. This
** allows a 64-bit integer to be encoded in 9 bytes.
**
** 0x00 becomes 0x00000000
+10 -13
View File
@@ -1113,9 +1113,9 @@ Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
** Join two expressions using an AND operator. If either expression is
** NULL, then just return the other expression.
**
** If one side or the other of the AND is known to be false, and neither side
** is part of an ON clause, then instead of returning an AND expression,
** just return a constant expression with a value of false.
** If one side or the other of the AND is known to be false, then instead
** of returning an AND expression, just return a constant expression with
** a value of false.
*/
Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
sqlite3 *db = pParse->db;
@@ -1123,17 +1123,14 @@ Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
return pRight;
}else if( pRight==0 ){
return pLeft;
}else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
&& !IN_RENAME_OBJECT
){
sqlite3ExprDeferredDelete(pParse, pLeft);
sqlite3ExprDeferredDelete(pParse, pRight);
return sqlite3Expr(db, TK_INTEGER, "0");
}else{
u32 f = pLeft->flags | pRight->flags;
if( (f&(EP_OuterON|EP_InnerON|EP_IsFalse))==EP_IsFalse
&& !IN_RENAME_OBJECT
){
sqlite3ExprDeferredDelete(pParse, pLeft);
sqlite3ExprDeferredDelete(pParse, pRight);
return sqlite3Expr(db, TK_INTEGER, "0");
}else{
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
}
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
}
}
+1 -1
View File
@@ -97,7 +97,7 @@ const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne];
** isalnum() 0x06
** isxdigit() 0x08
** toupper() 0x20
** SQLite identifier character 0x40 $, _, or non-ascii
** SQLite identifier character 0x40
** Quote character 0x80
**
** Bit 0x20 is set if the mapped character requires translation to upper
+180 -799
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -3933,7 +3933,7 @@ int sqlite3_sleep(int ms){
/* This function works in milliseconds, but the underlying OsSleep()
** API uses microseconds. Hence the 1000's.
*/
rc = (sqlite3OsSleep(pVfs, ms<0 ? 0 : 1000*ms)/1000);
rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000);
return rc;
}
-4
View File
@@ -38,8 +38,4 @@
#define SQLITE_4_BYTE_ALIGNED_MALLOC
#endif /* defined(_MSC_VER) && !defined(_WIN64) */
#if !defined(HAVE_LOG2) && defined(_MSC_VER) && _MSC_VER<1800
#define HAVE_LOG2 0
#endif /* !defined(HAVE_LOG2) && defined(_MSC_VER) && _MSC_VER<1800 */
#endif /* SQLITE_MSVC_H */
+3 -10
View File
@@ -5197,7 +5197,7 @@ static int winOpen(
if( isReadWrite ){
int rc2, isRO = 0;
sqlite3BeginBenignMalloc();
rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
sqlite3EndBenignMalloc();
if( rc2==SQLITE_OK && isRO ) break;
}
@@ -5214,7 +5214,7 @@ static int winOpen(
if( isReadWrite ){
int rc2, isRO = 0;
sqlite3BeginBenignMalloc();
rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
sqlite3EndBenignMalloc();
if( rc2==SQLITE_OK && isRO ) break;
}
@@ -5234,7 +5234,7 @@ static int winOpen(
if( isReadWrite ){
int rc2, isRO = 0;
sqlite3BeginBenignMalloc();
rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
sqlite3EndBenignMalloc();
if( rc2==SQLITE_OK && isRO ) break;
}
@@ -5457,13 +5457,6 @@ static int winAccess(
OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
zFilename, flags, pResOut));
if( zFilename==0 ){
*pResOut = 0;
OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
zFilename, pResOut, *pResOut));
return SQLITE_OK;
}
zConverted = winConvertFromUtf8Filename(zFilename);
if( zConverted==0 ){
OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
+10 -28
View File
@@ -994,7 +994,6 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
fflush(stdout);
do{
zResult = local_getline(zPrior, stdin);
zPrior = 0;
/* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
if( zResult==0 ) sqlite3_sleep(50);
}while( zResult==0 && seenInterrupt>0 );
@@ -1861,7 +1860,6 @@ static void output_quoted_string(FILE *out, const char *z){
int i;
char c;
setBinaryMode(out, 1);
if( z==0 ) return;
for(i=0; (c = z[i])!=0 && c!='\''; i++){}
if( c==0 ){
utf8_printf(out,"'%s'",z);
@@ -3567,14 +3565,10 @@ static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
if( rc==SQLITE_OK && pQ && sqlite3_step(pQ)==SQLITE_ROW ){
sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
#ifdef NAN
}else if( sqlite3_strlike("_NAN", zVar, 0)==0 ){
sqlite3_bind_double(pStmt, i, NAN);
#endif
#ifdef INFINITY
}else if( sqlite3_strlike("_INF", zVar, 0)==0 ){
sqlite3_bind_double(pStmt, i, INFINITY);
#endif
}else{
sqlite3_bind_null(pStmt, i);
}
@@ -5001,10 +4995,10 @@ static int showHelp(FILE *out, const char *zPattern){
** Otherwise => whole help for documented commands
*/
enum HelpWanted hw = HW_SummaryOnly;
enum HelpHave hh = HH_More;
if( zPattern!=0 ){
hw = (*zPattern=='0')? HW_NoCull|HW_Undoc : HW_NoCull;
}
enum HelpHave hh = HH_More;
for(i=0; i<ArraySize(azHelp); i++){
switch( azHelp[i][0] ){
case ',':
@@ -5599,7 +5593,6 @@ static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
** \' -> '
** \\ -> backslash
** \NNN -> ascii character NNN in octal
** \xHH -> ascii character HH in hexadecimal
*/
static void resolve_backslashes(char *z){
int i, j;
@@ -5628,15 +5621,6 @@ static void resolve_backslashes(char *z){
c = '\'';
}else if( c=='\\' ){
c = '\\';
}else if( c=='x' ){
int nhd = 0, hdv;
u8 hv = 0;
while( nhd<2 && (c=z[i+1+nhd])!=0 && (hdv=hexDigitValue(c))>=0 ){
hv = (u8)((hv<<4)|hdv);
++nhd;
}
i += nhd;
c = (u8)hv;
}else if( c>='0' && c<='7' ){
c -= '0';
if( z[i+1]>='0' && z[i+1]<='7' ){
@@ -5768,7 +5752,7 @@ static int sql_trace_callback(
break;
}
case SQLITE_TRACE_PROFILE: {
sqlite3_int64 nNanosec = pX ? *(sqlite3_int64*)pX : 0;
sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
break;
}
@@ -5844,8 +5828,8 @@ static void import_append_char(ImportCtx *p, int c){
*/
static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
int c;
int cSep = (u8)p->cColSep;
int rSep = (u8)p->cRowSep;
int cSep = p->cColSep;
int rSep = p->cRowSep;
p->n = 0;
c = fgetc(p->in);
if( c==EOF || seenInterrupt ){
@@ -5934,8 +5918,8 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
*/
static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
int c;
int cSep = (u8)p->cColSep;
int rSep = (u8)p->cRowSep;
int cSep = p->cColSep;
int rSep = p->cRowSep;
p->n = 0;
c = fgetc(p->in);
if( c==EOF || seenInterrupt ){
@@ -8816,8 +8800,8 @@ static int do_meta_command(char *zLine, ShellState *p){
" for import\n");
goto meta_command_exit;
}
sCtx.cColSep = (u8)p->colSeparator[0];
sCtx.cRowSep = (u8)p->rowSeparator[0];
sCtx.cColSep = p->colSeparator[0];
sCtx.cRowSep = p->rowSeparator[0];
}
sCtx.zFile = zFile;
sCtx.nLine = 1;
@@ -9203,8 +9187,7 @@ static int do_meta_command(char *zLine, ShellState *p){
const char *zFile, *zProc;
char *zErrMsg = 0;
failIfSafeMode(p, "cannot run .load in safe mode");
if( nArg<2 || azArg[1][0]==0 ){
/* Must have a non-empty FILE. (Will not load self.) */
if( nArg<2 ){
raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
rc = 1;
goto meta_command_exit;
@@ -10529,8 +10512,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( bDebug ) utf8_printf(p->out, "%s\n", zRevText);
lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0);
if( lrc!=SQLITE_OK ){
/* assert(lrc==SQLITE_NOMEM); // might also be SQLITE_ERROR if the
** user does cruel and unnatural things like ".limit expr_depth 0". */
assert(lrc==SQLITE_NOMEM);
rc = 1;
}else{
if( zLike ) sqlite3_bind_text(pStmt,1,zLike,-1,SQLITE_STATIC);
+13 -32
View File
@@ -2398,7 +2398,7 @@ struct sqlite3_mem_methods {
** </dd>
**
** [[SQLITE_DBCONFIG_DQS_DML]]
** <dt>SQLITE_DBCONFIG_DQS_DML</dt>
** <dt>SQLITE_DBCONFIG_DQS_DML</td>
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
** the legacy [double-quoted string literal] misfeature for DML statements
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
@@ -2407,7 +2407,7 @@ struct sqlite3_mem_methods {
** </dd>
**
** [[SQLITE_DBCONFIG_DQS_DDL]]
** <dt>SQLITE_DBCONFIG_DQS_DDL</dt>
** <dt>SQLITE_DBCONFIG_DQS_DDL</td>
** <dd>The SQLITE_DBCONFIG_DQS option activates or deactivates
** the legacy [double-quoted string literal] misfeature for DDL statements,
** such as CREATE TABLE and CREATE INDEX. The
@@ -2416,7 +2416,7 @@ struct sqlite3_mem_methods {
** </dd>
**
** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</dt>
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
** assume that database schemas are untainted by malicious content.
** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
@@ -2436,7 +2436,7 @@ struct sqlite3_mem_methods {
** </dd>
**
** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt>
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>
** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
** the legacy file format flag. When activated, this flag causes all newly
** created database file to have a schema format version number (the 4-byte
@@ -2445,7 +2445,7 @@ struct sqlite3_mem_methods {
** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
** newly created databases are generally not understandable by SQLite versions
** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there
** is now scarcely any need to generate database files that are compatible
** is now scarcely any need to generated database files that are compatible
** all the way back to version 3.0.0, and so this setting is of little
** practical use, but is provided so that SQLite can continue to claim the
** ability to generate new database files that are compatible with version
@@ -2458,35 +2458,23 @@ struct sqlite3_mem_methods {
** </dd>
**
** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]
** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt>
** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</td>
** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in
** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears
** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()
** statistics. For statistics to be collected, the flag must be set on
** the database handle both when the SQL statement is prepared and when it
** is stepped. The flag is set (collection of statistics is enabled)
** by default. This option takes two arguments: an integer and a pointer to
** an integer.. The first argument is 1, 0, or -1 to enable, disable, or
** leave unchanged the statement scanstatus option. If the second argument
** is not NULL, then the value of the statement scanstatus setting after
** processing the first argument is written into the integer that the second
** argument points to.
** </dd>
** by default.</dd>
**
** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]]
** <dt>SQLITE_DBCONFIG_REVERSE_SCANORDER</dt>
** <dd>The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order
** <dt>SQLITE_DBCONFIG_REVERSE_SCANORDER</td>
** <dd>The SQLITE_DBCONFIG_REVERSE_SCANORDER option change the default order
** in which tables and indexes are scanned so that the scans start at the end
** and work toward the beginning rather than starting at the beginning and
** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
** same as setting [PRAGMA reverse_unordered_selects]. This option takes
** two arguments which are an integer and a pointer to an integer. The first
** argument is 1, 0, or -1 to enable, disable, or leave unchanged the
** reverse scan order flag, respectively. If the second argument is not NULL,
** then 0 or 1 is written into the integer that the second argument points to
** depending on if the reverse scan order flag is set after processing the
** first argument.
** </dd>
** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
** same as setting [PRAGMA reverse_unordered_selects]. This configuration option
** is useful for application testing.</dd>
**
** </dl>
*/
@@ -2508,7 +2496,7 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */
#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */
#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */
#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */
#define SQLITE_DBCONFIG_MAX 1019 /* Largest DBCONFIG */
@@ -6255,13 +6243,6 @@ void sqlite3_activate_cerod(
** of the default VFS is not implemented correctly, or not implemented at
** all, then the behavior of sqlite3_sleep() may deviate from the description
** in the previous paragraphs.
**
** If a negative argument is passed to sqlite3_sleep() the results vary by
** VFS and operating system. Some system treat a negative argument as an
** instruction to sleep forever. Others understand it to mean do not sleep
** at all. ^In SQLite version 3.42.0 and later, a negative
** argument passed into sqlite3_sleep() is changed to zero before it is relayed
** down into the xSleep method of the VFS.
*/
int sqlite3_sleep(int);
+1 -5
View File
@@ -294,7 +294,7 @@
# define SQLITE_NOINLINE
# define SQLITE_INLINE
#endif
#if defined(SQLITE_COVERAGE_TEST) || defined(__STRICT_ANSI__)
#if defined(SQLITE_COVERAGE_TEST)
# undef SQLITE_INLINE
# define SQLITE_INLINE
#endif
@@ -4456,8 +4456,6 @@ int sqlite3CantopenError(int);
# define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
# define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
# define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80)
# define sqlite3JsonId1(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x42)
# define sqlite3JsonId2(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x46)
#else
# define sqlite3Toupper(x) toupper((unsigned char)(x))
# define sqlite3Isspace(x) isspace((unsigned char)(x))
@@ -4467,8 +4465,6 @@ int sqlite3CantopenError(int);
# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
# define sqlite3Tolower(x) tolower((unsigned char)(x))
# define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`')
# define sqlite3JsonId1(x) (sqlite3IsIdChar(x)&&(x)<'0')
# define sqlite3JsonId2(x) sqlite3IsIdChar(x)
#endif
int sqlite3IsIdChar(u8);
+1 -3
View File
@@ -843,9 +843,7 @@ int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
u = u*16 + sqlite3HexToInt(z[k]);
}
memcpy(pOut, &u, 8);
if( k-i>16 ) return 2;
if( z[k]!=0 ) return 1;
return 0;
return (z[k]==0 && k-i<=16) ? 0 : 2;
}else
#endif /* SQLITE_OMIT_HEX_INTEGER */
{
+2 -2
View File
@@ -2745,7 +2745,7 @@ case OP_IfNullRow: { /* jump */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
if( pC && pC->nullRow ){
if( ALWAYS(pC) && pC->nullRow ){
sqlite3VdbeMemSetNull(aMem + pOp->p3);
goto jump_to_p2;
}
@@ -3240,7 +3240,7 @@ case OP_Affinity: {
}else{
pIn1->u.r = (double)pIn1->u.i;
pIn1->flags |= MEM_Real;
pIn1->flags &= ~(MEM_Int|MEM_Str);
pIn1->flags &= ~MEM_Int;
}
}
REGISTER_TRACE((int)(pIn1-aMem), pIn1);
+2 -3
View File
@@ -1337,9 +1337,9 @@ static const void *columnName(
assert( db!=0 );
n = sqlite3_column_count(pStmt);
if( N<n && N>=0 ){
u8 prior_mallocFailed = db->mallocFailed;
N += useType*n;
sqlite3_mutex_enter(db->mutex);
assert( db->mallocFailed==0 );
#ifndef SQLITE_OMIT_UTF16
if( useUtf16 ){
ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]);
@@ -1351,8 +1351,7 @@ static const void *columnName(
/* A malloc may have failed inside of the _text() call. If this
** is the case, clear the mallocFailed flag and return NULL.
*/
assert( db->mallocFailed==0 || db->mallocFailed==1 );
if( db->mallocFailed > prior_mallocFailed ){
if( db->mallocFailed ){
sqlite3OomClear(db);
ret = 0;
}
-1
View File
@@ -157,7 +157,6 @@ int sqlite3VdbeMemValidStrRep(Mem *p){
char *z;
int i, j, incr;
if( (p->flags & MEM_Str)==0 ) return 1;
if( p->db && p->db->mallocFailed ) return 1;
if( p->flags & MEM_Term ){
/* Insure that the string is properly zero-terminated. Pay particular
** attention to the case where p->n is odd */
+11 -34
View File
@@ -5982,45 +5982,22 @@ WhereInfo *sqlite3WhereBegin(
}
if( pParse->nErr ) goto whereBeginError;
/* The False-WHERE-Term-Bypass optimization:
/* Special case: WHERE terms that do not refer to any tables in the join
** (constant expressions). Evaluate each such term, and jump over all the
** generated code if the result is not true.
**
** If there are WHERE terms that are false, then no rows will be output,
** so skip over all of the code generated here.
** Do not do this if the expression contains non-deterministic functions
** that are not within a sub-select. This is not strictly required, but
** preserves SQLite's legacy behaviour in the following two cases:
**
** Conditions:
**
** (1) The WHERE term must not refer to any tables in the join.
** (2) The term must not come from an ON clause on the
** right-hand side of a LEFT or FULL JOIN.
** (3) The term must not come from an ON clause, or there must be
** no RIGHT or FULL OUTER joins in pTabList.
** (4) If the expression contains non-deterministic functions
** that are not within a sub-select. This is not required
** for correctness but rather to preserves SQLite's legacy
** behaviour in the following two cases:
**
** WHERE random()>0; -- eval random() once per row
** WHERE (SELECT random())>0; -- eval random() just once overall
**
** Note that the Where term need not be a constant in order for this
** optimization to apply, though it does need to be constant relative to
** the current subquery (condition 1). The term might include variables
** from outer queries so that the value of the term changes from one
** invocation of the current subquery to the next.
** FROM ... WHERE random()>0; -- eval random() once per row
** FROM ... WHERE (SELECT random())>0; -- eval random() once overall
*/
for(ii=0; ii<sWLB.pWC->nBase; ii++){
WhereTerm *pT = &sWLB.pWC->a[ii]; /* A term of the WHERE clause */
Expr *pX; /* The expression of pT */
WhereTerm *pT = &sWLB.pWC->a[ii];
if( pT->wtFlags & TERM_VIRTUAL ) continue;
pX = pT->pExpr;
assert( pX!=0 );
assert( pT->prereqAll!=0 || !ExprHasProperty(pX, EP_OuterON) );
if( pT->prereqAll==0 /* Conditions (1) and (2) */
&& (nTabList==0 || exprIsDeterministic(pX)) /* Condition (4) */
&& !(ExprHasProperty(pX, EP_InnerON) /* Condition (3) */
&& (pTabList->a[0].fg.jointype & JT_LTORJ)!=0 )
){
sqlite3ExprIfFalse(pParse, pX, pWInfo->iBreak, SQLITE_JUMPIFNULL);
if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){
sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL);
pT->wtFlags |= TERM_CODED;
}
}
-18
View File
@@ -1245,22 +1245,4 @@ do_eqp_test join-28.2 {
# |--SCAN t4
# `--SEARCH t3 USING AUTOMATIC COVERING INDEX (a=?)
# 2023-05-01 https://sqlite.org/forum/forumpost/96cd4a7e9e
#
reset_db
db null NULL
do_execsql_test join-29.1 {
CREATE TABLE t0(a INT); INSERT INTO t0(a) VALUES (1);
CREATE TABLE t1(b INT); INSERT INTO t1(b) VALUES (2);
CREATE VIEW v2(c) AS SELECT 3 FROM t1;
SELECT * FROM t1 JOIN v2 ON 0 FULL OUTER JOIN t0 ON true;
} {NULL NULL 1}
do_execsql_test join-29.2 {
SELECT * FROM t1 JOIN v2 ON 1=0 FULL OUTER JOIN t0 ON true;
} {NULL NULL 1}
do_execsql_test join-29.3 {
SELECT * FROM t1 JOIN v2 ON false FULL OUTER JOIN t0 ON true;
} {NULL NULL 1}
finish_test
-30
View File
@@ -89,35 +89,5 @@ do_execsql_test 4.4 {
SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33);
} {1}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.0 {
CREATE TABLE t0(w);
CREATE TABLE t1(x);
CREATE TABLE t2(y);
CREATE TABLE t3(z);
INSERT INTO t3 VALUES('t3val');
}
do_execsql_test 5.1 {
SELECT * FROM t1 INNER JOIN t2 ON (0) RIGHT OUTER JOIN t3;
} {{} {} t3val}
do_execsql_test 5.2 {
SELECT * FROM t1 INNER JOIN t2 ON (0) FULL OUTER JOIN t3;
} {{} {} t3val}
do_execsql_test 5.3 {
SELECT * FROM t3 LEFT JOIN t2 ON (0);
} {t3val {}}
do_execsql_test 5.4 {
SELECT * FROM t0 RIGHT JOIN t1 INNER JOIN t2 ON (0) RIGHT JOIN t3
} {{} {} {} t3val}
do_execsql_test 5.5 {
SELECT * FROM t0 RIGHT JOIN t1 INNER JOIN t2 ON (0)
} {}
finish_test
-27
View File
@@ -1,27 +0,0 @@
The files in this subdirectory are used to help measure the performance
of the SQLite JSON parser.
# 1.0 Prerequisites
1. Valgrind
2. Fossil
# 2.0 Setup
1. Run: "`tclsh json-generator.tcl | sqlite3 json100mb.db`" to create
the 100 megabyte test database. Do this so that the "json100mb.db"
file lands in the directory from which you will run tests, not in
the test/json subdirectory of the source tree.
2. Build the baseline sqlite3.c file. ("`make sqlite3.c`")
3. Run "`sh json-speed-check-1.sh trunk`". This creates the baseline
profile in "jout-trunk.txt".
# 3.0 Testing
1. Build the sqlite3.c to be tested.
2. Run "`sh json-speed-check-1.sh x1`". The profile output will appear
in jout-x1.txt. Substitute any label you want in place of "x1".
-401
View File
@@ -1,401 +0,0 @@
#!/usr/bin/tclsh
#
# Generate SQL that will populate an SQLite database with about 100 megabytes
# of pseudo-random JSON text.
#
# tclsh json-generator.tcl | sqlite3 json110mb.db
#
# srand() is used to initialize the random seed so that the same JSON
# is generated for every run.
#
expr srand(12345678)
set wordlist {
ability able abroad access account act
action active actor add address adept
adroit advance advice affect age ageless
agency agent agile agree air airfare
airline airport alert almond alpha always
amend amount amplify analyst anchor angel
angelic angle ankle annual answer antique
anybody anyhow appeal apple apricot apt
area argon arm army arrival arsenic
art artful article arugula aside ask
aspect assist assume atom atone attempt
author autumn average avocado award awl
azure back bacon bag bagel bake
baker balance ball balloon bamboo banana
band banjo bank barium base basil
basin basis basket bass bat bath
battery beach beak bean bear bearcub
beauty beef beet beige being bell
belly belt bench bend benefit best
beta better beyond bicycle bid big
bike bill bird biscuit bismuth bisque
bit black blank blest blind bliss
block bloom blue board boat body
bokchoy bone bonus book bookish boot
border boron boss bossy bottle bottom
bow bowl bowtie box brain brainy
branch brave bravely bread break breath
breezy brick bridge brie brief briefly
bright broad broil bromine bronze brother
brow brown brush buddy budget buffalo
bug bugle bull bunch burger burly
burrito bus busy butter button buy
buyer byte cab cabbage cabinet cable
cadet cadmium caesium cake calcium caliper
call caller calm calmly camera camp
can canary cancel candle candy cap
capable caper capital captain car carbon
card care career careful carp carpet
carrot carry case cash cassava casual
cat catch catfish catsear catsup cause
cave celery cell century chain chair
chalk chance change channel chapter chard
charge charity chart check cheddar cheery
cheese chicken chicory chiffon child chin
chip chives choice chowder chum church
circle city claim clam class classic
classy clay clean cleaner clear clearly
clerk click client climate clock clorine
closet clothes cloud clown club clue
cluster coach coast coat cobbler cobolt
cod code coffee colby cold collar
college comb combine comet comfort command
comment common company complex concept concern
concert conduit consist contact contest context
control convert cook cookie copilot copper
copy coral cordial corn corner corny
correct cost count counter country county
couple courage course court cover cow
cowbird crab crack craft crash crazy
cream credit creek cress crevice crew
crimson croaker crop cross crowd cube
cuckoo cuisine culture cup current curve
cut cyan cycle dagger daily dance
dare darter data date day daylily
deal dear dearly debate debit decade
decimal deep deft deftly degree delay
deluxe deposit depth design desk detail
device dew diamond diet dig dill
dinner dip direct dirt dish disk
display diver divide divine doctor dodger
donut door dot double dough draft
drag dragon drama draw drawer drawing
dream drill drink drive driver drop
drum dry dryer drywall duck due
dump dusk dust duty dye eagle
ear earring earth ease east easy
eat economy edge editor eel effect
effort egg eight elbow elegant element
elf elk email emerald employ end
endive endless energy engine enjoy enter
entry equal equip error escape essay
eternal evening event exam example excuse
exit expert extent extreme eye face
fact factor factual fail failure fair
fajita fall family fan fang farm
farmer fat fault feature feed feel
feeling fench fennel festive few fiber
field fig figure file fill film
filter final finance finding finger finish
fire fish fishing fit fitting five
fix flier flight floor floral florine
flour flow flower fly flying focus
fold folding food foot force forest
forever forgive form formal format fortune
forum frame free freedom freely fresh
friend frog front fruit fuchsia fuel
fun funny future gain galaxy gallium
game gamma gap garage garden garlic
gas gate gather gauge gear gem
gene general gentle gently gherkin ghost
gift give glad glass gleeful glossy
glove glue goal goat goby gold
goldeye golf good gouda goulash gourd
grab grace grade gram grand grape
grapes grass gravy gray great green
grits grocery ground group grouper grout
growth guard guave guess guest guide
guitar gumbo guppy habit hacksaw haddock
hafnium hagfish hair half halibut hall
hammer hand handle handy hanger happy
hat havarti hay haybale head health
healthy hearing heart hearty heat heavy
heel height helium hello help helpful
herald herring hide high highly highway
hill hip hipster hire history hit
hoki hold hole holiday holly home
honest honey hook hope hopeful horizon
horn horse host hotel hour house
housing human humane humor hunt hurry
ice icecube icefish icy idea ideal
image impact impress inch income indigo
initial inkpen insect inside intense invite
iodine iridium iron island issue item
ivory jacket jargon javelin jello jelly
jewel job jocund join joint joke
jovial joy joyful joyous judge juice
jump junior jury just justice kale
keel keep kelp ketchup key keyhole
keyway khaki kick kid kidney kiloohm
kind kindly king kitchen kite kiwi
knee knife krill krypton kumquat lab
lace lack ladder lake lamp lamprey
land laser laugh law lawn lawyer
layer lead leader leading leaf leafy
league leather leave lecture leek leg
lemon length lentil lesson let letter
lettuce level library life lift light
lily lime limit line linen link
lip list listen lithium lively living
lizard load loan lobster local lock
log long longfin look lotus love
lovely loving low lucid luck luffa
lunch lung machine magenta magnet mail
main major make mall manager mango
manner many map march market maroon
martian master match math matter maximum
maybe meal meaning meat media medium
meet meeting melody melon member memory
mention menu mercury merry mess message
messy metal meter method micron middle
might mile milk mind mine minimum
minnow minor mint minute mirror miss
mission misty mix mixer mixture mobile
mode model moment monitor monk month
moon moray morning most motor mouse
mouth move mover movie much mud
mudfish muffin mullet munster muon muscle
music mustard nail name nation native
natural nature navy neat neatly nebula
neck needle neon nerve net network
neutron news nibble nice nickel night
niobium nobody noise noodle normal north
nose note nothing notice nova novel
number nurse nursery oar object offer
office officer oil okay okra old
olive one onion open opening opinion
option orange orbit orchid order oregano
other ounce outcome outside oven owner
oxygen oyster pace pack package page
pager paint pair pale pan pancake
papaya paper pardon parent park parking
parsley parsnip part partner party pass
passage past pasta path patient pattern
pause pay pea peace peach peacock
peahen peak peanut pear pearl pen
penalty pencil pension people pepper perch
perfect period permit person phase phone
photo phrase physics piano pick picture
pie piece pigeon pike pilot pin
pink pinkie pious pipe pitch pizza
place plan plane planet plant planter
plastic plate play player playful plenty
pliers plum pod poem poet poetry
point police policy pollock pony pool
pop popover poptart pork port portal
post pot potato pound powder power
present press price pride primary print
prior private prize problem process produce
product profile profit program project promise
prompt proof proper protein proton public
puff puffer pull pumpkin pup pupfish
pure purple purpose push put quality
quark quarter quiet quill quit quote
rabbit raccoon race radiant radio radish
radium radon rain rainbow raise ramp
ranch range rasp rate ratio ray
razor reach read reading real reality
reason recipe record recover red redeem
reed reef refuse region regret regular
relaxed release relief relish remote remove
rent repair repeat reply report request
reserve resist resolve resort rest result
return reveal review reward ribbon rice
rich ride ridge right ring rise
risk river rivet road roast rock
rocket role roll roof room rope
rose rough roughy round row royal
rub ruby rudder ruin rule run
runner rush rust sacred saddle safe
safety sail salad salami sale salmon
salt sample sand sander sandy sauce
save saving saw scale scampi scene
scheme school score screen script sea
search season seat second secret sector
seemly self sell senate senior sense
series serve set shake shape share
shark shell shift shine shiny ship
shock shoe shoot shop shovel show
side sign signal silk silly silver
simple sing singer single sink site
size skill skin sky slate sleep
sleepy slice slide slip smart smell
smelt smile smoke smooth snap snipe
snow snowy sock socket sodium soft
softly soil sole solid song sorrel
sort soul sound soup source south
space spare speech speed spell spend
sphere spice spider spirit spite split
spoon sport spot spray spread spring
squab square squash stable staff stage
stand staple star start state status
stay steak steel step stern stew
stick still stock stone stop store
storm story strain street stress strike
string stroke strong studio study stuff
style sugar suit sulfur summer sun
sunny sunset super superb surf survey
sweet swim swing switch symbol system
table tackle tail tale talk tan
tank tap tape target task taste
tau tea teach teal team tear
tell ten tender tennis tent term
test tetra text thanks theme theory
thing think thread throat thumb ticket
tidy tie tiger till time timely
tin tip title toast today toe
tomato tone tongue tool tooth top
topic total touch tough tour towel
tower town track trade train trash
travel tray treat tree trick trip
trout trowel truck trupet trust truth
try tube tuna tune turf turkey
turn turnip tutor tux tweet twist
two type union unique unit upbeat
upper use useful user usual valley
value van vase vast veil vein
velvet verse very vessel vest video
view violet visit visual vivid voice
volume vowel voyage waffle wait wake
walk wall warm warmth wasabi wash
watch water wave wax way wealth
wear web wedge week weekly weight
west whale what wheat wheel when
where while who whole why will
win wind window wing winner winter
wire wish witty wolf wonder wood
wool woolly word work worker world
worry worth worthy wrap wrench wrist
writer xenon yak yam yard yarrow
year yearly yellow yew yogurt young
youth zebra zephyr zinc zone zoo
}
set nwordlist [llength $wordlist]
proc random_char {} {
return [string index \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
[expr {int(rand()*52)}]]
}
proc random_label {} {
set label [random_char]
while {rand()>0.8} {
append label [random_char]
}
if {rand()>0.9} {append label -}
append label [format %d [expr {int(rand()*100)}]]
return $label
}
proc random_numeric {} {
set n [expr {(rand()*2-1.0)*1e6}]
switch [expr {int(rand()*6)}] {
0 {set format %.3f}
1 {set format %.6E}
2 {set format %.4e}
default {set format %g}
}
return [format $format $n]
}
proc random_json {limit indent} {
global nwordlist wordlist
set res {}
if {$indent==0 || ($limit>0 && rand()>0.5)} {
incr limit -1
incr indent 2
set n [expr {int(rand()*5)+1}]
if {$n==5} {incr n [expr {int(rand()*10)}]}
if {rand()>0.5} {
set res \173\n
for {set i 0} {$i<$n} {incr i} {
append res [string repeat { } $indent]
if {rand()>0.8} {
if {rand()>0.5} {
set sep ":\n [string repeat { } $indent]"
} else {
set sep " : "
}
} else {
set sep :
}
append res \"[random_label]\"$sep[random_json $limit $indent]
if {$i<$n-1} {append res ,}
append res \n
}
incr indent -2
append res [string repeat { } $indent]
append res \175
return $res
} else {
set res \[\n
for {set i 0} {$i<$n} {incr i} {
append res [string repeat { } $indent]
append res [random_json $limit $indent]
if {$i<$n-1} {append res ,}
append res \n
}
incr indent -2
append res [string repeat { } $indent]
append res \]
return $res
}
} elseif {rand()>0.9} {
if {rand()>0.7} {return "true"}
if {rand()>0.5} {return "false"}
return "null"
} elseif {rand()>0.5} {
return [random_numeric]
} else {
set res \"
set n [expr {int(rand()*4)+1}]
if {$n>=4} {set n [expr {$n+int(rand()*6)}]}
for {set i 0} {$i<$n} {incr i} {
if {rand()<0.05} {
set w [random_numeric]
} else {
set k [expr {int(rand()*$nwordlist)}]
set w [lindex $wordlist $k]
}
if {rand()<0.07} {
set w \\\"$w\\\"
}
if {$i<$n-1} {
switch [expr {int(rand()*9)}] {
0 {set sp {, }}
1 {set sp "\\n "}
2 {set sp "-"}
default {set sp { }}
}
append res $w$sp
} else {
append res $w
if {rand()<0.2} {append res .}
}
}
return $res\"
}
}
puts "CREATE TABLE IF NOT EXISTS data1(x JSON);"
puts "BEGIN;"
set sz 0
for {set i 0} {$sz<100000000} {incr i} {
set j [random_json 7 0]
incr sz [string length $j]
puts "INSERT INTO data1(x) VALUES('$j');"
}
puts "COMMIT;"
puts "SELECT sum(length(x)) FROM data1;"
-4
View File
@@ -1,4 +0,0 @@
.mode qbox
.timer on
.param set $label 'q87'
SELECT rowid, x->>$label FROM data1 WHERE x->>$label IS NOT NULL;
-80
View File
@@ -1,80 +0,0 @@
#!/bin/bash
#
# This is a template for a script used for day-to-day size and
# performance monitoring of SQLite. Typical usage:
#
# sh speed-check.sh trunk # Baseline measurement of trunk
# sh speed-check.sh x1 # Measure some experimental change
# fossil xdiff --tk jout-trunk.txt jout-x1.txt # View chanages
#
# There are multiple output files, all with a base name given by
# the first argument:
#
# summary-$BASE.txt # Copy of standard output
# jout-$BASE.txt # cachegrind output
# explain-$BASE.txt # EXPLAIN listings (only with --explain)
#
if test "$1" = ""
then
echo "Usage: $0 OUTPUTFILE [OPTIONS]"
exit
fi
NAME=$1
shift
#CC_OPTS="-DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_MEMSYS5"
CC_OPTS="-DSQLITE_ENABLE_MEMSYS5"
CC=gcc
LEAN_OPTS="-DSQLITE_THREADSAFE=0"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_DEFAULT_MEMSTATUS=0"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_LIKE_DOESNT_MATCH_BLOBS"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_MAX_EXPR_DEPTH=0"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_DECLTYPE"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_DEPRECATED"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_PROGRESS_CALLBACK"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_SHARED_CACHE"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_USE_ALLOCA"
BASELINE="trunk"
doExplain=0
doCachegrind=1
doVdbeProfile=0
doWal=1
doDiff=1
while test "$1" != ""; do
case $1 in
--nodiff)
doDiff=0
;;
--lean)
CC_OPTS="$CC_OPTS $LEAN_OPTS"
;;
--clang)
CC=clang
;;
--gcc7)
CC=gcc-7
;;
-*)
CC_OPTS="$CC_OPTS $1"
;;
*)
BASELINE=$1
;;
esac
shift
done
echo "NAME = $NAME" | tee summary-$NAME.txt
echo "CC_OPTS = $CC_OPTS" | tee -a summary-$NAME.txt
rm -f cachegrind.out.* jsonshell
$CC -g -Os -Wall -I. $CC_OPTS ./shell.c ./sqlite3.c -o jsonshell -ldl -lpthread
ls -l jsonshell | tee -a summary-$NAME.txt
home=`echo $0 | sed -e 's,/[^/]*$,,'`
echo ./jsonshell json100mb.db "<$home/json-q1.txt"
valgrind --tool=cachegrind ./jsonshell json100mb.db <$home/json-q1.txt \
2>&1 | tee -a summary-$NAME.txt
cg_anno.tcl cachegrind.out.* >jout-$NAME.txt
echo '*****************************************************' >>jout-$NAME.txt
sed 's/^[0-9=-]\{9\}/==00000==/' summary-$NAME.txt >>jout-$NAME.txt
if test "$NAME" != "$BASELINE"; then
fossil xdiff --tk -c 20 jout-$BASELINE.txt jout-$NAME.txt
fi
+3 -117
View File
@@ -310,33 +310,12 @@ do_execsql_test json-6.1 {
SELECT json_valid('{"a":55,"b":72,}');
} {0}
do_execsql_test json-6.2 {
SELECT json_error_position('{"a":55,"b":72,}');
} {0}
do_execsql_test json-6.3 {
SELECT json_valid(json('{"a":55,"b":72,}'));
} {1}
do_execsql_test json-6.4 {
SELECT json_valid('{"a":55,"b":72 , }');
} {0}
do_execsql_test json-6.5 {
SELECT json_error_position('{"a":55,"b":72 , }');
} {0}
do_execsql_test json-6.6 {
SELECT json_error_position('{"a":55,"b":72,,}');
} {16}
do_execsql_test json-6.7 {
SELECT json_valid('{"a":55,"b":72}');
} {1}
do_execsql_test json-6.8 {
SELECT json_error_position('["a",55,"b",72,]');
do_execsql_test json-6.3 {
SELECT json_valid('["a",55,"b",72,]');
} {0}
do_execsql_test json-6.9 {
SELECT json_error_position('["a",55,"b",72 , ]');
} {0}
do_execsql_test json-6.10 {
SELECT json_error_position('["a",55,"b",72,,]');
} {16}
do_execsql_test json-6.11 {
do_execsql_test json-6.4 {
SELECT json_valid('["a",55,"b",72]');
} {1}
@@ -918,97 +897,4 @@ do_execsql_test json-20.3 {
SELECT json_object('a',2e370,'b',-3e380)->>'b';
} {-Inf}
# 2023-05-02 https://sqlite.org/forum/forumpost/06c6334412
# JSON functions should normally return NULL when given
# a NULL value as the JSON input.
#
db null NULL
do_execsql_test json-21.1 {
SELECT json_valid(NULL);
} NULL
do_execsql_test json-21.2 {
SELECT json_error_position(NULL);
} NULL
do_execsql_test json-21.3 {
SELECT json(NULL);
} NULL
do_execsql_test json-21.4 {
SELECT json_array(NULL);
} {[null]}
do_execsql_test json-21.5 {
SELECT json_extract(NULL);
} NULL
do_execsql_test json-21.6 {
SELECT json_insert(NULL,'$',123);
} NULL
do_execsql_test json-21.7 {
SELECT NULL->0;
} NULL
do_execsql_test json-21.8 {
SELECT NULL->>0;
} NULL
do_execsql_test json-21.9 {
SELECT '{a:5}'->NULL;
} NULL
do_execsql_test json-21.10 {
SELECT '{a:5}'->>NULL;
} NULL
do_catchsql_test json-21.11 {
SELECT json_object(NULL,5);
} {1 {json_object() labels must be TEXT}}
do_execsql_test json-21.12 {
SELECT json_patch(NULL,'{a:5}');
} NULL
do_execsql_test json-21.13 {
SELECT json_patch('{a:5}',NULL);
} NULL
do_execsql_test json-21.14 {
SELECT json_patch(NULL,NULL);
} NULL
do_execsql_test json-21.15 {
SELECT json_remove(NULL,'$');
} NULL
do_execsql_test json-21.16 {
SELECT json_remove('{a:5,b:7}',NULL);
} NULL
do_execsql_test json-21.17 {
SELECT json_replace(NULL,'$.a',123);
} NULL
do_execsql_test json-21.18 {
SELECT json_replace('{a:5,b:7}',NULL,NULL);
} {{{"a":5,"b":7}}}
do_execsql_test json-21.19 {
SELECT json_set(NULL,'$.a',123);
} NULL
do_execsql_test json-21.20 {
SELECT json_set('{a:5,b:7}',NULL,NULL);
} {{{"a":5,"b":7}}}
do_execsql_test json-21.21 {
SELECT json_type(NULL);
} NULL
do_execsql_test json-21.22 {
SELECT json_type('{a:5,b:7}',NULL);
} NULL
do_execsql_test json-21.23 {
SELECT json_quote(NULL);
} null
do_execsql_test json-21.24 {
SELECT count(*) FROM json_each(NULL);
} 0
do_execsql_test json-21.25 {
SELECT count(*) FROM json_tree(NULL);
} 0
do_execsql_test json-21.26 {
WITH c(x) AS (VALUES(1),(2.0),(NULL),('three'))
SELECT json_group_array(x) FROM c;
} {[1,2.0,null,"three"]}
do_execsql_test json-21.27 {
WITH c(x,y) AS (VALUES('a',1),('b',2.0),('c',NULL),(NULL,'three'),('e','four'))
SELECT json_group_object(x,y) FROM c;
} {{{"a":1,"b":2.0,"c":null,:"three","e":"four"}}}
finish_test
+12 -21
View File
@@ -301,27 +301,18 @@ for {set i 0} {$i<100} {incr i} {
# allowing them. The following tests verify that the problem is now
# fixed.
#
foreach {id j x0 x5} {
1401 {'{"x":01}'} 0 0
1402 {'{"x":-01}'} 0 0
1403 {'{"x":0}'} 1 1
1404 {'{"x":-0}'} 1 1
1405 {'{"x":0.1}'} 1 1
1406 {'{"x":-0.1}'} 1 1
1407 {'{"x":0.0000}'} 1 1
1408 {'{"x":-0.0000}'} 1 1
1409 {'{"x":01.5}'} 0 0
1410 {'{"x":-01.5}'} 0 0
1411 {'{"x":00}'} 0 0
1412 {'{"x":-00}'} 0 0
1413 {'{"x":+0}'} 0 1
1414 {'{"x":+5}'} 0 1
1415 {'{"x":+5.5}'} 0 1
} {
do_execsql_test json102-$id "
SELECT json_valid($j), NOT json_error_position($j);
" [list $x0 $x5]
}
do_execsql_test json102-1401 { SELECT json_valid('{"x":01}') } 0
do_execsql_test json102-1402 { SELECT json_valid('{"x":-01}') } 0
do_execsql_test json102-1403 { SELECT json_valid('{"x":0}') } 1
do_execsql_test json102-1404 { SELECT json_valid('{"x":-0}') } 1
do_execsql_test json102-1405 { SELECT json_valid('{"x":0.1}') } 1
do_execsql_test json102-1406 { SELECT json_valid('{"x":-0.1}') } 1
do_execsql_test json102-1407 { SELECT json_valid('{"x":0.0000}') } 1
do_execsql_test json102-1408 { SELECT json_valid('{"x":-0.0000}') } 1
do_execsql_test json102-1409 { SELECT json_valid('{"x":01.5}') } 0
do_execsql_test json102-1410 { SELECT json_valid('{"x":-01.5}') } 0
do_execsql_test json102-1411 { SELECT json_valid('{"x":00}') } 0
do_execsql_test json102-1412 { SELECT json_valid('{"x":-00}') } 0
#------------------------------------------------------------------------
# 2017-04-10 ticket 6c9b5514077fed34551f98e64c09a10dc2fc8e16
-42
View File
@@ -30,48 +30,6 @@ do_execsql_test json104-100 {
}
}');
} {{{"a":"z","c":{"d":"e"}}}}
do_execsql_test json104-101 {
SELECT json_patch('{
"a": "b",
"c": {
"d": "e",
"f": "g"
}
}','{
a:"z",
c: {
f: null
}
}');
} {{{"a":"z","c":{"d":"e"}}}}
do_execsql_test json104-102 {
SELECT json_patch('{
a: "b",
c: {
d: "e",
f: "g"
}
}','{
"a":"z",
"c": {
"f": null
}
}');
} {{{"a":"z","c":{"d":"e"}}}}
do_execsql_test json104-103 {
SELECT json_patch('{
a: "b",
c: {
d: "e",
f: "g"
}
}','{
a:"z",
c: {
f: null
}
}');
} {{{"a":"z","c":{"d":"e"}}}}
# This is the example from pages 4 and 5 of RFC-7396
-304
View File
@@ -1,304 +0,0 @@
# 2023-04-27
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements tests for the JSON5 enhancements to the
# JSON SQL functions extension to the SQLite library.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix json501
# From https://spec.json5.org/#introduction
#
#-----------------------------------------------------------------------------
# Summary of Features
#
# The following ECMAScript 5.1 features, which are not supported in JSON, have
# been extended to JSON5.
#
# Objects
#
# 1) Object keys may be an ECMAScript 5.1 IdentifierName.
# 2) Objects may have a single trailing comma.
#
# Arrays
#
# 3) Arrays may have a single trailing comma.
#
# Strings
#
# 4) Strings may be single quoted.
# 5) Strings may span multiple lines by escaping new line characters.
# 6) Strings may include character escapes.
#
# Numbers
#
# 7) Numbers may be hexadecimal.
# 8) Numbers may have a leading or trailing decimal point.
# 9) Numbers may be IEEE 754 positive infinity, negative infinity, and NaN.
# 10) Numbers may begin with an explicit plus sign.
#
# Comments
#
# 11) Single and multi-line comments are allowed.
#
# White Space
#
# 12) Additional white space characters are allowed.
#-----------------------------------------------------------------------------
#
# Test number in this file are of the form X.Y where X is one of the item
# numbers in the feature list above and Y is the test sequence number.
#
###############################################################################
# 1) Object keys may be an ECMAScript 5.1 IdentifierName.
do_execsql_test 1.1 {
WITH c(x) AS (VALUES('{a:5,b:6}'))
SELECT x->>'a', json(x), json_valid(x), NOT json_error_position(x) FROM c;
} {5 {{"a":5,"b":6}} 0 1}
do_execsql_test 1.2 {
SELECT '[7,null,{a:5,b:6},[8,9]]'->>'$[2].b';
} {6}
do_execsql_test 1.3 {
SELECT '{ $123 : 789 }'->>'$."$123"';
} 789
do_execsql_test 1.4 {
SELECT '{ _123$xyz : 789 }'->>'$."_123$xyz"';
} 789
do_execsql_test 1.5 {
SELECT '{ MNO_123$xyz : 789 }'->>'$."MNO_123$xyz"';
} 789
do_execsql_test 1.6 {
SELECT json('{ MNO_123$xyz : 789 }');
} [list {{"MNO_123$xyz":789}}]
do_catchsql_test 1.10 {
SELECT json('{ MNO_123/xyz : 789 }');
} {1 {malformed JSON}}
do_execsql_test 1.11 {
SELECT '{ MNO_123æxyz : 789 }'->>'MNO_123æxyz';
} {789}
###############################################################################
# 2) Objects may have a single trailing comma.
do_execsql_test 2.1 {
WITH c(x) AS (VALUES('{"a":5, "b":6, }'))
SELECT x->>'b', json(x), json_valid(x), NOT json_error_position(x) FROM c;
} {6 {{"a":5,"b":6}} 0 1}
do_execsql_test 2.2 {
SELECT '{a:5, b:6 , }'->>'b';
} 6
do_catchsql_test 2.3 {
SELECT '{a:5, b:6 ,, }'->>'b';
} {1 {malformed JSON}}
do_catchsql_test 2.4 {
SELECT '{a:5, b:6, ,}'->>'b';
} {1 {malformed JSON}}
###############################################################################
# 3) Arrays may have a single trailing comma.
do_execsql_test 3.1 {
WITH c(x) AS (VALUES('[5, 6,]'))
SELECT x->>1, json(x), json_valid(x), NOT json_error_position(x) FROM c;
} {6 {[5,6]} 0 1}
do_execsql_test 3.2 {
SELECT '[5, 6 , ]'->>1;
} 6
do_catchsql_test 3.3 {
SELECT '[5, 6,,]'->>1;
} {1 {malformed JSON}}
do_catchsql_test 3.4 {
SELECT '[5, 6 , , ]'->>1;
} {1 {malformed JSON}}
###############################################################################
# 4) Strings may be single quoted.
do_execsql_test 4.1 {
WITH c(x) AS (VALUES('{"a": ''abcd''}'))
SELECT x->>'a', json(x), json_valid(x), NOT json_error_position(x) FROM c;
} {abcd {{"a":"abcd"}} 0 1}
do_execsql_test 4.2 {
SELECT '{b: 123, ''a'': ''ab\''cd''}'->>'a';
} {ab'cd}
###############################################################################
# 5) Strings may span multiple lines by escaping new line characters.
do_execsql_test 5.1 {
WITH c(x) AS (VALUES('{a: "abc'||char(0x5c,0x0a)||'xyz"}'))
SELECT x->>'a', json(x), json_valid(x), NOT json_error_position(x) FROM c;
} {abcxyz {{"a":"abcxyz"}} 0 1}
do_execsql_test 5.2 {
SELECT ('{a: "abc'||char(0x5c,0x0d)||'xyz"}')->>'a';
} {abcxyz}
do_execsql_test 5.3 {
SELECT ('{a: "abc'||char(0x5c,0x0d,0x0a)||'xyz"}')->>'a';
} {abcxyz}
do_execsql_test 5.4 {
SELECT ('{a: "abc'||char(0x5c,0x2028)||'xyz"}')->>'a';
} {abcxyz}
do_execsql_test 5.5 {
SELECT ('{a: "abc'||char(0x5c,0x2029)||'xyz"}')->>'a';
} {abcxyz}
###############################################################################
# 6) Strings may include character escapes.
do_execsql_test 6.1 {
SELECT ('{a: "abc'||char(0x5c,0x27)||'xyz"}')->>'a';
} {abc'xyz}
do_execsql_test 6.2 {
SELECT ('{a: "abc'||char(0x5c,0x22)||'xyz"}')->>'a';
} {abc"xyz}
do_execsql_test 6.3 {
SELECT ('{a: "abc'||char(0x5c,0x5c)||'xyz"}')->>'a';
} {{abc\xyz}}
do_execsql_test 6.4 {
SELECT hex(('{a: "abc\bxyz"}')->>'a');
} {6162630878797A}
do_execsql_test 6.5 {
SELECT hex(('{a: "abc\f\n\r\t\vxyz"}')->>'a');
} {6162630C0A0D090B78797A}
do_execsql_test 6.6 {
SELECT hex(('{a: "abc\0xyz"}')->>'a');
} {6162630078797A}
do_execsql_test 6.7 {
SELECT '{a: "abc\x35\x4f\x6Exyz"}'->>'a';
} {abc5Onxyz}
do_execsql_test 6.8 {
SELECT '{a: "\x6a\x6A\x6b\x6B\x6c\x6C\x6d\x6D\x6e\x6E\x6f\x6F"}'->>'a';
} {jjkkllmmnnoo}
###############################################################################
# 7) Numbers may be hexadecimal.
do_execsql_test 7.1 {
SELECT '{a: 0x0}'->>'a';
} 0
do_execsql_test 7.2 {
SELECT '{a: -0x0}'->>'a';
} 0
do_execsql_test 7.3 {
SELECT '{a: +0x0}'->>'a';
} 0
do_execsql_test 7.4 {
SELECT '{a: 0xabcdef}'->>'a';
} 11259375
do_execsql_test 7.5 {
SELECT '{a: -0xaBcDeF}'->>'a';
} -11259375
do_execsql_test 7.6 {
SELECT '{a: +0xABCDEF}'->>'a';
} 11259375
###############################################################################
# 8) Numbers may have a leading or trailing decimal point.
do_execsql_test 8.1 {
WITH c(x) AS (VALUES('{x: 4.}')) SELECT x->>'x', json(x) FROM c;
} {4.0 {{"x":4.0}}}
do_execsql_test 8.2 {
WITH c(x) AS (VALUES('{x: +4.}')) SELECT x->>'x', json(x) FROM c;
} {4.0 {{"x":4.0}}}
do_execsql_test 8.3 {
WITH c(x) AS (VALUES('{x: -4.}')) SELECT x->>'x', json(x) FROM c;
} {-4.0 {{"x":-4.0}}}
do_execsql_test 8.3 {
WITH c(x) AS (VALUES('{x: .5}')) SELECT x->>'x', json(x) FROM c;
} {0.5 {{"x":0.5}}}
do_execsql_test 8.4 {
WITH c(x) AS (VALUES('{x: -.5}')) SELECT x->>'x', json(x) FROM c;
} {-0.5 {{"x":-0.5}}}
do_execsql_test 8.5 {
WITH c(x) AS (VALUES('{x: +.5}')) SELECT x->>'x', json(x) FROM c;
} {0.5 {{"x":0.5}}}
do_execsql_test 8.6 {
WITH c(x) AS (VALUES('{x: 4.e0}')) SELECT x->>'x', json(x) FROM c;
} {4.0 {{"x":4.0e0}}}
do_execsql_test 8.7 {
WITH c(x) AS (VALUES('{x: +4.e1}')) SELECT x->>'x', json(x) FROM c;
} {40.0 {{"x":4.0e1}}}
do_execsql_test 8.8 {
WITH c(x) AS (VALUES('{x: -4.e2}')) SELECT x->>'x', json(x) FROM c;
} {-400.0 {{"x":-4.0e2}}}
do_execsql_test 8.9 {
WITH c(x) AS (VALUES('{x: .5e3}')) SELECT x->>'x', json(x) FROM c;
} {500.0 {{"x":0.5e3}}}
do_execsql_test 8.10 {
WITH c(x) AS (VALUES('{x: -.5e-1}')) SELECT x->>'x', json(x) FROM c;
} {-0.05 {{"x":-0.5e-1}}}
do_execsql_test 8.11 {
WITH c(x) AS (VALUES('{x: +.5e-2}')) SELECT x->>'x', json(x) FROM c;
} {0.005 {{"x":0.5e-2}}}
###############################################################################
# 9) Numbers may be IEEE 754 positive infinity, negative infinity, and NaN.
do_execsql_test 9.1 {
WITH c(x) AS (VALUES('{x: +Infinity}')) SELECT x->>'x', json(x) FROM c;
} {Inf {{"x":9.0e999}}}
do_execsql_test 9.2 {
WITH c(x) AS (VALUES('{x: -Infinity}')) SELECT x->>'x', json(x) FROM c;
} {-Inf {{"x":-9.0e999}}}
do_execsql_test 9.3 {
WITH c(x) AS (VALUES('{x: Infinity}')) SELECT x->>'x', json(x) FROM c;
} {Inf {{"x":9.0e999}}}
do_execsql_test 9.4 {
WITH c(x) AS (VALUES('{x: NaN}')) SELECT x->>'x', json(x) FROM c;
} {{} {{"x":null}}}
###############################################################################
# 10) Numbers may begin with an explicit plus sign.
do_execsql_test 10.1 {
SELECT '{a: +123}'->'a';
} 123
###############################################################################
# 11) Single and multi-line comments are allowed.
do_execsql_test 11.1 {
SELECT ' /* abc */ { /*def*/ aaa /* xyz */ : // to the end of line
123 /* xyz */ , /* 123 */ }'->>'aaa';
} 123
###############################################################################
# 12) Additional white space characters are allowed.
do_execsql_test 12.1 {
SELECT (char(0x09,0x0a,0x0b,0x0c,0x0d,0x20,0xa0,0x2028,0x2029)
|| '{a: "xyz"}')->>'a';
} xyz
do_execsql_test 12.2 {
SELECT ('{a:' || char(0x09,0x0a,0x0b,0x0c,0x0d,0x20,0xa0,0x2028,0x2029)
|| '"xyz"}')->>'a';
} xyz
do_execsql_test 12.3 {
SELECT (char(0x1680,0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,
0x2006,0x2007,0x2008,0x2009,0x200a,0x3000,0xfeff)
|| '{a: "xyz"}')->>'a';
} xyz
do_execsql_test 12.4 {
SELECT ('{a: ' ||char(0x1680,0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,
0x2006,0x2007,0x2008,0x2009,0x200a,0x3000,0xfeff)
|| ' "xyz"}')->>'a';
} xyz
finish_test
-25
View File
@@ -1,25 +0,0 @@
# 2023-04-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.
#
#***********************************************************************
# This file implements tests for the JSON5 enhancements to the
# JSON SQL functions extension to the SQLite library.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix json502
do_execsql_test 1.1 {
CREATE TABLE t1(x JSON);
INSERT INTO t1(x) VALUES('{a:{b:{c:"hello",},},}');
SELECT fullkey FROM t1, json_tree(x);
} {{$} {$.a} {$.a.b} {$.a.b.c}}
finish_test
-3
View File
@@ -592,9 +592,6 @@ do_test misc1-18.1 {
set n [sqlite3_sleep 100]
expr {$n>=100}
} {1}
do_test misc1-18.2 {
sqlite3_sleep -100
} {0}
# 2014-01-10: In a CREATE TABLE AS, if one or more of the column names
# are an empty string, that is still OK.
-5
View File
@@ -254,11 +254,6 @@ do_test shell1-2.4.2 {
catchcmd "test.db" ".mode \"csv\""
} {0 {}}
# check that certain quoted arg escapes work
do_test shell1-2.5.1 {
catchcmd ":memory:" ".print \"\\060\\077 \\x3f\\x30 \\a\\t\""
} [list 0 "0? ?0 \a\t"]
#----------------------------------------------------------------------------
# Test cases shell1-3.*: Basic test that "dot" command can be called.
-46
View File
@@ -216,51 +216,5 @@ do_test shell2-1.4.9 {
done
2}}
# Verify that generate_series stays sane near 64-bit range boundaries.
# See overflow report at https://sqlite.org/forum/forumpost/5d34ce5280
do_test shell2-1.4.10 {
set res [catchcmd :memory: [string trim {
SELECT * FROM generate_series(9223372036854775807,9223372036854775807,1);
SELECT * FROM generate_series(9223372036854775807,9223372036854775807,-1);
SELECT avg(rowid),min(value),max(value) FROM generate_series(
-9223372036854775808,9223372036854775807,1085102592571150095);
SELECT * FROM generate_series(-9223372036854775808,9223372036854775807,
9223372036854775807);
SELECT value,rowid FROM generate_series(-4611686018427387904,
4611686018427387904, 4611686018427387904) ORDER BY value DESC;
SELECT * FROM generate_series(0,-2,-1);
SELECT * FROM generate_series(0,-2);
SELECT * FROM generate_series(0,2) LIMIT 3;}]]
} {0 {9223372036854775807
9223372036854775807
9.5|-9223372036854775808|9223372036854775807
-9223372036854775808
-1
9223372036854775806
4611686018427387904|3
0|2
-4611686018427387904|1
0
-1
-2
0
1
2}}
# Bug discovered while messing around, .import hangs with
# bit 7 set in column separator.
do_test shell2-1.4.11 {
forcedelete dummy.csv
set df [open dummy.csv w]
puts $df dog,cat
close $df
set res [catchcmd :memory: [string trim {
CREATE TABLE t(line text);
.mode ascii
.separator "\377" "\n"
.import dummy.csv t
SELECT count(*) FROM t;}]]
} {0 1}
finish_test
+1 -1
View File
@@ -61,7 +61,7 @@ do_execsql_test tabfunc01-1.8 {
} {30 25 20 15 10 5 0}
do_execsql_test tabfunc01-1.9 {
SELECT rowid, * FROM generate_series(0,32,5) ORDER BY value DESC;
} {7 30 6 25 5 20 4 15 3 10 2 5 1 0}
} {1 30 2 25 3 20 4 15 5 10 6 5 7 0}
do_execsql_test tabfunc01-1.10 {
SELECT rowid, * FROM generate_series(0,32,5) ORDER BY +value DESC;
} {7 30 6 25 5 20 4 15 3 10 2 5 1 0}