Sync w/trunk, further streamline shell's resumable prescan.
FossilOrigin-Name: 9e00f9f7c03c192a3fb6b22851db0626515c59daac5ce6520229c42c838bf5b7
This commit is contained in:
commit
7e00984a47
@ -468,7 +468,8 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/userauth/userauth.c
|
||||
$(TOP)/ext/userauth/userauth.c \
|
||||
$(TOP)/ext/rtree/test_rtreedoc.c
|
||||
|
||||
# Source code to the library files needed by the test fixture
|
||||
#
|
||||
|
@ -1586,6 +1586,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\totype.c \
|
||||
$(TOP)\ext\misc\unionvtab.c \
|
||||
$(TOP)\ext\misc\wholenumber.c \
|
||||
$(TOP)\ext\rtree\test_rtreedoc.c \
|
||||
fts5.c
|
||||
|
||||
# If use of zlib is enabled, add the "zipfile.c" source file.
|
||||
|
@ -64,7 +64,11 @@
|
||||
#endif
|
||||
int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
/*
|
||||
** If building separately, we will need some setup that is normally
|
||||
** found in sqliteInt.h
|
||||
*/
|
||||
#if !defined(SQLITE_AMALGAMATION)
|
||||
#include "sqlite3rtree.h"
|
||||
typedef sqlite3_int64 i64;
|
||||
typedef sqlite3_uint64 u64;
|
||||
@ -77,7 +81,17 @@ typedef unsigned int u32;
|
||||
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
||||
# define ALWAYS(X) (1)
|
||||
# define NEVER(X) (0)
|
||||
#elif !defined(NDEBUG)
|
||||
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
||||
# define NEVER(X) ((X)?(assert(0),1):0)
|
||||
#else
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_AMALGAMATION) */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@ -135,7 +149,9 @@ struct Rtree {
|
||||
u8 nBytesPerCell; /* Bytes consumed per cell */
|
||||
u8 inWrTrans; /* True if inside write transaction */
|
||||
u8 nAux; /* # of auxiliary columns in %_rowid */
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
u8 nAuxNotNull; /* Number of initial not-null aux columns */
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 bCorrupt; /* Shadow table corruption detected */
|
||||
#endif
|
||||
@ -666,18 +682,6 @@ static void nodeBlobReset(Rtree *pRtree){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if pNode is the same as pParent or any of the parents
|
||||
** of pParent.
|
||||
*/
|
||||
static int nodeInParentChain(const RtreeNode *pNode, const RtreeNode *pParent){
|
||||
do{
|
||||
if( pNode==pParent ) return 1;
|
||||
pParent = pParent->pParent;
|
||||
}while( pParent );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Obtain a reference to an r-tree node.
|
||||
*/
|
||||
@ -694,14 +698,7 @@ static int nodeAcquire(
|
||||
** increase its reference count and return it.
|
||||
*/
|
||||
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
|
||||
if( pParent && !pNode->pParent ){
|
||||
if( nodeInParentChain(pNode, pParent) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
pParent->nRef++;
|
||||
pNode->pParent = pParent;
|
||||
}else if( pParent && pNode->pParent && pParent!=pNode->pParent ){
|
||||
if( pParent && pParent!=pNode->pParent ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
@ -759,7 +756,7 @@ static int nodeAcquire(
|
||||
** are the leaves, and so on. If the depth as specified on the root node
|
||||
** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
|
||||
*/
|
||||
if( pNode && rc==SQLITE_OK && iNode==1 ){
|
||||
if( rc==SQLITE_OK && pNode && iNode==1 ){
|
||||
pRtree->iDepth = readInt16(pNode->zData);
|
||||
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
@ -1365,11 +1362,12 @@ static int nodeRowidIndex(
|
||||
*/
|
||||
static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
|
||||
RtreeNode *pParent = pNode->pParent;
|
||||
if( pParent ){
|
||||
if( ALWAYS(pParent) ){
|
||||
return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
|
||||
}else{
|
||||
*piIndex = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
*piIndex = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1492,7 +1490,8 @@ static RtreeSearchPoint *rtreeSearchPointNew(
|
||||
pNew = rtreeEnqueue(pCur, rScore, iLevel);
|
||||
if( pNew==0 ) return 0;
|
||||
ii = (int)(pNew - pCur->aPoint) + 1;
|
||||
if( ii<RTREE_CACHE_SZ ){
|
||||
assert( ii==1 );
|
||||
if( ALWAYS(ii<RTREE_CACHE_SZ) ){
|
||||
assert( pCur->aNode[ii]==0 );
|
||||
pCur->aNode[ii] = pCur->aNode[0];
|
||||
}else{
|
||||
@ -1553,7 +1552,7 @@ static void rtreeSearchPointPop(RtreeCursor *p){
|
||||
if( p->bPoint ){
|
||||
p->anQueue[p->sPoint.iLevel]--;
|
||||
p->bPoint = 0;
|
||||
}else if( p->nPoint ){
|
||||
}else if( ALWAYS(p->nPoint) ){
|
||||
p->anQueue[p->aPoint[0].iLevel]--;
|
||||
n = --p->nPoint;
|
||||
p->aPoint[0] = p->aPoint[n];
|
||||
@ -1694,7 +1693,7 @@ static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
|
||||
RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
|
||||
int rc = SQLITE_OK;
|
||||
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
|
||||
if( rc==SQLITE_OK && p ){
|
||||
if( rc==SQLITE_OK && ALWAYS(p) ){
|
||||
*pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
|
||||
}
|
||||
return rc;
|
||||
@ -1712,7 +1711,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
|
||||
|
||||
if( rc ) return rc;
|
||||
if( p==0 ) return SQLITE_OK;
|
||||
if( NEVER(p==0) ) return SQLITE_OK;
|
||||
if( i==0 ){
|
||||
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
|
||||
}else if( i<=pRtree->nDim2 ){
|
||||
@ -1911,8 +1910,11 @@ static int rtreeFilter(
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
RtreeSearchPoint *pNew;
|
||||
assert( pCsr->bPoint==0 ); /* Due to the resetCursor() call above */
|
||||
pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
if( NEVER(pNew==0) ){ /* Because pCsr->bPoint was FALSE */
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pNew->id = 1;
|
||||
pNew->iCell = 0;
|
||||
pNew->eWithin = PARTLY_WITHIN;
|
||||
@ -1989,7 +1991,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
|
||||
|
||||
if( bMatch==0 && p->usable
|
||||
&& p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
&& p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
){
|
||||
/* We have an equality constraint on the rowid. Use strategy 1. */
|
||||
int jj;
|
||||
@ -2242,12 +2244,19 @@ static int AdjustTree(
|
||||
){
|
||||
RtreeNode *p = pNode;
|
||||
int cnt = 0;
|
||||
int rc;
|
||||
while( p->pParent ){
|
||||
RtreeNode *pParent = p->pParent;
|
||||
RtreeCell cell;
|
||||
int iCell;
|
||||
|
||||
if( (++cnt)>1000 || nodeParentIndex(pRtree, p, &iCell) ){
|
||||
cnt++;
|
||||
if( NEVER(cnt>100) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
rc = nodeParentIndex(pRtree, p, &iCell);
|
||||
if( NEVER(rc!=SQLITE_OK) ){
|
||||
RTREE_IS_CORRUPT(pRtree);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
@ -2631,11 +2640,12 @@ static int SplitNode(
|
||||
RtreeNode *pParent = pLeft->pParent;
|
||||
int iCell;
|
||||
rc = nodeParentIndex(pRtree, pLeft, &iCell);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ALWAYS(rc==SQLITE_OK) ){
|
||||
nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);
|
||||
rc = AdjustTree(pRtree, pParent, &leftbbox);
|
||||
assert( rc==SQLITE_OK );
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( NEVER(rc!=SQLITE_OK) ){
|
||||
goto splitnode_out;
|
||||
}
|
||||
}
|
||||
@ -2710,7 +2720,7 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
|
||||
*/
|
||||
iNode = sqlite3_column_int64(pRtree->pReadParent, 0);
|
||||
for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
|
||||
if( !pTest ){
|
||||
if( pTest==0 ){
|
||||
rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
|
||||
}
|
||||
}
|
||||
@ -2741,6 +2751,7 @@ static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
|
||||
pParent = pNode->pParent;
|
||||
pNode->pParent = 0;
|
||||
rc = deleteCell(pRtree, pParent, iCell, iHeight+1);
|
||||
assert( rc==SQLITE_OK );
|
||||
}
|
||||
rc2 = nodeRelease(pRtree, pParent);
|
||||
if( rc==SQLITE_OK ){
|
||||
@ -2963,7 +2974,7 @@ static int rtreeInsertCell(
|
||||
}
|
||||
}else{
|
||||
rc = AdjustTree(pRtree, pNode, pCell);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ALWAYS(rc==SQLITE_OK) ){
|
||||
if( iHeight==0 ){
|
||||
rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
|
||||
}else{
|
||||
@ -3069,7 +3080,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
|
||||
int rc2;
|
||||
RtreeNode *pChild = 0;
|
||||
i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
|
||||
rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
|
||||
rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); /* tag-20210916a */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
|
||||
}
|
||||
@ -3404,7 +3415,7 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
|
||||
char *zSql;
|
||||
sqlite3_stmt *p;
|
||||
int rc;
|
||||
i64 nRow = 0;
|
||||
i64 nRow = RTREE_MIN_ROWEST;
|
||||
|
||||
rc = sqlite3_table_column_metadata(
|
||||
db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
|
||||
@ -3421,20 +3432,10 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
|
||||
rc = sqlite3_finalize(p);
|
||||
}else if( rc!=SQLITE_NOMEM ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( nRow==0 ){
|
||||
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
|
||||
}else{
|
||||
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
|
||||
}
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3584,9 +3585,12 @@ static int rtreeSqlInit(
|
||||
sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
|
||||
for(ii=0; ii<pRtree->nAux; ii++){
|
||||
if( ii ) sqlite3_str_append(p, ",", 1);
|
||||
#ifdef SQLITE_ENABLE_GEOPOLY
|
||||
if( ii<pRtree->nAuxNotNull ){
|
||||
sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii);
|
||||
}else{
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
|
||||
}
|
||||
}
|
||||
@ -4525,7 +4529,10 @@ int sqlite3_rtree_query_callback(
|
||||
|
||||
/* Allocate and populate the context object. */
|
||||
pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback));
|
||||
if( !pGeomCtx ) return SQLITE_NOMEM;
|
||||
if( !pGeomCtx ){
|
||||
if( xDestructor ) xDestructor(pContext);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pGeomCtx->xGeom = 0;
|
||||
pGeomCtx->xQueryFunc = xQueryFunc;
|
||||
pGeomCtx->xDestructor = xDestructor;
|
||||
|
@ -145,7 +145,7 @@ populate_t1
|
||||
do_test rtreeA-2.2.0 { truncate_node 1 200 } {}
|
||||
do_corruption_tests rtreeA-2.2 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
|
||||
}
|
||||
@ -160,7 +160,7 @@ do_test rtreeA-3.1.0.1 { set_tree_depth t1 } {1}
|
||||
do_test rtreeA-3.1.0.2 { set_tree_depth t1 3 } {3}
|
||||
do_corruption_tests rtreeA-3.1 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ do_execsql_test rtreeA-3.1.0.3 {
|
||||
do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000}
|
||||
do_corruption_tests rtreeA-3.2 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ do_test rtreeA-3.3.0 {
|
||||
} {65535}
|
||||
do_corruption_tests rtreeA-3.3 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
}
|
||||
|
||||
@ -203,7 +203,7 @@ do_test rtreeA-4.1.0 {
|
||||
} {4000}
|
||||
do_corruption_tests rtreeA-4.1 {
|
||||
1 "SELECT * FROM t1"
|
||||
2 "SELECT * FROM t1 WHERE rowid=5"
|
||||
2 "SELECT * FROM t1 WHERE +rowid=5"
|
||||
3 "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
|
||||
4 "SELECT * FROM t1 WHERE x1<10 AND x2>12"
|
||||
}
|
||||
@ -216,7 +216,7 @@ create_t1
|
||||
populate_t1
|
||||
do_execsql_test rtreeA-5.1.0 { DELETE FROM t1_parent } {}
|
||||
do_corruption_tests rtreeA-5.1 {
|
||||
1 "DELETE FROM t1 WHERE rowid = 5"
|
||||
1 "DELETE FROM t1 WHERE +rowid = 5"
|
||||
2 "DELETE FROM t1"
|
||||
}
|
||||
|
||||
|
1578
ext/rtree/rtreedoc.test
Normal file
1578
ext/rtree/rtreedoc.test
Normal file
File diff suppressed because it is too large
Load Diff
346
ext/rtree/rtreedoc2.test
Normal file
346
ext/rtree/rtreedoc2.test
Normal file
@ -0,0 +1,346 @@
|
||||
# 2021 September 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# The focus of this file is testing the r-tree extension.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix rtreedoc2
|
||||
|
||||
ifcapable !rtree {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
# Section 6 of documentation.
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
set testprefix rtreedoc2-1
|
||||
|
||||
# EVIDENCE-OF: R-35254-48865 A call to one of the above APIs creates a
|
||||
# new SQL function named by the second parameter (zQueryFunc or zGeom).
|
||||
#
|
||||
# [register_circle_geom db] registers new geometry callback "Qcircle"
|
||||
# and legacy implementation "circle". Test that these do actually appear.
|
||||
#
|
||||
do_execsql_test 1.1.0 {
|
||||
SELECT * FROM pragma_function_list WHERE name IN('circle', 'qcircle');
|
||||
} {
|
||||
}
|
||||
do_test 1.1 {
|
||||
register_circle_geom db
|
||||
} {SQLITE_OK}
|
||||
do_execsql_test 1.1.2 {
|
||||
SELECT * FROM pragma_function_list WHERE name = 'circle' AND enc='utf8';
|
||||
} {
|
||||
circle 0 s utf8 -1 0
|
||||
}
|
||||
do_execsql_test 1.1.3 {
|
||||
SELECT * FROM pragma_function_list WHERE name = 'qcircle' AND enc='utf8';
|
||||
} {
|
||||
qcircle 0 s utf8 -1 0
|
||||
}
|
||||
|
||||
do_execsql_test 1.2.0 { SELECT circle(1, 2, 3); } {{}}
|
||||
do_execsql_test 1.2.1 { SELECT qcircle(1, 2, 3); } {{}}
|
||||
|
||||
# EVIDENCE-OF: R-61427-46983
|
||||
do_execsql_test 1.3.0 {
|
||||
CREATE VIRTUAL TABLE demo_index USING rtree(id, x1,x2, y1,y2);
|
||||
INSERT INTO demo_index VALUES(10, 45,45, 24,24);
|
||||
INSERT INTO demo_index VALUES(20, 50,50, 28,28);
|
||||
INSERT INTO demo_index VALUES(30, 43,43, 22,22);
|
||||
}
|
||||
do_execsql_test 1.3.1 {
|
||||
SELECT id FROM demo_index WHERE id MATCH circle(45.3, 22.9, 5.0)
|
||||
} {10 30}
|
||||
|
||||
# EVIDENCE-OF: R-16907-50223 The SQL syntax for custom queries is the
|
||||
# same regardless of which interface, sqlite3_rtree_geometry_callback()
|
||||
# or sqlite3_rtree_query_callback(), is used to register the SQL
|
||||
# function.
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT id FROM demo_index WHERE id MATCH qcircle(45.3, 22.9, 5.0, 1)
|
||||
} {10 30}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-59634-51678 When that SQL function appears on the
|
||||
# right-hand side of the MATCH operator and the left-hand side of the
|
||||
# MATCH operator is any column in the R*Tree virtual table, then the
|
||||
# callback defined by the third argument (xQueryFunc or xGeom) is
|
||||
# invoked to determine if a particular object or subtree overlaps the
|
||||
# desired region.
|
||||
proc box_geom {args} {
|
||||
lappend ::box_geom [concat [lindex $args 0] [lrange $args 2 end-1]]
|
||||
return ""
|
||||
}
|
||||
register_box_geom db box_geom
|
||||
set box_geom [list]
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT id FROM demo_index WHERE id MATCH box(43,46, 21,25);
|
||||
} {10 30}
|
||||
do_test 1.3.3 {
|
||||
set ::box_geom
|
||||
} [list {*}{
|
||||
{box {43.0 46.0 21.0 25.0} {45.0 45.0 24.0 24.0}}
|
||||
{box {43.0 46.0 21.0 25.0} {50.0 50.0 28.0 28.0}}
|
||||
{box {43.0 46.0 21.0 25.0} {43.0 43.0 22.0 22.0}}
|
||||
}]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
# Section 6 of documentation.
|
||||
#-------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
set testprefix rtreedoc2-2
|
||||
|
||||
# EVIDENCE-OF: R-02424-24769 The second argument is the number of
|
||||
# coordinates in each r-tree entry, and is always the same for any given
|
||||
# R*Tree.
|
||||
#
|
||||
# EVIDENCE-OF: R-40260-16838 The number of coordinates is 2 for a
|
||||
# 1-dimensional R*Tree, 4 for a 2-dimensional R*Tree, 6 for a
|
||||
# 3-dimensional R*Tree, and so forth.
|
||||
#
|
||||
# The second argument refered to above is the length of the list passed
|
||||
# as the 3rd parameter to the Tcl script.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE rt1 USING rtree(id, x1,x2);
|
||||
CREATE VIRTUAL TABLE rt2 USING rtree(id, x1,x2, y1,y2);
|
||||
CREATE VIRTUAL TABLE rt3 USING rtree(id, x1,x2, y1,y2, z1,z2);
|
||||
|
||||
INSERT INTO rt1 DEFAULT VALUES;
|
||||
INSERT INTO rt2 DEFAULT VALUES;
|
||||
INSERT INTO rt3 DEFAULT VALUES;
|
||||
}
|
||||
foreach {tn tbl nCoord} {
|
||||
1 rt1 2
|
||||
2 rt2 4
|
||||
3 rt3 6
|
||||
} {
|
||||
set ::box_geom [list]
|
||||
do_catchsql_test 1.$tn.1 "
|
||||
SELECT id FROM $tbl WHERE id MATCH box();
|
||||
" {1 {SQL logic error}}
|
||||
|
||||
do_test 1.$tn.2 {
|
||||
llength [lindex $::box_geom 0 2]
|
||||
} $nCoord
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-28051-48608 If xGeom returns anything other than
|
||||
# SQLITE_OK, then the r-tree query will abort with an error.
|
||||
proc box_geom {args} {
|
||||
error "an error!"
|
||||
}
|
||||
do_catchsql_test 2.0 {
|
||||
SELECT * FROM rt2 WHERE id MATCH box(22,23, 24,25);
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
INSERT INTO rt1 VALUES(10, 10, 10);
|
||||
INSERT INTO rt1 VALUES(11, 11, 11);
|
||||
INSERT INTO rt1 VALUES(12, 12, 12);
|
||||
INSERT INTO rt1 VALUES(13, 13, 13);
|
||||
INSERT INTO rt1 VALUES(14, 14, 14);
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-53759-57366 The exact same sqlite3_rtree_geometry
|
||||
# structure is used for every callback for same MATCH operator in the
|
||||
# same query.
|
||||
proc box_geom {args} {
|
||||
lappend ::ptr_list [lindex $args 4]
|
||||
return 0
|
||||
}
|
||||
set ::ptr_list [list]
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM rt1 WHERE id MATCH box(1,1);
|
||||
}
|
||||
do_test 3.2 {
|
||||
set val [lindex $::ptr_list 0]
|
||||
foreach p $::ptr_list {
|
||||
if {$p!=$val} {error "pointer mismatch"}
|
||||
}
|
||||
} {}
|
||||
|
||||
# EVIDENCE-OF: R-60247-35692 The contents of the sqlite3_rtree_geometry
|
||||
# structure are initialized by SQLite but are not subsequently modified.
|
||||
proc box_geom {args} {
|
||||
lappend ::box_geom [concat [lindex $args 0] [lrange $args 2 end-1]]
|
||||
if {[llength $::box_geom]==3} {
|
||||
return "zero"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
set ::box_geom [list]
|
||||
do_catchsql_test 3.2 {
|
||||
SELECT * FROM rt1 WHERE id MATCH box(1,1);
|
||||
} {1 {SQL logic error}}
|
||||
do_test 3.3 {
|
||||
set ::box_geom
|
||||
} [list {*}{
|
||||
{box {1.0 1.0} {0.0 0.0}}
|
||||
{box {1.0 1.0} {10.0 10.0}}
|
||||
{box {1.0 1.0} {11.0 11.0}}
|
||||
{box 0.0 {12.0 12.0}}
|
||||
}]
|
||||
|
||||
# EVIDENCE-OF: R-31246-29731 The pContext member of the
|
||||
# sqlite3_rtree_geometry structure is always set to a copy of the
|
||||
# pContext argument passed to sqlite3_rtree_geometry_callback() when the
|
||||
# callback is registered.
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE r1 USING rtree(id, minX,maxX, minY,maxY);
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<120
|
||||
)
|
||||
INSERT INTO r1 SELECT i,i,i+1, 200,201 FROM s;
|
||||
}
|
||||
set ctx [register_box_geom db box_geom]
|
||||
set ::box_geom [list]
|
||||
proc box_geom {args} {
|
||||
lappend ::box_geom [lindex $args 1]
|
||||
return ""
|
||||
}
|
||||
do_execsql_test 4.1 {
|
||||
SELECT count(*) FROM r1 WHERE id MATCH box(0,150,199,201)
|
||||
} 120
|
||||
do_test 4.2 {
|
||||
foreach g $::box_geom {
|
||||
if {$g!=$ctx} {error "pointer mismatch"}
|
||||
}
|
||||
} {}
|
||||
|
||||
# EVIDENCE-OF: R-09904-19077 The aParam[] array (size nParam) contains
|
||||
# the parameter values passed to the SQL function on the right-hand side
|
||||
# of the MATCH operator.
|
||||
proc box_geom {args} {
|
||||
set ::box_geom [lindex $args 2]
|
||||
}
|
||||
foreach {tn q vals} {
|
||||
1 "SELECT count(*) FROM r1 WHERE id MATCH box(1,2,3)" {1.0 2.0 3.0}
|
||||
2 "SELECT count(*) FROM r1 WHERE id MATCH box(10001)" {10001.0}
|
||||
3 "SELECT count(*) FROM r1 WHERE id MATCH box(-10001)" {-10001.0}
|
||||
} {
|
||||
do_catchsql_test 5.$tn.1 $q {1 {SQL logic error}}
|
||||
do_test 5.$tn.2 { set ::box_geom } $vals
|
||||
}
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE myrtree USING rtree(id, x1,x2);
|
||||
INSERT INTO myrtree VALUES(1, 1, 1);
|
||||
INSERT INTO myrtree VALUES(2, 2, 2);
|
||||
INSERT INTO myrtree VALUES(3, 3, 3);
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-44448-00687 The pUser and xDelUser members of the
|
||||
# sqlite3_rtree_geometry structure are initially set to NULL.
|
||||
set ::box_geom_calls 0
|
||||
proc box_geom {args} {
|
||||
incr ::box_geom_calls
|
||||
return user_is_zero
|
||||
}
|
||||
do_execsql_test 5.1.1 {
|
||||
SELECT * FROM myrtree WHERE id MATCH box(4, 5);
|
||||
}
|
||||
do_test 5.1.2 { set ::box_geom_calls } 3
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-55837-00155 The pUser variable may be set by the
|
||||
# callback implementation to any arbitrary value that may be useful to
|
||||
# subsequent invocations of the callback within the same query (for
|
||||
# example, a pointer to a complicated data structure used to test for
|
||||
# region intersection).
|
||||
#
|
||||
# EVIDENCE-OF: R-34745-08839 If the xDelUser variable is set to a
|
||||
# non-NULL value, then after the query has finished running SQLite
|
||||
# automatically invokes it with the value of the pUser variable as the
|
||||
# only argument.
|
||||
#
|
||||
set ::box_geom_calls 0
|
||||
proc box_geom {args} {
|
||||
incr ::box_geom_calls
|
||||
switch -- $::box_geom_calls {
|
||||
1 {
|
||||
return user_is_zero
|
||||
}
|
||||
2 {
|
||||
return [list user box_geom_finalizer]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
proc box_geom_finalizer {} {
|
||||
set ::box_geom_finalizer "::box_geom_calls is $::box_geom_calls"
|
||||
}
|
||||
do_execsql_test 5.1.1 {
|
||||
SELECT * FROM myrtree WHERE id MATCH box(4, 5);
|
||||
}
|
||||
do_test 5.1.2 { set ::box_geom_calls } 3
|
||||
do_test 5.1.3 {
|
||||
set ::box_geom_finalizer
|
||||
} {::box_geom_calls is 3}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-28176-28813 The xGeom callback always does a
|
||||
# depth-first search of the r-tree.
|
||||
#
|
||||
# For a breadth first search, final test case would return "B L" only.
|
||||
#
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE xyz USING rtree(x, x1,x2, y1,y2);
|
||||
WITH s(i) AS (
|
||||
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<15
|
||||
)
|
||||
INSERT INTO xyz SELECT NULL, one.i,one.i+1, two.i,two.i+1 FROM s one, s two;
|
||||
}
|
||||
do_execsql_test 6.1 {
|
||||
SELECT count(*) FROM xyz_node
|
||||
} {10}
|
||||
proc box_geom {args} {
|
||||
set coords [lindex $args 3]
|
||||
set area [expr {
|
||||
([lindex $coords 1]-[lindex $coords 0]) *
|
||||
([lindex $coords 3]-[lindex $coords 2])
|
||||
}]
|
||||
if {$area==1} {
|
||||
lappend ::box_geom_calls L
|
||||
} else {
|
||||
lappend ::box_geom_calls B
|
||||
}
|
||||
}
|
||||
set ::box_geom_calls [list]
|
||||
do_execsql_test 6.2 {
|
||||
SELECT count(*) FROM xyz WHERE x MATCH box(0,20,0,20)
|
||||
} 225
|
||||
do_test 6.3 {
|
||||
set prev ""
|
||||
set box_calls [list]
|
||||
foreach c $::box_geom_calls {
|
||||
if {$c!=$prev} {
|
||||
lappend ::box_calls $c
|
||||
set prev $c
|
||||
}
|
||||
}
|
||||
set ::box_calls
|
||||
} {B L B L B L B L B L B L B L B L B L}
|
||||
|
||||
|
||||
finish_test
|
||||
|
228
ext/rtree/test_rtreedoc.c
Normal file
228
ext/rtree/test_rtreedoc.c
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
** 2010 August 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.
|
||||
**
|
||||
*************************************************************************
|
||||
** Code for testing all sorts of SQLite interfaces. This code
|
||||
** is not included in the SQLite library.
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
#endif
|
||||
|
||||
/* Solely for the UNUSED_PARAMETER() macro. */
|
||||
#include "sqliteInt.h"
|
||||
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
|
||||
typedef struct BoxGeomCtx BoxGeomCtx;
|
||||
struct BoxGeomCtx {
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Obj *pScript;
|
||||
};
|
||||
|
||||
static void testDelUser(void *pCtx){
|
||||
BoxGeomCtx *p = (BoxGeomCtx*)pCtx;
|
||||
Tcl_EvalObjEx(p->interp, p->pScript, 0);
|
||||
Tcl_DecrRefCount(p->pScript);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
|
||||
static int invokeTclGeomCb(
|
||||
const char *zName,
|
||||
sqlite3_rtree_geometry *p,
|
||||
int nCoord,
|
||||
sqlite3_rtree_dbl *aCoord
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
if( p->pContext ){
|
||||
char aPtr[64];
|
||||
BoxGeomCtx *pCtx = (BoxGeomCtx*)p->pContext;
|
||||
Tcl_Interp *interp = pCtx->interp;
|
||||
Tcl_Obj *pScript = 0;
|
||||
Tcl_Obj *pParam = 0;
|
||||
Tcl_Obj *pCoord = 0;
|
||||
int ii;
|
||||
Tcl_Obj *pRes;
|
||||
|
||||
|
||||
pScript = Tcl_DuplicateObj(pCtx->pScript);
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(zName,-1));
|
||||
|
||||
sqlite3_snprintf(sizeof(aPtr)-1, aPtr, "%p", (void*)p->pContext);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(aPtr,-1));
|
||||
|
||||
pParam = Tcl_NewObj();
|
||||
for(ii=0; ii<p->nParam; ii++){
|
||||
Tcl_ListObjAppendElement(
|
||||
interp, pParam, Tcl_NewDoubleObj(p->aParam[ii])
|
||||
);
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pScript, pParam);
|
||||
|
||||
pCoord = Tcl_NewObj();
|
||||
for(ii=0; ii<nCoord; ii++){
|
||||
Tcl_ListObjAppendElement(interp, pCoord, Tcl_NewDoubleObj(aCoord[ii]));
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, pScript, pCoord);
|
||||
|
||||
sqlite3_snprintf(sizeof(aPtr)-1, aPtr, "%p", (void*)p);
|
||||
Tcl_ListObjAppendElement(interp, pScript, Tcl_NewStringObj(aPtr,-1));
|
||||
|
||||
rc = Tcl_EvalObjEx(interp, pScript, 0);
|
||||
if( rc!=TCL_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
int nObj = 0;
|
||||
Tcl_Obj **aObj = 0;
|
||||
|
||||
pRes = Tcl_GetObjResult(interp);
|
||||
if( Tcl_ListObjGetElements(interp, pRes, &nObj, &aObj) ) return TCL_ERROR;
|
||||
if( nObj>0 ){
|
||||
const char *zCmd = Tcl_GetString(aObj[0]);
|
||||
if( 0==sqlite3_stricmp(zCmd, "zero") ){
|
||||
p->aParam[0] = 0.0;
|
||||
p->nParam = 1;
|
||||
}
|
||||
else if( 0==sqlite3_stricmp(zCmd, "user") ){
|
||||
if( p->pUser || p->xDelUser ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
BoxGeomCtx *pCtx = sqlite3_malloc(sizeof(BoxGeomCtx));
|
||||
if( pCtx==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
pCtx->interp = interp;
|
||||
pCtx->pScript = Tcl_DuplicateObj(pRes);
|
||||
Tcl_IncrRefCount(pCtx->pScript);
|
||||
Tcl_ListObjReplace(interp, pCtx->pScript, 0, 1, 0, 0);
|
||||
p->pUser = (void*)pCtx;
|
||||
p->xDelUser = testDelUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( 0==sqlite3_stricmp(zCmd, "user_is_zero") ){
|
||||
if( p->pUser || p->xDelUser ) rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
# EVIDENCE-OF: R-00693-36727 The legacy xGeom callback is invoked with
|
||||
# four arguments.
|
||||
|
||||
# EVIDENCE-OF: R-50437-53270 The first argument is a pointer to an
|
||||
# sqlite3_rtree_geometry structure which provides information about how
|
||||
# the SQL function was invoked.
|
||||
|
||||
# EVIDENCE-OF: R-40260-16838 The number of coordinates is 2 for a
|
||||
# 1-dimensional R*Tree, 4 for a 2-dimensional R*Tree, 6 for a
|
||||
# 3-dimensional R*Tree, and so forth.
|
||||
|
||||
# EVIDENCE-OF: R-00090-24248 The third argument, aCoord[], is an array
|
||||
# of nCoord coordinates that defines a bounding box to be tested.
|
||||
|
||||
# EVIDENCE-OF: R-28207-40885 The last argument is a pointer into which
|
||||
# the callback result should be written.
|
||||
|
||||
*/
|
||||
static int box_geom(
|
||||
sqlite3_rtree_geometry *p, /* R-50437-53270 */
|
||||
int nCoord, /* R-02424-24769 */
|
||||
sqlite3_rtree_dbl *aCoord, /* R-00090-24248 */
|
||||
int *pRes /* R-28207-40885 */
|
||||
){
|
||||
int ii;
|
||||
|
||||
if( p->nParam!=nCoord ){
|
||||
invokeTclGeomCb("box", p, nCoord, aCoord);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
if( invokeTclGeomCb("box", p, nCoord, aCoord) ) return SQLITE_ERROR;
|
||||
|
||||
for(ii=0; ii<nCoord; ii+=2){
|
||||
if( aCoord[ii]>p->aParam[ii+1] || aCoord[ii+1]<p->aParam[ii] ){
|
||||
/* R-28207-40885 */
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* R-28207-40885 */
|
||||
*pRes = 1;
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int SQLITE_TCLAPI register_box_geom(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
|
||||
extern const char *sqlite3ErrName(int);
|
||||
sqlite3 *db;
|
||||
BoxGeomCtx *pCtx;
|
||||
char aPtr[64];
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
pCtx = (BoxGeomCtx*)ckalloc(sizeof(BoxGeomCtx*));
|
||||
pCtx->interp = interp;
|
||||
pCtx->pScript = Tcl_DuplicateObj(objv[2]);
|
||||
Tcl_IncrRefCount(pCtx->pScript);
|
||||
|
||||
sqlite3_rtree_geometry_callback(db, "box", box_geom, (void*)pCtx);
|
||||
|
||||
sqlite3_snprintf(64, aPtr, "%p", (void*)pCtx);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(aPtr, -1));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int SQLITE_TCLAPI register_box_query(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
|
||||
extern const char *sqlite3ErrName(int);
|
||||
sqlite3 *db;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_RTREE */
|
||||
|
||||
|
||||
int Sqlitetestrtreedoc_Init(Tcl_Interp *interp){
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
Tcl_CreateObjCommand(interp, "register_box_geom", register_box_geom, 0, 0);
|
||||
Tcl_CreateObjCommand(interp, "register_box_query", register_box_query, 0, 0);
|
||||
#endif /* SQLITE_ENABLE_RTREE */
|
||||
return TCL_OK;
|
||||
}
|
3
main.mk
3
main.mk
@ -387,7 +387,8 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/fts5/fts5_tcl.c \
|
||||
$(TOP)/ext/fts5/fts5_test_mi.c \
|
||||
$(TOP)/ext/fts5/fts5_test_tok.c
|
||||
$(TOP)/ext/fts5/fts5_test_tok.c \
|
||||
$(TOP)/ext/rtree/test_rtreedoc.c
|
||||
|
||||
|
||||
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
|
||||
|
60
manifest
60
manifest
@ -1,11 +1,11 @@
|
||||
C CLI\sprescanner\smade\sto\smatch\sSQLite's\srules\sfor\sdelimited\sidentifiers.\sTests\sbegun.
|
||||
D 2021-09-11T02:42:04.707
|
||||
C Sync\sw/trunk,\sfurther\sstreamline\sshell's\sresumable\sprescan.
|
||||
D 2021-09-18T21:35:22.366
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 83c348515cb62f6f2a2ddf3fd014113ff20564b776e1a614079722c88c6ff43d
|
||||
F Makefile.in 2a6e71e91f29e9eb0cb800b6500bbbfef31730d5c37eaadb6e8ea8a45e6ead21
|
||||
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
|
||||
F Makefile.msc 7dc32ba195639311ef4fa3d8f8ec218de37fde12d7ef5a33e9a7de921b0025ca
|
||||
F Makefile.msc b18738be47ba9293dbea2048fe1d5a737456fdc630361cc98ef2c2f73bf3395c
|
||||
F README.md 27fb76aa7eb57ed63a53bbba7292b6bf71f51125554f79f16b5d040edd1e6110
|
||||
F VERSION c6595fef606851f2bc3ebed6a7386c73751835fc909feab7c093739fa4b3c1d1
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@ -393,7 +393,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/geopoly.c 98d45533989e908bf65b43f36ff6eaad95a9ffe6f3b6b8658fbd47d45c58b10b
|
||||
F ext/rtree/rtree.c 0d1ef309e2bfbe469e3ee363ff9ea0420d5f7b9fcf15b5d9abb9d48a789c26f5
|
||||
F ext/rtree/rtree.c fb930d5bee9deb9efbfbed72be56a0d4e4950ab216284fb5ec1c9863d32a32fa
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 00792b030a4e188ff1b22e8530e8aa0452bb5dd81c2b18cb004afc7dc63e040e
|
||||
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
|
||||
@ -404,7 +404,7 @@ F ext/rtree/rtree6.test 9ce3691c1aac43070a9f194f0ebf54372db346c5a82241fd11b525ed
|
||||
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
|
||||
F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e
|
||||
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
|
||||
F ext/rtree/rtreeA.test ed2f1be9c06dde0b1ab93a95dd9e87eeaa02db2d30bcb4b9179b69ee3dc3319b
|
||||
F ext/rtree/rtreeA.test c0d8e91e25052d5f3fbda17632ca843b82ca13c4181fb6000a0d63bd2d7e70ce
|
||||
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
|
||||
F ext/rtree/rtreeC.test c4bfa9a61c6788c03e4a9ce40ab2cfc6100982559effd9842d1b658e1d47aa5f
|
||||
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
|
||||
@ -418,8 +418,11 @@ F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b5879
|
||||
F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35
|
||||
F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
|
||||
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
|
||||
F ext/rtree/rtreedoc.test 243cd3fdee1cb89e290e908ddde0cc0cfda0ccb85473c6d1b3c43e6260b14cac
|
||||
F ext/rtree/rtreedoc2.test 194ebb7d561452dcdc10bf03f44e30c082c2f0c14efeb07f5e02c7daf8284d93
|
||||
F ext/rtree/rtreefuzz001.test 0fc793f67897c250c5fde96cefee455a5e2fb92f4feeabde5b85ea02040790ee
|
||||
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
|
||||
F ext/rtree/test_rtreedoc.c 216f988e0b56474a3d42905653777772d3bdd413a7fe09a79e466b19296853b0
|
||||
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
||||
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
@ -466,7 +469,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 4e075c9618c06c55d1cc723087b0722f384247b6b8db1ac2cb161f864c953c97
|
||||
F main.mk 002e77acdfeb08d1d8f4d360b01e130aa243fb5701728e81fac9085794f27155
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@ -478,14 +481,14 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 38975b971a4c36dbcc8004c74b492213a851ab368d29238c531a22636508a5d4
|
||||
F src/alter.c a4e20094bb7e6ca5fa832779dc0b6aedfed4cab92144d3bc754fc6dfe6f26f34
|
||||
F src/analyze.c abbaaf7dca79d1c31c713500324fc0b55bf3eeac5b7b07001452a3d0f210de4f
|
||||
F src/attach.c a514e81758ba7b3a3a0501faf70af6cfc509de8810235db726cfc9f25165e929
|
||||
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
|
||||
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 742425ddcc06b2fef621b26edded28f77c7f9a9e96bdb3cb5217eb91444d99cf
|
||||
F src/btree.c bed4239e31772ed5486e947d8eaf3d38fcc76136e19d0383bad15609198419c2
|
||||
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
|
||||
F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
|
||||
F src/build.c 8fa6deebf8726339a5aafb322e9d79c48950b994f33f17460c5393ef593d202e
|
||||
@ -496,10 +499,10 @@ F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
|
||||
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
|
||||
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
|
||||
F src/delete.c 3ce6af6b64c8b476de51ccc32da0cb3142d42e65754e1d8118addf65b8bcba15
|
||||
F src/expr.c e98375fc63552cc8cdd36a41bdca3039cb603d9fe67abd9c9f40adae8405fbc5
|
||||
F src/expr.c ce736caaf1cf6d69789511e9fc5ed31013d9570d5d773cce909d396112d83843
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 1905af1821b88321e1bb9d6a69e704495b6844a9b6c29398d40117cc251e893c
|
||||
F src/func.c c224240cbc97fa5e9c4fe9acb128716cb835ca045532bca6951b7c45b020c56c
|
||||
F src/func.c 812ac5383067bed7150d8597e83c47b714d73db0e62af55811d1a145243e58e1
|
||||
F src/global.c 612ea60c9acbcb45754c2ed659b4a56936a06814718e969636fedc7e3b889808
|
||||
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
|
||||
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
|
||||
@ -515,7 +518,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c b93b8762ab999a29ae7751532dadf0a1ac78040308a5fb1d17fcc365171d67eb
|
||||
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
|
||||
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
F src/memdb.c 73622017aa03a3cabd1c4d6fca97eedada2155817dd0d74d6c1aeb42573b515d
|
||||
F src/memdb.c cd8cf3ee965db4a4ab4b5423b49a4ef810490b8ba828911e523325f2cce3ed1a
|
||||
F src/memjournal.c a85f0dc5c02a42453d0bc3819ecfb5666cb6433e5deefcd93ccbe05c9f088b83
|
||||
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
|
||||
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
|
||||
@ -531,7 +534,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c b11e4610769922253dec27d7af4a07ff84f65169d19bda5e9b12a152a706f7f5
|
||||
F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 95c255256b13827caf038c8f963d334784073f38ab6ef9d70371d9d04f3c43e0
|
||||
F src/pager.c 1ba6a843148282895d800aa69919553079946ef9a198a97e5d7c64442d10ed4c
|
||||
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
|
||||
F src/parse.y 86aa016b281f61d7664dd8cb7808cab8114d14cfaf362a9b9fc9ead8f33546b7
|
||||
F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b
|
||||
@ -544,16 +547,16 @@ F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b
|
||||
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
|
||||
F src/resolve.c 42b94d37a54200707a95566eff4f7e8a380e32d080016b699f23bd79a73a5028
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c b2c48dfc02b486fd2da2be1605503615958ba1997d40d994c2946975d0150a31
|
||||
F src/shell.c.in be7cd92c042b5e16bfd727404c5b2ec72c8e177ee2e092da6fe3ea031bbf8ece
|
||||
F src/select.c 030c3d07326708343208418c84da607752aebc13c92df929b7c68c7c08e7df54
|
||||
F src/shell.c.in 639c01f9a743ed73beb1d4b1e982b07b731c3801811d8344063f43b11008582a
|
||||
F src/sqlite.h.in 4e977a5e2ed1a9e8987ff65a2cab5f99a4298ebf040ea5ff636e1753339ff45a
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
|
||||
F src/sqliteInt.h 4cb73cc4b9b7705ccfd5bdfb9c248a9772a90ba52f743dbab90d13123babe36b
|
||||
F src/sqliteInt.h b62ee1fc9da3634616b969abe8b55fafcb540e4e7e5637ee2a2bb5fa477f4a38
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 05663f6b5010b044eac0ef22fc8fb5ea3406d2502700a898261683258042c88b
|
||||
F src/tclsqlite.c 428e813dabf82804bc13196af35a0c3c6ef4347fe557fa6717c5c66bba6e8520
|
||||
F src/test1.c 63761c2be2607f1b425fde991beda48aed384f8d67f2b4ee549174c88b433009
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
@ -597,7 +600,7 @@ F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
|
||||
F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a
|
||||
F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
|
||||
F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
|
||||
F src/test_tclsh.c eeafce33ad2136d57e5dec10f1e9a4347447eb72ffd504a1c7b9c6bfe2e71578
|
||||
F src/test_tclsh.c c4065ced25126e25c40122c5ff62dc89902ea617d72cdd27765151cdd7fcc477
|
||||
F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
|
||||
F src/test_thread.c 269ea9e1fa5828dba550eb26f619aa18aedbc29fd92f8a5f6b93521fbb74a61c
|
||||
F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43
|
||||
@ -616,7 +619,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
F src/util.c 3f27a1eae01c8bbbb8cdef2f26bd8e6a2a7db08106ef7c3dcc990787a5da6e86
|
||||
F src/vacuum.c 454973a59fb20bb982efc2df568a098616db6328a0491b6e84e2e07f7333db45
|
||||
F src/vdbe.c 39755f468a623af5e805c65a9ad7edb7c45fd78239fd58a319c7db8dfacc302b
|
||||
F src/vdbe.c a4b6736b22ccb9e875dea4350ea1666276500b4d6a27eed9c7d000faa1fea163
|
||||
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
|
||||
F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b
|
||||
F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5
|
||||
@ -635,7 +638,7 @@ F src/where.c da3981a12e9eb5a71d32bab60ac1957fd4aa337aaea07ca8019b01f8788f442a
|
||||
F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b
|
||||
F src/wherecode.c 0208553a0602146b5640747c0e3f7a8c785108c2d06a160b69f23491e9dc781e
|
||||
F src/whereexpr.c e5fdac355deef93a821f03b90770f92f2be833e92bbdeff8ac1b6c2ae1f74356
|
||||
F src/window.c 420167512050a0dfc0f0115b9f0c7d299da9759c9bb2ae83a61fb8d730a5707f
|
||||
F src/window.c a5417de85a13e1f47bfb33c0bae5ae0ded5d68b146f4986c3d89d10a04f2c262
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
|
||||
@ -853,12 +856,12 @@ F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
|
||||
F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
|
||||
F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145
|
||||
F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14
|
||||
F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
|
||||
F test/e_changes.test 6ba336a796db32f890e50197ab6a8fe5e6017e431fc9082702c246120cd58d55
|
||||
F test/e_createtable.test 7997c0106c181243e0ac7db7ba8b9ae7233d0bfb0188605650322a7a02ea326e
|
||||
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
|
||||
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
|
||||
F test/e_expr.test 6ba7a51ece7b3e7fc145f14f924eed25ebb5a24e7b8596c78f3838d372cf0385
|
||||
F test/e_expr.test e164550b9f8fd9c130283d1eae692dff9e2ba67f4dbd35f7325021f5d4b8851c
|
||||
F test/e_fkey.test 351c7b989e5aefcc339ef5fc78dc4738442bd247a392cd67d81c2881000c369e
|
||||
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
|
||||
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
|
||||
@ -866,7 +869,7 @@ F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a42
|
||||
F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
|
||||
F test/e_select.test c5425a423da06d0494119db8361ebfc6de302929f7546ca596d56224137e0360
|
||||
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
|
||||
F test/e_totalchanges.test 1daded1db6867991c10b53a18436b2602f41ad82a2b8c2e1ed5eb7d1ad15edaf
|
||||
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
|
||||
F test/e_uri.test 47eeb2960e74613f0f8722b2f13aef08fde69daa16e5380ac93df84dac8b1f72
|
||||
F test/e_vacuum.test 0d8832a2ce92350db0d0cff47b419465fd9772562e1f77ff7d9478c07a4980d2
|
||||
@ -1057,7 +1060,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
|
||||
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
|
||||
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
|
||||
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
|
||||
F test/fuzzdata8.db 270cbd5fc46e1bf05e1d8a9ca8a6283df2b9a6d204c6135b51a11f39db21e0da
|
||||
F test/fuzzdata8.db 81c9cfdd1c9dad84c1dbefb0a22cf31b685b8255031bc3827a6926412b0dc6f1
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
|
||||
@ -1448,7 +1451,7 @@ F test/tabfunc01.test d6821e7042e5653104dac0c63d75eff24a2415ab1889fc68b5db7fde59
|
||||
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
|
||||
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 316c96f974f0e6d7480186e3f5bb53413e5ee5480596544a97484888912a365c
|
||||
F test/tclsqlite.test 97cda6e4843e9f3e06c56f656d9b77ee0178fe1ee33fb09a6eeae8f125757ac1
|
||||
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
|
||||
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
|
||||
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
|
||||
@ -1922,8 +1925,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 968aed690ba7240f8a256f5ba679cc971f432ff9af0ff99744824af79b952545
|
||||
Q +2dd61dd97b0326b59b0bc3c83b4d4b9acf811c5acae4d1003e7525ba7a26daf5
|
||||
R 646f691d304e0a026b7432ed79848447
|
||||
P 15b105c520968855ad960d8929f80af9e9bedc155237af9af1956f7b546947f2 99d6bb22e8735681443bfe67287aa15ce2c57d0d63e304abf8aa01fde50dd021
|
||||
R 49a56387d26f2bce27d3217e1e0550b1
|
||||
U larrybr
|
||||
Z d0aaf8bc6b08262fe824a57812c4fb12
|
||||
Z f54f51b048cd8993f1718034d535befc
|
||||
|
@ -1 +1 @@
|
||||
15b105c520968855ad960d8929f80af9e9bedc155237af9af1956f7b546947f2
|
||||
9e00f9f7c03c192a3fb6b22851db0626515c59daac5ce6520229c42c838bf5b7
|
@ -647,8 +647,7 @@ void sqlite3AlterRenameColumn(
|
||||
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
|
||||
"sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
|
||||
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' "
|
||||
" AND (type != 'index' OR tbl_name = %Q)"
|
||||
" AND sql NOT LIKE 'create virtual%%'",
|
||||
" AND (type != 'index' OR tbl_name = %Q)",
|
||||
zDb,
|
||||
zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1,
|
||||
pTab->zName
|
||||
@ -1498,7 +1497,7 @@ static void renameColumnFunc(
|
||||
sqlite3WalkSelect(&sWalker, pSelect);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
|
||||
}else if( ALWAYS(IsOrdinaryTable(sParse.pNewTable)) ){
|
||||
}else if( IsOrdinaryTable(sParse.pNewTable) ){
|
||||
/* A regular table */
|
||||
int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
|
||||
FKey *pFKey;
|
||||
|
@ -7096,7 +7096,7 @@ static int rebuildPage(
|
||||
|
||||
assert( i<iEnd );
|
||||
j = get2byte(&aData[hdr+5]);
|
||||
if( j>(u32)usableSize ){ j = 0; }
|
||||
if( NEVER(j>(u32)usableSize) ){ j = 0; }
|
||||
memcpy(&pTmp[j], &aData[j], usableSize - j);
|
||||
|
||||
for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
|
||||
@ -7327,7 +7327,7 @@ static int editPage(
|
||||
|
||||
pData = &aData[get2byteNotZero(&aData[hdr+5])];
|
||||
if( pData<pBegin ) goto editpage_fail;
|
||||
if( pData>pPg->aDataEnd ) goto editpage_fail;
|
||||
if( NEVER(pData>pPg->aDataEnd) ) goto editpage_fail;
|
||||
|
||||
/* Add cells to the start of the page */
|
||||
if( iNew<iOld ){
|
||||
@ -8733,7 +8733,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
|
||||
do{
|
||||
rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
|
||||
if( rc ) return rc;
|
||||
if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){
|
||||
if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || pPage->isInit ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
if( iOffset+ovflPageSize<(u32)nTotal ){
|
||||
|
@ -3866,6 +3866,7 @@ static int exprCodeInlineFunction(
|
||||
** Test-only SQL functions that are only usable if enabled
|
||||
** via SQLITE_TESTCTRL_INTERNAL_FUNCTIONS
|
||||
*/
|
||||
#if !defined(SQLITE_UNTESTABLE)
|
||||
case INLINEFUNC_expr_compare: {
|
||||
/* Compare two expressions using sqlite3ExprCompare() */
|
||||
assert( nFarg==2 );
|
||||
@ -3899,7 +3900,6 @@ static int exprCodeInlineFunction(
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
case INLINEFUNC_affinity: {
|
||||
/* The AFFINITY() function evaluates to a string that describes
|
||||
** the type affinity of the argument. This is used for testing of
|
||||
@ -3913,7 +3913,7 @@ static int exprCodeInlineFunction(
|
||||
(aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_UNTESTABLE) */
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
16
src/func.c
16
src/func.c
@ -571,9 +571,9 @@ static void last_insert_rowid(
|
||||
/*
|
||||
** Implementation of the changes() SQL function.
|
||||
**
|
||||
** IMP: R-62073-11209 The changes() SQL function is a wrapper
|
||||
** around the sqlite3_changes64() C/C++ function and hence follows the same
|
||||
** rules for counting changes.
|
||||
** IMP: R-32760-32347 The changes() SQL function is a wrapper
|
||||
** around the sqlite3_changes64() C/C++ function and hence follows the
|
||||
** same rules for counting changes.
|
||||
*/
|
||||
static void changes(
|
||||
sqlite3_context *context,
|
||||
@ -596,8 +596,8 @@ static void total_changes(
|
||||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
/* IMP: R-52756-41993 This function was a wrapper around the
|
||||
** sqlite3_total_changes() C/C++ interface. */
|
||||
/* IMP: R-11217-42568 This function is a wrapper around the
|
||||
** sqlite3_total_changes64() C/C++ interface. */
|
||||
sqlite3_result_int64(context, sqlite3_total_changes64(db));
|
||||
}
|
||||
|
||||
@ -2123,12 +2123,12 @@ void sqlite3RegisterBuiltinFunctions(void){
|
||||
*/
|
||||
static FuncDef aBuiltinFunc[] = {
|
||||
/***** Functions only available with SQLITE_TESTCTRL_INTERNAL_FUNCTIONS *****/
|
||||
#if !defined(SQLITE_UNTESTABLE)
|
||||
TEST_FUNC(implies_nonnull_row, 2, INLINEFUNC_implies_nonnull_row, 0),
|
||||
TEST_FUNC(expr_compare, 2, INLINEFUNC_expr_compare, 0),
|
||||
TEST_FUNC(expr_implies_expr, 2, INLINEFUNC_expr_implies_expr, 0),
|
||||
#ifdef SQLITE_DEBUG
|
||||
TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
|
||||
#endif
|
||||
TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
|
||||
#endif /* !defined(SQLITE_UNTESTABLE) */
|
||||
/***** Regular functions *****/
|
||||
#ifdef SQLITE_SOUNDEX
|
||||
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
|
||||
|
@ -508,7 +508,7 @@ static int memdbOpen(
|
||||
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
|
||||
return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFd, flags, pOutFlags);
|
||||
}
|
||||
memset(pFile, 0, sizeof(*p));
|
||||
memset(pFile, 0, sizeof(*pFile));
|
||||
szName = sqlite3Strlen30(zName);
|
||||
if( szName>1 && zName[0]=='/' ){
|
||||
int i;
|
||||
|
12
src/pager.c
12
src/pager.c
@ -679,8 +679,8 @@ struct Pager {
|
||||
i16 nReserve; /* Number of unused bytes at end of each page */
|
||||
u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
|
||||
u32 sectorSize; /* Assumed sector size during rollback */
|
||||
int pageSize; /* Number of bytes in a page */
|
||||
Pgno mxPgno; /* Maximum allowed size of the database */
|
||||
i64 pageSize; /* Number of bytes in a page */
|
||||
i64 journalSizeLimit; /* Size limit for persistent journal files */
|
||||
char *zFilename; /* Name of the database file */
|
||||
char *zJournal; /* Name of the journal file */
|
||||
@ -6737,8 +6737,8 @@ int sqlite3PagerRefcount(Pager *pPager){
|
||||
** used by the pager and its associated cache.
|
||||
*/
|
||||
int sqlite3PagerMemUsed(Pager *pPager){
|
||||
int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
|
||||
+ 5*sizeof(void*);
|
||||
int perPageSize = pPager->pageSize + pPager->nExtra
|
||||
+ (int)(sizeof(PgHdr) + 5*sizeof(void*));
|
||||
return perPageSize*sqlite3PcachePagecount(pPager->pPCache)
|
||||
+ sqlite3MallocSize(pPager)
|
||||
+ pPager->pageSize;
|
||||
@ -6932,14 +6932,14 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
|
||||
}
|
||||
pPager->nSavepoint = nNew;
|
||||
|
||||
/* If this is a release of the outermost savepoint, truncate
|
||||
** the sub-journal to zero bytes in size. */
|
||||
/* Truncate the sub-journal so that it only includes the parts
|
||||
** that are still in use. */
|
||||
if( op==SAVEPOINT_RELEASE ){
|
||||
PagerSavepoint *pRel = &pPager->aSavepoint[nNew];
|
||||
if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){
|
||||
/* Only truncate if it is an in-memory sub-journal. */
|
||||
if( sqlite3JournalIsInMemory(pPager->sjfd) ){
|
||||
i64 sz = (pPager->pageSize+4)*pRel->iSubRec;
|
||||
i64 sz = (pPager->pageSize+4)*(i64)pRel->iSubRec;
|
||||
rc = sqlite3OsTruncate(pPager->sjfd, sz);
|
||||
assert( rc==SQLITE_OK );
|
||||
}
|
||||
|
@ -347,6 +347,9 @@ static void addWhereTerm(
|
||||
pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
|
||||
|
||||
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
|
||||
assert( pE2!=0 || pEq==0 ); /* Due to db->mallocFailed test
|
||||
** in sqlite3DbMallocRawNN() called from
|
||||
** sqlite3PExpr(). */
|
||||
if( pEq && isOuterJoin ){
|
||||
ExprSetProperty(pEq, EP_FromJoin);
|
||||
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
|
||||
|
140
src/shell.c.in
140
src/shell.c.in
@ -635,19 +635,38 @@ static int strlenChar(const char *z){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if zFile does not exist or if it is not an ordinary file.
|
||||
** Return open FILE * if zFile exists, can be opened for read
|
||||
** and is an ordinary file or a character stream source.
|
||||
** Otherwise return 0.
|
||||
*/
|
||||
static FILE * openChrSource(const char *zFile){
|
||||
#ifdef _WIN32
|
||||
# define notNormalFile(X) 0
|
||||
struct _stat x = {0};
|
||||
# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
|
||||
/* On Windows, open first, then check the stream nature. This order
|
||||
** is necessary because _stat() and sibs, when checking a named pipe,
|
||||
** effectively break the pipe as its supplier sees it. */
|
||||
FILE *rv = fopen(zFile, "rb");
|
||||
if( rv==0 ) return 0;
|
||||
if( _fstat(_fileno(rv), &x) != 0
|
||||
|| !STAT_CHR_SRC(x.st_mode)){
|
||||
fclose(rv);
|
||||
rv = 0;
|
||||
}
|
||||
return rv;
|
||||
#else
|
||||
static int notNormalFile(const char *zFile){
|
||||
struct stat x;
|
||||
int rc;
|
||||
memset(&x, 0, sizeof(x));
|
||||
rc = stat(zFile, &x);
|
||||
return rc || !S_ISREG(x.st_mode);
|
||||
}
|
||||
struct stat x = {0};
|
||||
int rc = stat(zFile, &x);
|
||||
# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
|
||||
if( rc!=0 ) return 0;
|
||||
if( STAT_CHR_SRC(x.st_mode) ){
|
||||
return fopen(zFile, "rb");
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#undef STAT_CHR_SRC
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine reads a line of text from FILE in, stores
|
||||
@ -1203,7 +1222,7 @@ struct ShellState {
|
||||
#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
|
||||
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
|
||||
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
|
||||
#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
|
||||
#define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */
|
||||
#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
|
||||
#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
|
||||
|
||||
@ -9239,7 +9258,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
pclose(p->in);
|
||||
}
|
||||
#endif
|
||||
}else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
|
||||
}else if( (p->in = openChrSource(azArg[1]))==0 ){
|
||||
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
|
||||
rc = 1;
|
||||
}else{
|
||||
@ -10601,18 +10620,15 @@ meta_command_exit:
|
||||
/* Line scan result and intermediate states (supporting scan resumption)
|
||||
*/
|
||||
typedef enum {
|
||||
QSS_InPlain = 0, QSS_InQuote = 1, QSS_InBlockComment = 2,
|
||||
QSS_NoDark = 0, QSS_HasDark = 1<<2, QSS_EndingSemi = 1<<3,
|
||||
QSS_ScanMask = 0x3, QSS_DarkMask = 1<<2,
|
||||
QSS_CharShift = 4, QSS_StateMask = ((1<<QSS_CharShift)-1),
|
||||
QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
|
||||
QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
|
||||
QSS_Start = 0
|
||||
} QuickScanState;
|
||||
#define QSS_STATE(qss) ((qss) & QSS_ScanMask)
|
||||
#define QSS_SETV(qss, newst) (newst | ((qss) & (QSS_StateMask^QSS_ScanMask)))
|
||||
#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_NoDark)
|
||||
#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
|
||||
#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
|
||||
#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
|
||||
#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
|
||||
#define QSS_SEMITERM(qss) \
|
||||
(((qss)&(QSS_ScanMask|QSS_EndingSemi))==QSS_EndingSemi)
|
||||
#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
|
||||
|
||||
/*
|
||||
** Scan line for classification to guide shell's handling.
|
||||
@ -10621,69 +10637,69 @@ typedef enum {
|
||||
*/
|
||||
static QuickScanState quickscan(char *zLine, QuickScanState qss){
|
||||
char cin;
|
||||
switch( QSS_STATE(qss) ){
|
||||
case QSS_InPlain:
|
||||
InPlainSet:
|
||||
qss = QSS_SETV(qss, QSS_InPlain);
|
||||
char cWait = (char)qss; /* intentional narrowing loss */
|
||||
if( cWait==0 ){
|
||||
PlainScan:
|
||||
while (cin = *zLine++){
|
||||
if( IsSpace(cin) )
|
||||
continue;
|
||||
switch (cin){
|
||||
case '-':
|
||||
if( *zLine=='-' ){
|
||||
while((cin = *++zLine)!=0 ){
|
||||
if( cin=='\n')
|
||||
continue;
|
||||
}
|
||||
return qss;
|
||||
}
|
||||
break;
|
||||
if( *zLine!='-' )
|
||||
break;
|
||||
while((cin = *++zLine)!=0 )
|
||||
if( cin=='\n')
|
||||
goto PlainScan;
|
||||
return qss;
|
||||
case ';':
|
||||
qss |= QSS_EndingSemi;
|
||||
continue;
|
||||
case '/':
|
||||
if( *zLine=='*' ){
|
||||
++zLine;
|
||||
qss = QSS_SETV(qss, QSS_InBlockComment);
|
||||
goto InBlockComment;
|
||||
cWait = '*';
|
||||
qss = QSS_SETV(qss, cWait);
|
||||
goto TermScan;
|
||||
}
|
||||
break;
|
||||
case '[':
|
||||
cin = ']';
|
||||
/* fall thru */
|
||||
case '`': case '\'': case '"':
|
||||
qss = qss & ~QSS_EndingSemi | QSS_HasDark;
|
||||
qss = QSS_SETV(qss, QSS_InQuote) | (cin<<QSS_CharShift);
|
||||
goto InQuote;
|
||||
cWait = cin;
|
||||
qss = QSS_HasDark | cWait;
|
||||
goto TermScan;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
qss = qss & ~QSS_EndingSemi | QSS_HasDark;
|
||||
qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
|
||||
}
|
||||
break;
|
||||
case QSS_InQuote:
|
||||
InQuote: {
|
||||
char cLeave = qss >> QSS_CharShift;
|
||||
while (cin = *zLine++){
|
||||
if( cin==cLeave ){
|
||||
if(*zLine==cLeave && cLeave!=']')
|
||||
}else{
|
||||
TermScan:
|
||||
while (cin = *zLine++){
|
||||
if( cin==cWait ){
|
||||
switch( cWait ){
|
||||
case '*':
|
||||
if( *zLine != '/' )
|
||||
continue;
|
||||
++zLine;
|
||||
cWait = 0;
|
||||
qss = QSS_SETV(qss, 0);
|
||||
goto PlainScan;
|
||||
case '`': case '\'': case '"':
|
||||
if(*zLine==cWait){
|
||||
++zLine;
|
||||
else
|
||||
goto InPlainSet;
|
||||
continue;
|
||||
}
|
||||
/* fall thru */
|
||||
case ']':
|
||||
cWait = 0;
|
||||
qss = QSS_SETV(qss, 0);
|
||||
goto PlainScan;
|
||||
default: assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QSS_InBlockComment:
|
||||
InBlockComment:
|
||||
while (cin = *zLine++){
|
||||
if( cin=='*' && *zLine=='/' ){
|
||||
++zLine;
|
||||
goto InPlainSet;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
return qss;
|
||||
}
|
||||
@ -10784,7 +10800,7 @@ static int process_input(ShellState *p){
|
||||
int rc; /* Error code */
|
||||
int errCnt = 0; /* Number of errors seen */
|
||||
int startline = 0; /* Line number for start of current input */
|
||||
QuickScanState qss = QSS_InPlain; /* Accumulated line status (so far) */
|
||||
QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
|
||||
|
||||
p->lineno = 0;
|
||||
while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
|
||||
@ -10800,7 +10816,7 @@ static int process_input(ShellState *p){
|
||||
seenInterrupt = 0;
|
||||
}
|
||||
p->lineno++;
|
||||
if( QSS_STATE(qss)==QSS_InPlain
|
||||
if( QSS_INPLAIN(qss)
|
||||
&& line_is_command_terminator(zLine)
|
||||
&& line_is_complete(zSql, nSql) ){
|
||||
memcpy(zLine,";",2);
|
||||
@ -11502,8 +11518,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
"%s",cmdline_option_value(argc,argv,++i));
|
||||
}else if( strcmp(z,"-header")==0 ){
|
||||
data.showHeader = 1;
|
||||
}else if( strcmp(z,"-noheader")==0 ){
|
||||
ShellSetFlag(&data, SHFLG_HeaderSet);
|
||||
}else if( strcmp(z,"-noheader")==0 ){
|
||||
data.showHeader = 0;
|
||||
ShellSetFlag(&data, SHFLG_HeaderSet);
|
||||
}else if( strcmp(z,"-echo")==0 ){
|
||||
ShellSetFlag(&data, SHFLG_Echo);
|
||||
}else if( strcmp(z,"-eqp")==0 ){
|
||||
|
@ -4985,7 +4985,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
# define sqlite3VtabClear(Y)
|
||||
# define sqlite3VtabClear(D,T)
|
||||
# define sqlite3VtabSync(X,Y) SQLITE_OK
|
||||
# define sqlite3VtabRollback(X)
|
||||
# define sqlite3VtabCommit(X)
|
||||
|
130
src/tclsqlite.c
130
src/tclsqlite.c
@ -181,6 +181,7 @@ struct SqliteDb {
|
||||
int nVMStep; /* Another statistic for most recent operation */
|
||||
int nTransaction; /* Number of nested [transaction] methods */
|
||||
int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */
|
||||
int nRef; /* Delete object when this reaches 0 */
|
||||
#ifdef SQLITE_TEST
|
||||
int bLegacyPrepare; /* True to use sqlite3_prepare() */
|
||||
#endif
|
||||
@ -517,64 +518,84 @@ static void flushStmtCache(SqliteDb *pDb){
|
||||
pDb->stmtList = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Increment the reference counter on the SqliteDb object. The reference
|
||||
** should be released by calling delDatabaseRef().
|
||||
*/
|
||||
static void addDatabaseRef(SqliteDb *pDb){
|
||||
pDb->nRef++;
|
||||
}
|
||||
|
||||
/*
|
||||
** Decrement the reference counter associated with the SqliteDb object.
|
||||
** If it reaches zero, delete the object.
|
||||
*/
|
||||
static void delDatabaseRef(SqliteDb *pDb){
|
||||
assert( pDb->nRef>0 );
|
||||
pDb->nRef--;
|
||||
if( pDb->nRef==0 ){
|
||||
flushStmtCache(pDb);
|
||||
closeIncrblobChannels(pDb);
|
||||
sqlite3_close(pDb->db);
|
||||
while( pDb->pFunc ){
|
||||
SqlFunc *pFunc = pDb->pFunc;
|
||||
pDb->pFunc = pFunc->pNext;
|
||||
assert( pFunc->pDb==pDb );
|
||||
Tcl_DecrRefCount(pFunc->pScript);
|
||||
Tcl_Free((char*)pFunc);
|
||||
}
|
||||
while( pDb->pCollate ){
|
||||
SqlCollate *pCollate = pDb->pCollate;
|
||||
pDb->pCollate = pCollate->pNext;
|
||||
Tcl_Free((char*)pCollate);
|
||||
}
|
||||
if( pDb->zBusy ){
|
||||
Tcl_Free(pDb->zBusy);
|
||||
}
|
||||
if( pDb->zTrace ){
|
||||
Tcl_Free(pDb->zTrace);
|
||||
}
|
||||
if( pDb->zTraceV2 ){
|
||||
Tcl_Free(pDb->zTraceV2);
|
||||
}
|
||||
if( pDb->zProfile ){
|
||||
Tcl_Free(pDb->zProfile);
|
||||
}
|
||||
if( pDb->zBindFallback ){
|
||||
Tcl_Free(pDb->zBindFallback);
|
||||
}
|
||||
if( pDb->zAuth ){
|
||||
Tcl_Free(pDb->zAuth);
|
||||
}
|
||||
if( pDb->zNull ){
|
||||
Tcl_Free(pDb->zNull);
|
||||
}
|
||||
if( pDb->pUpdateHook ){
|
||||
Tcl_DecrRefCount(pDb->pUpdateHook);
|
||||
}
|
||||
if( pDb->pPreUpdateHook ){
|
||||
Tcl_DecrRefCount(pDb->pPreUpdateHook);
|
||||
}
|
||||
if( pDb->pRollbackHook ){
|
||||
Tcl_DecrRefCount(pDb->pRollbackHook);
|
||||
}
|
||||
if( pDb->pWalHook ){
|
||||
Tcl_DecrRefCount(pDb->pWalHook);
|
||||
}
|
||||
if( pDb->pCollateNeeded ){
|
||||
Tcl_DecrRefCount(pDb->pCollateNeeded);
|
||||
}
|
||||
Tcl_Free((char*)pDb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** TCL calls this procedure when an sqlite3 database command is
|
||||
** deleted.
|
||||
*/
|
||||
static void SQLITE_TCLAPI DbDeleteCmd(void *db){
|
||||
SqliteDb *pDb = (SqliteDb*)db;
|
||||
flushStmtCache(pDb);
|
||||
closeIncrblobChannels(pDb);
|
||||
sqlite3_close(pDb->db);
|
||||
while( pDb->pFunc ){
|
||||
SqlFunc *pFunc = pDb->pFunc;
|
||||
pDb->pFunc = pFunc->pNext;
|
||||
assert( pFunc->pDb==pDb );
|
||||
Tcl_DecrRefCount(pFunc->pScript);
|
||||
Tcl_Free((char*)pFunc);
|
||||
}
|
||||
while( pDb->pCollate ){
|
||||
SqlCollate *pCollate = pDb->pCollate;
|
||||
pDb->pCollate = pCollate->pNext;
|
||||
Tcl_Free((char*)pCollate);
|
||||
}
|
||||
if( pDb->zBusy ){
|
||||
Tcl_Free(pDb->zBusy);
|
||||
}
|
||||
if( pDb->zTrace ){
|
||||
Tcl_Free(pDb->zTrace);
|
||||
}
|
||||
if( pDb->zTraceV2 ){
|
||||
Tcl_Free(pDb->zTraceV2);
|
||||
}
|
||||
if( pDb->zProfile ){
|
||||
Tcl_Free(pDb->zProfile);
|
||||
}
|
||||
if( pDb->zBindFallback ){
|
||||
Tcl_Free(pDb->zBindFallback);
|
||||
}
|
||||
if( pDb->zAuth ){
|
||||
Tcl_Free(pDb->zAuth);
|
||||
}
|
||||
if( pDb->zNull ){
|
||||
Tcl_Free(pDb->zNull);
|
||||
}
|
||||
if( pDb->pUpdateHook ){
|
||||
Tcl_DecrRefCount(pDb->pUpdateHook);
|
||||
}
|
||||
if( pDb->pPreUpdateHook ){
|
||||
Tcl_DecrRefCount(pDb->pPreUpdateHook);
|
||||
}
|
||||
if( pDb->pRollbackHook ){
|
||||
Tcl_DecrRefCount(pDb->pRollbackHook);
|
||||
}
|
||||
if( pDb->pWalHook ){
|
||||
Tcl_DecrRefCount(pDb->pWalHook);
|
||||
}
|
||||
if( pDb->pCollateNeeded ){
|
||||
Tcl_DecrRefCount(pDb->pCollateNeeded);
|
||||
}
|
||||
Tcl_Free((char*)pDb);
|
||||
delDatabaseRef(pDb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1246,6 +1267,7 @@ static int SQLITE_TCLAPI DbTransPostCmd(
|
||||
}
|
||||
pDb->disableAuth--;
|
||||
|
||||
delDatabaseRef(pDb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1579,6 +1601,7 @@ static void dbEvalInit(
|
||||
Tcl_IncrRefCount(pArray);
|
||||
}
|
||||
p->evalFlags = evalFlags;
|
||||
addDatabaseRef(p->pDb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1719,6 +1742,7 @@ static void dbEvalFinalize(DbEvalContext *p){
|
||||
}
|
||||
Tcl_DecrRefCount(p->pSql);
|
||||
dbReleaseColumnNames(p);
|
||||
delDatabaseRef(p->pDb);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3435,6 +3459,7 @@ deserialize_error:
|
||||
** opened above. If not using NRE, evaluate the script directly, then
|
||||
** call function DbTransPostCmd() to commit (or rollback) the transaction
|
||||
** or savepoint. */
|
||||
addDatabaseRef(pDb); /* DbTransPostCmd() calls delDatabaseRef() */
|
||||
if( DbUseNre() ){
|
||||
Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
|
||||
(void)Tcl_NREvalObj(interp, pScript, 0);
|
||||
@ -3842,6 +3867,7 @@ static int SQLITE_TCLAPI DbMain(
|
||||
}else{
|
||||
Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
|
||||
}
|
||||
p->nRef = 1;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,7 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
|
||||
extern int Sqlitetestintarray_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestvfs_Init(Tcl_Interp *);
|
||||
extern int Sqlitetestrtree_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestrtreedoc_Init(Tcl_Interp*);
|
||||
extern int Sqlitequota_Init(Tcl_Interp*);
|
||||
extern int Sqlitemultiplex_Init(Tcl_Interp*);
|
||||
extern int SqliteSuperlock_Init(Tcl_Interp*);
|
||||
@ -156,6 +157,7 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
|
||||
Sqlitetestintarray_Init(interp);
|
||||
Sqlitetestvfs_Init(interp);
|
||||
Sqlitetestrtree_Init(interp);
|
||||
Sqlitetestrtreedoc_Init(interp);
|
||||
Sqlitequota_Init(interp);
|
||||
Sqlitemultiplex_Init(interp);
|
||||
SqliteSuperlock_Init(interp);
|
||||
|
@ -8367,6 +8367,11 @@ abort_due_to_error:
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
assert( rc );
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( db->flags & SQLITE_VdbeTrace ){
|
||||
printf("ABORT-due-to-error. rc=%d\n", rc);
|
||||
}
|
||||
#endif
|
||||
if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
|
||||
}
|
||||
|
@ -1066,6 +1066,9 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
("New window-function subquery in FROM clause of (%u/%p)\n",
|
||||
p->selId, p));
|
||||
p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
|
||||
assert( pSub!=0 || p->pSrc==0 ); /* Due to db->mallocFailed test inside
|
||||
** of sqlite3DbMallocRawNN() called from
|
||||
** sqlite3SrcListAppend() */
|
||||
if( p->pSrc ){
|
||||
Table *pTab2;
|
||||
p->pSrc->a[0].pSelect = pSub;
|
||||
|
@ -25,10 +25,10 @@ proc do_changes_test {tn sql res} {
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-15996-49369 This function returns the number of rows
|
||||
# modified, inserted or deleted by the most recently completed INSERT,
|
||||
# UPDATE or DELETE statement on the database connection specified by the
|
||||
# only parameter.
|
||||
# EVIDENCE-OF: R-58361-29089 The changes() function returns the number
|
||||
# of database rows that were changed or inserted or deleted by the most
|
||||
# recently completed INSERT, DELETE, or UPDATE statement, exclusive of
|
||||
# statements in lower-level triggers.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
@ -108,7 +108,7 @@ foreach {tn schema} {
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-44877-05564 Executing any other type of SQL statement
|
||||
# X-EVIDENCE-OF: R-44877-05564 Executing any other type of SQL statement
|
||||
# does not modify the value returned by this function.
|
||||
#
|
||||
reset_db
|
||||
|
@ -84,12 +84,12 @@ db func regexp -argcount 2 regexfunc
|
||||
# in the documentation exist and that the relative precedences of the
|
||||
# operators are also as the documentation suggests.
|
||||
#
|
||||
# EVIDENCE-OF: R-15514-65163 SQLite understands the following binary
|
||||
# X-EVIDENCE-OF: R-15514-65163 SQLite understands the following binary
|
||||
# operators, in order from highest to lowest precedence: || * / % + -
|
||||
# << >> & | < <= > >= = == != <> IS IS
|
||||
# NOT IN LIKE GLOB MATCH REGEXP AND OR
|
||||
#
|
||||
# EVIDENCE-OF: R-38759-38789 Operators IS and IS NOT have the same
|
||||
# X-EVIDENCE-OF: R-38759-38789 Operators IS and IS NOT have the same
|
||||
# precedence as =.
|
||||
#
|
||||
|
||||
@ -180,7 +180,7 @@ do_execsql_test e_expr-1.6 {
|
||||
# Check that the four unary prefix operators mentioned in the
|
||||
# documentation exist.
|
||||
#
|
||||
# EVIDENCE-OF: R-13958-53419 Supported unary prefix operators are these:
|
||||
# X-EVIDENCE-OF: R-13958-53419 Supported unary prefix operators are these:
|
||||
# - + ~ NOT
|
||||
#
|
||||
do_execsql_test e_expr-2.1 { SELECT - 10 } {-10}
|
||||
@ -368,7 +368,7 @@ db collate reverse reverse_collate
|
||||
# EVIDENCE-OF: R-59577-33471 The COLLATE operator is a unary postfix
|
||||
# operator that assigns a collating sequence to an expression.
|
||||
#
|
||||
# EVIDENCE-OF: R-36231-30731 The COLLATE operator has a higher
|
||||
# X-EVIDENCE-OF: R-36231-30731 The COLLATE operator has a higher
|
||||
# precedence (binds more tightly) than any binary operator and any unary
|
||||
# prefix operator except "~".
|
||||
#
|
||||
@ -860,7 +860,7 @@ foreach {tn x expr res nEval} {
|
||||
} [list $nEval $res]
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-05155-34454 The precedence of the BETWEEN operator is
|
||||
# X-EVIDENCE-OF: R-05155-34454 The precedence of the BETWEEN operator is
|
||||
# the same as the precedence as operators == and != and LIKE and groups
|
||||
# left to right.
|
||||
#
|
||||
|
@ -32,10 +32,9 @@ do_execsql_test 1.0 {
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-65438-26258 This function returns the total number of
|
||||
# rows inserted, modified or deleted by all INSERT, UPDATE or DELETE
|
||||
# statements completed since the database connection was opened,
|
||||
# including those executed as part of trigger programs.
|
||||
# EVIDENCE-OF: R-38914-26427 The total_changes() function returns the
|
||||
# number of row changes caused by INSERT, UPDATE or DELETE statements
|
||||
# since the current database connection was opened.
|
||||
#
|
||||
# 1.1.*: different types of I/U/D statements,
|
||||
# 1.2.*: trigger programs.
|
||||
|
Binary file not shown.
@ -848,4 +848,40 @@ do_catchsql_test 19.911 {
|
||||
} {1 {invalid command name "bind_fallback_does_not_exist"}}
|
||||
db bind_fallback {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_test 20.0 {
|
||||
db transaction {
|
||||
db close
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 20.1 {
|
||||
sqlite3 db test.db
|
||||
set rc [catch {
|
||||
db eval {SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3} { db close }
|
||||
} msg]
|
||||
list $rc $msg
|
||||
} {1 {invalid command name "db"}}
|
||||
|
||||
|
||||
proc closedb {} {
|
||||
db close
|
||||
return 10
|
||||
}
|
||||
proc func1 {} { return 1 }
|
||||
|
||||
sqlite3 db test.db
|
||||
db func closedb closedb
|
||||
db func func1 func1
|
||||
|
||||
do_test 20.2 {
|
||||
set rc [catch {
|
||||
db eval {
|
||||
SELECT closedb(),func1() UNION ALL SELECT 20,30 UNION ALL SELECT 30,40
|
||||
}
|
||||
} msg]
|
||||
list $rc $msg
|
||||
} {0 {10 1 20 30 30 40}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user