aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyze.c1
-rw-r--r--src/expr.c126
-rw-r--r--src/pager.c1
-rw-r--r--src/pcache.c1
-rw-r--r--src/pcache1.c6
-rw-r--r--src/select.c19
-rw-r--r--src/shell.c.in28
-rw-r--r--src/sqlite.h.in2
-rw-r--r--src/sqliteInt.h18
-rw-r--r--src/tclsqlite.c136
-rw-r--r--src/tclsqlite.h42
-rw-r--r--src/test1.c333
-rw-r--r--src/test2.c6
-rw-r--r--src/test3.c14
-rw-r--r--src/test4.c6
-rw-r--r--src/test5.c12
-rw-r--r--src/test6.c15
-rw-r--r--src/test8.c6
-rw-r--r--src/test9.c6
-rw-r--r--src/test_async.c11
-rw-r--r--src/test_autoext.c9
-rw-r--r--src/test_backup.c9
-rw-r--r--src/test_bestindex.c14
-rw-r--r--src/test_blob.c20
-rw-r--r--src/test_btree.c6
-rw-r--r--src/test_config.c6
-rw-r--r--src/test_demovfs.c9
-rw-r--r--src/test_fs.c7
-rw-r--r--src/test_func.c6
-rw-r--r--src/test_hexio.c42
-rw-r--r--src/test_init.c6
-rw-r--r--src/test_intarray.c9
-rw-r--r--src/test_malloc.c13
-rw-r--r--src/test_md5.c9
-rw-r--r--src/test_multiplex.c9
-rw-r--r--src/test_mutex.c7
-rw-r--r--src/test_osinst.c9
-rw-r--r--src/test_pcache.c3
-rw-r--r--src/test_quota.c11
-rw-r--r--src/test_rtree.c12
-rw-r--r--src/test_schema.c6
-rw-r--r--src/test_superlock.c9
-rw-r--r--src/test_syscall.c14
-rw-r--r--src/test_tclsh.c9
-rw-r--r--src/test_tclvar.c14
-rw-r--r--src/test_thread.c14
-rw-r--r--src/test_vdbecov.c6
-rw-r--r--src/test_vfs.c24
-rw-r--r--src/test_window.c2
-rw-r--r--src/treeview.c6
-rw-r--r--src/vdbe.c20
-rw-r--r--src/vdbe.h15
-rw-r--r--src/vdbeaux.c11
-rw-r--r--src/where.c6
54 files changed, 623 insertions, 538 deletions
diff --git a/src/analyze.c b/src/analyze.c
index 8c48a8ff2..774eeeed2 100644
--- a/src/analyze.c
+++ b/src/analyze.c
@@ -1832,6 +1832,7 @@ static int loadStatTbl(
return SQLITE_NOMEM_BKPT;
}
pSpace = (tRowcnt*)&pIdx->aSample[nSample];
+ assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
pIdx->pTable->tabFlags |= TF_HasStat4;
for(i=0; i<nSample; i++){
diff --git a/src/expr.c b/src/expr.c
index bda91df83..53b0170ab 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -85,7 +85,9 @@ char sqlite3ExprAffinity(const Expr *pExpr){
op = pExpr->op;
continue;
}
- if( op!=TK_REGISTER || (op = pExpr->op2)==TK_REGISTER ) break;
+ if( op!=TK_REGISTER ) break;
+ op = pExpr->op2;
+ if( NEVER( op==TK_REGISTER ) ) break;
}
return pExpr->affExpr;
}
@@ -3420,6 +3422,49 @@ void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
#ifndef SQLITE_OMIT_SUBQUERY
/*
+** Scan all previously generated bytecode looking for an OP_BeginSubrtn
+** that is compatible with pExpr. If found, add the y.sub values
+** to pExpr and return true. If not found, return false.
+*/
+static int findCompatibleInRhsSubrtn(
+ Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* IN operator with RHS that we want to reuse */
+ SubrtnSig *pNewSig /* Signature for the IN operator */
+){
+ VdbeOp *pOp, *pEnd;
+ SubrtnSig *pSig;
+ Vdbe *v;
+
+ if( pNewSig==0 ) return 0;
+ if( (pParse->mSubrtnSig & (1<<(pNewSig->selId&7)))==0 ) return 0;
+ assert( pExpr->op==TK_IN );
+ assert( !ExprUseYSub(pExpr) );
+ assert( ExprUseXSelect(pExpr) );
+ assert( pExpr->x.pSelect!=0 );
+ assert( (pExpr->x.pSelect->selFlags & SF_All)==0 );
+ v = pParse->pVdbe;
+ assert( v!=0 );
+ pOp = sqlite3VdbeGetOp(v, 1);
+ pEnd = sqlite3VdbeGetLastOp(v);
+ for(; pOp<pEnd; pOp++){
+ if( pOp->p4type!=P4_SUBRTNSIG ) continue;
+ assert( pOp->opcode==OP_BeginSubrtn );
+ pSig = pOp->p4.pSubrtnSig;
+ assert( pSig!=0 );
+ if( pNewSig->selId!=pSig->selId ) continue;
+ if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue;
+ pExpr->y.sub.iAddr = pSig->iAddr;
+ pExpr->y.sub.regReturn = pSig->regReturn;
+ pExpr->iTable = pSig->iTable;
+ ExprSetProperty(pExpr, EP_Subrtn);
+ return 1;
+ }
+ return 0;
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
** Generate code that will construct an ephemeral table containing all terms
** in the RHS of an IN operator. The IN operator can be in either of two
** forms:
@@ -3467,11 +3512,28 @@ void sqlite3CodeRhsOfIN(
** and reuse it many names.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
- /* Reuse of the RHS is allowed */
- /* If this routine has already been coded, but the previous code
- ** might not have been invoked yet, so invoke it now as a subroutine.
+ /* Reuse of the RHS is allowed
+ **
+ ** Compute a signature for the RHS of the IN operator to facility
+ ** finding and reusing prior instances of the same IN operator.
*/
- if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ SubrtnSig *pSig = 0;
+ assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 );
+ if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){
+ pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0]));
+ if( pSig ){
+ pSig->selId = pExpr->x.pSelect->selId;
+ pSig->zAff = exprINAffinity(pParse, pExpr);
+ }
+ }
+
+ /* Check to see if there is a prior materialization of the RHS of
+ ** this IN operator. If there is, then make use of that prior
+ ** materialization rather than recomputing it.
+ */
+ if( ExprHasProperty(pExpr, EP_Subrtn)
+ || findCompatibleInRhsSubrtn(pParse, pExpr, pSig)
+ ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
@@ -3483,6 +3545,10 @@ void sqlite3CodeRhsOfIN(
assert( iTab!=pExpr->iTable );
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
+ if( pSig ){
+ sqlite3DbFree(pParse->db, pSig->zAff);
+ sqlite3DbFree(pParse->db, pSig);
+ }
return;
}
@@ -3493,7 +3559,13 @@ void sqlite3CodeRhsOfIN(
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
-
+ if( pSig ){
+ pSig->iAddr = pExpr->y.sub.iAddr;
+ pSig->regReturn = pExpr->y.sub.regReturn;
+ pSig->iTable = iTab;
+ pParse->mSubrtnSig = 1 << (pSig->selId&7);
+ sqlite3VdbeChangeP4(v, -1, (const char*)pSig, P4_SUBRTNSIG);
+ }
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
@@ -3534,19 +3606,34 @@ void sqlite3CodeRhsOfIN(
SelectDest dest;
int i;
int rc;
+ int addrBloom = 0;
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
+ if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
+ int regBloom = ++pParse->nMem;
+ addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
+ VdbeComment((v, "Bloom filter"));
+ dest.iSDParm2 = regBloom;
+ }
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
sqlite3SelectDelete(pParse->db, pCopy);
sqlite3DbFree(pParse->db, dest.zAffSdst);
+ if( addrBloom ){
+ sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
+ if( dest.iSDParm2==0 ){
+ sqlite3VdbeChangeToNoop(v, addrBloom);
+ }else{
+ sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
+ }
+ }
if( rc ){
sqlite3KeyInfoUnref(pKeyInfo);
return;
- }
+ }
assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
assert( pEList!=0 );
assert( pEList->nExpr>0 );
@@ -3840,9 +3927,7 @@ static void sqlite3ExprCodeIN(
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
zAff = exprINAffinity(pParse, pExpr);
nVector = sqlite3ExprVectorSize(pExpr->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(
- pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
- );
+ aiMap = (int*)sqlite3DbMallocZero(pParse->db, nVector*sizeof(int));
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
/* Attempt to compute the RHS. After this step, if anything other than
@@ -3985,6 +4070,15 @@ static void sqlite3ExprCodeIN(
sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
if( destIfFalse==destIfNull ){
/* Combine Step 3 and Step 5 into a single opcode */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr);
+ assert( pOp->opcode==OP_Once || pParse->nErr );
+ if( pOp->opcode==OP_Once && pOp->p3>0 ){
+ assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
+ sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
+ rLhs, nVector); VdbeCoverage(v);
+ }
+ }
sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
rLhs, nVector); VdbeCoverage(v);
goto sqlite3ExprCodeIN_finished;
@@ -4270,10 +4364,14 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
void sqlite3ExprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
if( NEVER(p==0) ) return;
- p->op2 = p->op;
- p->op = TK_REGISTER;
- p->iTable = iReg;
- ExprClearProperty(p, EP_Skip);
+ if( p->op==TK_REGISTER ){
+ assert( p->iTable==iReg );
+ }else{
+ p->op2 = p->op;
+ p->op = TK_REGISTER;
+ p->iTable = iReg;
+ ExprClearProperty(p, EP_Skip);
+ }
}
/*
diff --git a/src/pager.c b/src/pager.c
index 268dc7db3..1ac858a07 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -4064,6 +4064,7 @@ static int pagerAcquireMapPage(
return SQLITE_NOMEM_BKPT;
}
p->pExtra = (void *)&p[1];
+ assert( EIGHT_BYTE_ALIGNMENT( p->pExtra ) );
p->flags = PGHDR_MMAP;
p->nRef = 1;
p->pPager = pPager;
diff --git a/src/pcache.c b/src/pcache.c
index 2974b0810..3429284dc 100644
--- a/src/pcache.c
+++ b/src/pcache.c
@@ -512,6 +512,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
pPgHdr->pData = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
memset(pPgHdr->pExtra, 0, 8);
+ assert( EIGHT_BYTE_ALIGNMENT( pPgHdr->pExtra ) );
pPgHdr->pCache = pCache;
pPgHdr->pgno = pgno;
pPgHdr->flags = PGHDR_CLEAN;
diff --git a/src/pcache1.c b/src/pcache1.c
index 1591f014c..a0a8c7e28 100644
--- a/src/pcache1.c
+++ b/src/pcache1.c
@@ -320,7 +320,8 @@ static int pcache1InitBulk(PCache1 *pCache){
do{
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
pX->page.pBuf = zBulk;
- pX->page.pExtra = &pX[1];
+ pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
+ assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
@@ -457,7 +458,8 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
if( pPg==0 ) return 0;
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
p->page.pBuf = pPg;
- p->page.pExtra = &p[1];
+ p->page.pExtra = (u8*)p + ROUND8(sizeof(*p));
+ assert( EIGHT_BYTE_ALIGNMENT( p->page.pExtra ) );
p->isBulkLocal = 0;
p->isAnchor = 0;
p->pLruPrev = 0; /* Initializing this saves a valgrind error */
diff --git a/src/select.c b/src/select.c
index f2d44bf36..6a4d0397f 100644
--- a/src/select.c
+++ b/src/select.c
@@ -1377,12 +1377,18 @@ static void selectInnerLoop(
** case the order does matter */
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
+ pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */
}else{
int r1 = sqlite3GetTempReg(pParse);
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
+ if( pDest->iSDParm2 ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+ regResult, nResultCol);
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+ }
sqlite3ReleaseTempReg(pParse, r1);
}
break;
@@ -3316,6 +3322,11 @@ static int generateOutputSubroutine(
r1, pDest->zAffSdst, pIn->nSdst);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
+ if( pDest->iSDParm2>0 ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+ pIn->iSdst, pIn->nSdst);
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+ }
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -5066,7 +5077,8 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
**
** NAME AMBIGUITY
**
-** This optimization is called the "WHERE-clause push-down optimization".
+** This optimization is called the "WHERE-clause push-down optimization"
+** or sometimes the "predicate push-down optimization".
**
** Do not confuse this optimization with another unrelated optimization
** with a similar name: The "MySQL push-down optimization" causes WHERE
@@ -8500,7 +8512,10 @@ int sqlite3Select(
if( iOrderByCol ){
Expr *pX = p->pEList->a[iOrderByCol-1].pExpr;
Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX);
- if( ALWAYS(pBase!=0) && pBase->op!=TK_AGG_COLUMN ){
+ if( ALWAYS(pBase!=0)
+ && pBase->op!=TK_AGG_COLUMN
+ && pBase->op!=TK_REGISTER
+ ){
sqlite3ExprToRegister(pX, iAMem+j);
}
}
diff --git a/src/shell.c.in b/src/shell.c.in
index a5bfab589..f389c1f47 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -1200,6 +1200,7 @@ INCLUDE ../ext/misc/pcachetrace.c
INCLUDE ../ext/misc/shathree.c
INCLUDE ../ext/misc/uint.c
INCLUDE ../ext/misc/decimal.c
+INCLUDE ../ext/misc/percentile.c
#undef sqlite3_base_init
#define sqlite3_base_init sqlite3_base64_init
INCLUDE ../ext/misc/base64.c
@@ -5374,6 +5375,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_uint_init(p->db, 0, 0);
sqlite3_stmtrand_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
+ sqlite3_percentile_init(p->db, 0, 0);
sqlite3_base64_init(p->db, 0, 0);
sqlite3_base85_init(p->db, 0, 0);
sqlite3_regexp_init(p->db, 0, 0);
@@ -11974,27 +11976,29 @@ static char *find_home_dir(int clearFlag){
/*
** On non-Windows platforms, look for $XDG_CONFIG_HOME.
** If ${XDG_CONFIG_HOME}/sqlite3/sqliterc is found, return
-** the path to it, else return 0. The result is cached for
-** subsequent calls.
+** the path to it. If there is no $(XDG_CONFIG_HOME) then
+** look for $(HOME)/.config/sqlite3/sqliterc and if found
+** return that. If none of these are found, return 0.
+**
+** The string returned is obtained from sqlite3_malloc() and
+** should be freed by the caller.
*/
-static const char *find_xdg_config(void){
+static char *find_xdg_config(void){
#if defined(_WIN32) || defined(WIN32) || defined(_WIN32_WCE) \
|| defined(__RTP__) || defined(_WRS_KERNEL)
return 0;
#else
- static int alreadyTried = 0;
- static char *zConfig = 0;
+ char *zConfig = 0;
const char *zXdgHome;
- if( alreadyTried!=0 ){
- return zConfig;
- }
- alreadyTried = 1;
zXdgHome = getenv("XDG_CONFIG_HOME");
if( zXdgHome==0 ){
- return 0;
+ const char *zHome = getenv("HOME");
+ if( zHome==0 ) return 0;
+ zConfig = sqlite3_mprintf("%s/.config/sqlite3/sqliterc", zHome);
+ }else{
+ zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
}
- zConfig = sqlite3_mprintf("%s/sqlite3/sqliterc", zXdgHome);
shell_check_oom(zConfig);
if( access(zConfig,0)!=0 ){
sqlite3_free(zConfig);
@@ -12022,7 +12026,7 @@ static void process_sqliterc(
int savedLineno = p->lineno;
if( sqliterc == NULL ){
- sqliterc = find_xdg_config();
+ sqliterc = zBuf = find_xdg_config();
}
if( sqliterc == NULL ){
home_dir = find_home_dir(0);
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 183fb2a08..027c0e62d 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -5820,7 +5820,7 @@ int sqlite3_value_encoding(sqlite3_value*);
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
-** Every [application-defined SQL function] that invoke this interface
+** Every [application-defined SQL function] that invokes this interface
** should include the [SQLITE_SUBTYPE] property in the text
** encoding argument when the function is [sqlite3_create_function|registered].
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 44914065c..bfe0bf94b 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -143,10 +143,13 @@
/*
** Macro to disable warnings about missing "break" at the end of a "case".
*/
-#if GCC_VERSION>=7000000
-# define deliberate_fall_through __attribute__((fallthrough));
-#else
-# define deliberate_fall_through
+#if defined(__has_attribute)
+# if __has_attribute(fallthrough)
+# define deliberate_fall_through __attribute__((fallthrough));
+# endif
+#endif
+#if !defined(deliberate_fall_through)
+# define deliberate_fall_through
#endif
/*
@@ -3621,7 +3624,11 @@ struct Select {
** SRT_Set The result must be a single column. Store each
** row of result as the key in table pDest->iSDParm.
** Apply the affinity pDest->affSdst before storing
-** results. Used to implement "IN (SELECT ...)".
+** results. if pDest->iSDParm2 is positive, then it is
+** a regsiter holding a Bloom filter for the IN operator
+** that should be populated in addition to the
+** pDest->iSDParm table. This SRT is used to
+** implement "IN (SELECT ...)".
**
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
** the result there. The cursor is left open after
@@ -3830,6 +3837,7 @@ struct Parse {
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
u8 bHasWith; /* True if statement contains WITH */
u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */
+ u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
#endif
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index d91b2fa3f..906f429ab 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -35,14 +35,23 @@
# include "msvc.h"
#endif
+/****** Copy of tclsqlite.h ******/
#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
+# include "sqlite_tcl.h" /* Special case for Windows using STDCALL */
#else
-# include "tcl.h"
+# include <tcl.h> /* All normal cases */
# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
+# define SQLITE_TCLAPI
# endif
#endif
+/* Compatability between Tcl8.6 and Tcl9.0 */
+#if TCL_MAJOR_VERSION==9
+# define CONST const
+#else
+ typedef int Tcl_Size;
+#endif
+/**** End copy of tclsqlite.h ****/
+
#include <errno.h>
/*
@@ -209,7 +218,8 @@ struct SqliteDb {
struct IncrblobChannel {
sqlite3_blob *pBlob; /* sqlite3 blob handle */
SqliteDb *pDb; /* Associated database connection */
- int iSeek; /* Current seek offset */
+ sqlite3_int64 iSeek; /* Current seek offset */
+ unsigned int isClosed; /* TCL_CLOSE_READ or TCL_CLOSE_WRITE */
Tcl_Channel channel; /* Channel identifier */
IncrblobChannel *pNext; /* Linked list of all open incrblob channels */
IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */
@@ -249,14 +259,23 @@ static void closeIncrblobChannels(SqliteDb *pDb){
/*
** Close an incremental blob channel.
*/
-static int SQLITE_TCLAPI incrblobClose(
+static int SQLITE_TCLAPI incrblobClose2(
ClientData instanceData,
- Tcl_Interp *interp
+ Tcl_Interp *interp,
+ int flags
){
IncrblobChannel *p = (IncrblobChannel *)instanceData;
- int rc = sqlite3_blob_close(p->pBlob);
+ int rc;
sqlite3 *db = p->pDb->db;
+ if( flags ){
+ p->isClosed |= flags;
+ return TCL_OK;
+ }
+
+ /* If we reach this point, then we really do need to close the channel */
+ rc = sqlite3_blob_close(p->pBlob);
+
/* Remove the channel from the SqliteDb.pIncrblob list. */
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
@@ -277,6 +296,13 @@ static int SQLITE_TCLAPI incrblobClose(
}
return TCL_OK;
}
+static int SQLITE_TCLAPI incrblobClose(
+ ClientData instanceData,
+ Tcl_Interp *interp
+){
+ return incrblobClose2(instanceData, interp, 0);
+}
+
/*
** Read data from an incremental blob channel.
@@ -288,9 +314,9 @@ static int SQLITE_TCLAPI incrblobInput(
int *errorCodePtr
){
IncrblobChannel *p = (IncrblobChannel *)instanceData;
- int nRead = bufSize; /* Number of bytes to read */
- int nBlob; /* Total size of the blob */
- int rc; /* sqlite error code */
+ sqlite3_int64 nRead = bufSize; /* Number of bytes to read */
+ sqlite3_int64 nBlob; /* Total size of the blob */
+ int rc; /* sqlite error code */
nBlob = sqlite3_blob_bytes(p->pBlob);
if( (p->iSeek+nRead)>nBlob ){
@@ -300,7 +326,7 @@ static int SQLITE_TCLAPI incrblobInput(
return 0;
}
- rc = sqlite3_blob_read(p->pBlob, (void *)buf, nRead, p->iSeek);
+ rc = sqlite3_blob_read(p->pBlob, (void *)buf, (int)nRead, (int)p->iSeek);
if( rc!=SQLITE_OK ){
*errorCodePtr = rc;
return -1;
@@ -320,9 +346,9 @@ static int SQLITE_TCLAPI incrblobOutput(
int *errorCodePtr
){
IncrblobChannel *p = (IncrblobChannel *)instanceData;
- int nWrite = toWrite; /* Number of bytes to write */
- int nBlob; /* Total size of the blob */
- int rc; /* sqlite error code */
+ sqlite3_int64 nWrite = toWrite; /* Number of bytes to write */
+ sqlite3_int64 nBlob; /* Total size of the blob */
+ int rc; /* sqlite error code */
nBlob = sqlite3_blob_bytes(p->pBlob);
if( (p->iSeek+nWrite)>nBlob ){
@@ -333,7 +359,7 @@ static int SQLITE_TCLAPI incrblobOutput(
return 0;
}
- rc = sqlite3_blob_write(p->pBlob, (void *)buf, nWrite, p->iSeek);
+ rc = sqlite3_blob_write(p->pBlob, (void*)buf,(int)nWrite, (int)p->iSeek);
if( rc!=SQLITE_OK ){
*errorCodePtr = EIO;
return -1;
@@ -346,9 +372,9 @@ static int SQLITE_TCLAPI incrblobOutput(
/*
** Seek an incremental blob channel.
*/
-static int SQLITE_TCLAPI incrblobSeek(
+static long long SQLITE_TCLAPI incrblobWideSeek(
ClientData instanceData,
- long offset,
+ long long offset,
int seekMode,
int *errorCodePtr
){
@@ -370,6 +396,14 @@ static int SQLITE_TCLAPI incrblobSeek(
return p->iSeek;
}
+static int SQLITE_TCLAPI incrblobSeek(
+ ClientData instanceData,
+ long offset,
+ int seekMode,
+ int *errorCodePtr
+){
+ return incrblobWideSeek(instanceData,offset,seekMode,errorCodePtr);
+}
static void SQLITE_TCLAPI incrblobWatch(
@@ -388,7 +422,7 @@ static int SQLITE_TCLAPI incrblobHandle(
static Tcl_ChannelType IncrblobChannelType = {
"incrblob", /* typeName */
- TCL_CHANNEL_VERSION_2, /* version */
+ TCL_CHANNEL_VERSION_5, /* version */
incrblobClose, /* closeProc */
incrblobInput, /* inputProc */
incrblobOutput, /* outputProc */
@@ -397,11 +431,11 @@ static Tcl_ChannelType IncrblobChannelType = {
0, /* getOptionProc */
incrblobWatch, /* watchProc (this is a no-op) */
incrblobHandle, /* getHandleProc (always returns error) */
- 0, /* close2Proc */
+ incrblobClose2, /* close2Proc */
0, /* blockModeProc */
0, /* flushProc */
0, /* handlerProc */
- 0, /* wideSeekProc */
+ incrblobWideSeek, /* wideSeekProc */
};
/*
@@ -433,8 +467,9 @@ static int createIncrblobChannel(
}
p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel));
- p->iSeek = 0;
+ memset(p, 0, sizeof(*p));
p->pBlob = pBlob;
+ if( (flags & TCL_WRITABLE)==0 ) p->isClosed |= TCL_CLOSE_WRITE;
sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count);
p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags);
@@ -474,7 +509,7 @@ static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){
** characters appear in pCmd, we will report the string as unsafe.
*/
const char *z;
- int n;
+ Tcl_Size n;
z = Tcl_GetStringFromObj(pCmd, &n);
while( n-- > 0 ){
int c = *(z++);
@@ -981,7 +1016,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
** be preserved and reused on the next invocation.
*/
Tcl_Obj **aArg;
- int nArg;
+ Tcl_Size nArg;
if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
return;
@@ -1044,7 +1079,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
}else{
Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
- int n;
+ Tcl_Size n;
u8 *data;
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
char c = zType[0];
@@ -1455,7 +1490,7 @@ static int dbPrepareAndBind(
}
}
if( pVar ){
- int n;
+ Tcl_Size n;
u8 *data;
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
c = zType[0];
@@ -1469,8 +1504,9 @@ static int dbPrepareAndBind(
Tcl_IncrRefCount(pVar);
pPreStmt->apParm[iParm++] = pVar;
}else if( c=='b' && strcmp(zType,"boolean")==0 ){
- Tcl_GetIntFromObj(interp, pVar, &n);
- sqlite3_bind_int(pStmt, i, n);
+ int nn;
+ Tcl_GetIntFromObj(interp, pVar, &nn);
+ sqlite3_bind_int(pStmt, i, nn);
}else if( c=='d' && strcmp(zType,"double")==0 ){
double r;
Tcl_GetDoubleFromObj(interp, pVar, &r);
@@ -2034,7 +2070,7 @@ static int SQLITE_TCLAPI DbObjCmd(
}
}else{
char *zAuth;
- int len;
+ Tcl_Size len;
if( pDb->zAuth ){
Tcl_Free(pDb->zAuth);
}
@@ -2137,7 +2173,7 @@ static int SQLITE_TCLAPI DbObjCmd(
}
}else{
char *zCallback;
- int len;
+ Tcl_Size len;
if( pDb->zBindFallback ){
Tcl_Free(pDb->zBindFallback);
}
@@ -2167,7 +2203,7 @@ static int SQLITE_TCLAPI DbObjCmd(
}
}else{
char *zBusy;
- int len;
+ Tcl_Size len;
if( pDb->zBusy ){
Tcl_Free(pDb->zBusy);
}
@@ -2274,7 +2310,7 @@ static int SQLITE_TCLAPI DbObjCmd(
SqlCollate *pCollate;
char *zName;
char *zScript;
- int nScript;
+ Tcl_Size nScript;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
return TCL_ERROR;
@@ -2333,7 +2369,7 @@ static int SQLITE_TCLAPI DbObjCmd(
}
}else{
const char *zCommit;
- int len;
+ Tcl_Size len;
if( pDb->zCommit ){
Tcl_Free(pDb->zCommit);
}
@@ -2653,7 +2689,8 @@ static int SQLITE_TCLAPI DbObjCmd(
Tcl_Obj *pValue = 0;
unsigned char *pBA;
unsigned char *pData;
- int len, xrc;
+ Tcl_Size len;
+ int xrc;
sqlite3_int64 mxSize = 0;
int i;
int isReadonly = 0;
@@ -3024,7 +3061,7 @@ deserialize_error:
return TCL_ERROR;
}
if( objc==3 ){
- int len;
+ Tcl_Size len;
char *zNull = Tcl_GetStringFromObj(objv[2], &len);
if( pDb->zNull ){
Tcl_Free(pDb->zNull);
@@ -3078,7 +3115,7 @@ deserialize_error:
#endif
}else if( objc==4 ){
char *zProgress;
- int len;
+ Tcl_Size len;
int N;
if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){
return TCL_ERROR;
@@ -3124,7 +3161,7 @@ deserialize_error:
}
}else{
char *zProfile;
- int len;
+ Tcl_Size len;
if( pDb->zProfile ){
Tcl_Free(pDb->zProfile);
}
@@ -3335,7 +3372,7 @@ deserialize_error:
}
}else{
char *zTrace;
- int len;
+ Tcl_Size len;
if( pDb->zTrace ){
Tcl_Free(pDb->zTrace);
}
@@ -3375,7 +3412,7 @@ deserialize_error:
}
}else{
char *zTraceV2;
- int len;
+ Tcl_Size len;
Tcl_WideInt wMask = 0;
if( objc==4 ){
static const char *TTYPE_strs[] = {
@@ -3961,14 +3998,25 @@ EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; }
EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;}
+/*
+** Versions of all of the above entry points that omit the "3" at the end
+** of the name. Years ago (circa 2004) the "3" was necessary to distinguish
+** SQLite version 3 from Sqlite version 2. But two decades have elapsed.
+** SQLite2 is not longer a conflict. So it is ok to omit the "3".
+**
+** Omitting the "3" helps TCL find the entry point.
+*/
+EXTERN int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
+EXTERN int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+EXTERN int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
+EXTERN int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
+EXTERN int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; }
+EXTERN int Sqlite_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;}
+/* Also variants with a lowercase "s" */
+EXTERN int sqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
+EXTERN int sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
-#ifndef SQLITE_3_SUFFIX_ONLY
-int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
-int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
-int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
-int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
-#endif
/*
** If the TCLSH macro is defined, add code to make a stand-alone program.
diff --git a/src/tclsqlite.h b/src/tclsqlite.h
new file mode 100644
index 000000000..b9a948ef1
--- /dev/null
+++ b/src/tclsqlite.h
@@ -0,0 +1,42 @@
+/*
+** 2024-07-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.
+**
+*************************************************************************
+** This header file defines the interface to TCL as used by SQLite.
+** SQLite subcomponents that use TCL (the libsqlite3.c interface library
+** and various test*.c pieces) should #include this file rather than
+** including tcl.h directly.
+*/
+/****** Any edits to this file must mirrored in tclsqlite.c ***********/
+
+/* When compiling for Windows using STDCALL instead of CDECL calling
+** conventions, the MSVC makefile has to build a customized version of
+** the "tcl.h" header that specifies the calling conventions for each
+** interface. That customized "tcl.h" is named "sqlite_tcl.h".
+*/
+#if defined(INCLUDE_SQLITE_TCL_H)
+# include "sqlite_tcl.h" /* Special case for Windows using STDCALL */
+#else
+# include <tcl.h> /* All normal cases */
+# ifndef SQLITE_TCLAPI
+# define SQLITE_TCLAPI
+# endif
+#endif
+
+/****** Any edits to this file must mirrored in tclsqlite.c ***********/
+
+/* Compatability between Tcl8.6 and Tcl9.0 */
+#if TCL_MAJOR_VERSION==9
+# define CONST const
+#else
+ typedef int Tcl_Size;
+#endif
+
+/****** Any edits to this file must mirrored in tclsqlite.c ***********/
diff --git a/src/test1.c b/src/test1.c
index 975758131..88bfdc06d 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -26,11 +26,7 @@
#endif
#include "vdbeInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
@@ -1772,7 +1768,7 @@ static int SQLITE_TCLAPI blobHandleFromObj(
sqlite3_blob **ppBlob
){
char *z;
- int n;
+ Tcl_Size n;
z = Tcl_GetStringFromObj(pObj, &n);
if( n==0 ){
@@ -2339,13 +2335,13 @@ static int SQLITE_TCLAPI test_stmt_scanstatus(
};
Tcl_Obj **aFlag = 0;
- int nFlag = 0;
+ Tcl_Size nFlag = 0;
int ii;
if( Tcl_ListObjGetElements(interp, objv[2], &nFlag, &aFlag) ){
return TCL_ERROR;
}
- for(ii=0; ii<nFlag; ii++){
+ for(ii=0; ii<(int)nFlag; ii++){
int iVal = 0;
int res = Tcl_GetIndexFromObjStruct(
interp, aFlag[ii], aTbl, sizeof(aTbl[0]), "flag", 0, &iVal
@@ -2766,7 +2762,7 @@ static int SQLITE_TCLAPI test_snapshot_open_blob(
sqlite3 *db;
char *zName;
unsigned char *pBlob;
- int nBlob;
+ Tcl_Size nBlob;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
@@ -2801,8 +2797,8 @@ static int SQLITE_TCLAPI test_snapshot_cmp_blob(
int res;
unsigned char *p1;
unsigned char *p2;
- int n1;
- int n2;
+ Tcl_Size n1;
+ Tcl_Size n2;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2");
@@ -4102,7 +4098,7 @@ static int SQLITE_TCLAPI test_bind_text(
){
sqlite3_stmt *pStmt;
int idx;
- int trueLength = 0;
+ Tcl_Size trueLength = 0;
int bytes;
char *value;
int rc;
@@ -4160,7 +4156,7 @@ static int SQLITE_TCLAPI test_bind_text16(
char *value;
char *toFree = 0;
int rc;
- int trueLength = 0;
+ Tcl_Size trueLength = 0;
void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
Tcl_Obj *oStmt = objv[objc-4];
@@ -4214,7 +4210,8 @@ static int SQLITE_TCLAPI test_bind_blob(
Tcl_Obj *CONST objv[]
){
sqlite3_stmt *pStmt;
- int len, idx;
+ Tcl_Size len;
+ int idx;
int bytes;
char *value;
int rc;
@@ -4240,7 +4237,7 @@ static int SQLITE_TCLAPI test_bind_blob(
if( bytes>len ){
char zBuf[200];
sqlite3_snprintf(sizeof(zBuf), zBuf,
- "cannot use %d blob bytes, have %d", bytes, len);
+ "cannot use %d blob bytes, have %d", bytes, (int)len);
Tcl_AppendResult(interp, zBuf, (char*)0);
return TCL_ERROR;
}
@@ -4538,9 +4535,9 @@ static int SQLITE_TCLAPI test_carray_bind(
struct iovec *a = sqlite3_malloc( sizeof(struct iovec)*nData );
if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
for(j=0; j<nData; j++){
- int n = 0;
+ Tcl_Size n = 0;
unsigned char *v = Tcl_GetByteArrayFromObj(objv[i+i], &n);
- a[j].iov_len = n;
+ a[j].iov_len = (size_t)n;
a[j].iov_base = sqlite3_malloc64( n );
if( a[j].iov_base==0 ){
a[j].iov_len = 0;
@@ -5116,7 +5113,7 @@ static int SQLITE_TCLAPI test_prepare16(
char zBuf[50];
int rc;
int bytes; /* The integer specified as arg 3 */
- int objlen; /* The byte-array length of arg 2 */
+ Tcl_Size objlen; /* The byte-array length of arg 2 */
if( objc!=5 && objc!=4 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -5176,7 +5173,7 @@ static int SQLITE_TCLAPI test_prepare16_v2(
char zBuf[50];
int rc;
int bytes; /* The integer specified as arg 3 */
- int objlen; /* The byte-array length of arg 2 */
+ Tcl_Size objlen; /* The byte-array length of arg 2 */
if( objc!=5 && objc!=4 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -5256,9 +5253,9 @@ static int SQLITE_TCLAPI test_open_v2(
int rc;
char zBuf[100];
- int nFlag;
+ Tcl_Size nFlag;
Tcl_Obj **apFlag;
- int i;
+ Tcl_Size i;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
@@ -5967,6 +5964,145 @@ static int SQLITE_TCLAPI tcl_variable_type(
return TCL_OK;
}
+#include <ctype.h>
+
+/*
+** Usage: fpnum_compare STRING1 STRING2
+**
+** Compare two strings. Return true if the strings are the same and
+** false if they differ.
+**
+** For this comparison, the strings are analyzed as a sequenced of
+** whitespace separated tokens. The whitespace is ignored. Only the
+** tokens are compared. Comparison rules:
+**
+** A. Tokens that are not floating-point numbers must match exactly.
+**
+** B. Floating point number must have exactly the same digits before
+** the decimal point.
+**
+** C. Digits must match after the decimal point up to 15 digits,
+** taking rounding into consideration.
+**
+** D. An exponent on a floating point of the form "e+NN" will
+** match "e+N" if NN==N. Likewise for the negative exponent.
+**
+** This routine is used for comparing results that might involve floating
+** point values. Tcl9.0 and Tcl8.6 differ in the number of significant
+** digits that they show, so there is no way to write a portable test result
+** without this routine.
+**
+** This routine is only called after [string compare] fails, which is seldom,
+** so performance is not a pressing concern. Better to get the correct answer
+** slowly.
+*/
+static int SQLITE_TCLAPI fpnum_compare(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ const unsigned char *zA;
+ const unsigned char *zB;
+ int i, j;
+ int nDigit;
+
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "STRING1 STRING2");
+ return TCL_ERROR;
+ }
+ zA = (const unsigned char*)Tcl_GetString(objv[1]);
+ zB = (const unsigned char*)Tcl_GetString(objv[2]);
+ i = j = 0;
+ while( 1 ){
+ /* Skip whitespace before and after tokens */
+ while( isspace(zA[i]) ){ i++; }
+ while( isspace(zB[j]) ){ j++; }
+
+ if( zA[i]!=zB[j] ) break; /* First character must match */
+ if( zA[i]=='-' && isdigit(zA[i+1]) ){ i++; j++; } /* Skip initial '-' */
+ if( !isdigit(zA[i]) ){
+ /* Not a number. Must match exactly */
+ while( !isspace(zA[i]) && zA[i] && zA[i]==zB[j] ){ i++; j++; }
+ if( zA[i]!=zB[j] ) break;
+ if( isspace(zA[i]) ) continue;
+ break;
+ }
+
+ /* At this point we know we are dealing with a number zA[i] and zB[j]
+ ** are both digits (leading "-" have been skipped). See if they are
+ ** the same number. Start by matching digits before the decimal
+ ** point, which must all be the same. */
+ nDigit = 0;
+ while( zA[i]==zB[j] && isdigit(zA[i]) ){ i++; j++; nDigit++; }
+ if( zA[i]!=zB[j] ) break;
+ if( zA[i]==0 ) break;
+ if( zA[i]=='.' && zB[j]=='.' ){
+ /* Count more matching digits after the decimal point */
+ i++;
+ j++;
+ while( zA[i]==zB[j] && isdigit(zA[i]) ){ i++; j++; nDigit++; }
+ if( zA[i]==0 ){
+ while( zB[j]=='0' || (isdigit(zB[j]) && nDigit>=15) ){ j++; nDigit++; }
+ break;
+ }
+ if( zB[j]==0 ){
+ while( zA[i]=='0' || (isdigit(zA[i]) && nDigit>=15) ){ i++; nDigit++; }
+ break;
+ }
+ if( isspace(zA[i]) && isspace(zB[j]) ) continue;
+
+ if( isdigit(zA[i]) && isdigit(zB[j]) ){
+ /* A and B are both digits, but different digits */
+ if( zA[i]==zB[j]+1 && !isdigit(zA[i+1]) && isdigit(zB[j+1]) ){
+ /* Is A a rounded up version of B? */
+ j++;
+ while( zB[j]=='9' ){ j++; nDigit++; }
+ if( nDigit<14 && (!isdigit(zB[j]) || zB[j]<5) ) break;
+ while( isdigit(zB[j]) ){ j++; }
+ i++;
+ }else if( zB[j]==zA[i]+1 && !isdigit(zB[j+1]) && isdigit(zA[i+1]) ){
+ /* Is B a rounded up version of A? */
+ i++;
+ while( zA[i]=='9' ){ i++; nDigit++; }
+ if( nDigit<14 && (!isdigit(zA[i]) || zA[i]<5) ) break;
+ while( isdigit(zA[i]) ){ i++; }
+ j++;
+ }else{
+ break;
+ }
+ }else if( !isdigit(zA[i]) && isdigit(zB[j]) ){
+ while( zB[j]=='0' ){ j++; nDigit++; }
+ if( nDigit<15 ) break;
+ while( isdigit(zB[j]) ){ j++; }
+ }else if( !isdigit(zB[j]) && isdigit(zA[i]) ){
+ while( zA[i]=='0' ){ i++; nDigit++; }
+ if( nDigit<15 ) break;
+ while( isdigit(zA[i]) ){ i++; }
+ }else{
+ break;
+ }
+ }
+ if( zA[i]=='e' && zB[j]=='e' ){
+ i++;
+ j++;
+ if( (zA[i]=='+' || zA[i]=='-') && zB[j]==zA[i] ){ i++; j++; }
+ if( zA[i]!=zB[j] ){
+ if( zA[i]=='0' && zA[i+1]==zB[j] ){ i++; }
+ if( zB[j]=='0' && zB[j+1]==zA[i] ){ j++; }
+ }
+ while( zA[i]==zB[j] && isdigit(zA[i]) ){ i++; j++; }
+ if( zA[i]!=zB[j] ) break;
+ if( zA[i]==0 ) break;
+ continue;
+ }
+ }
+ while( isspace(zA[i]) ){ i++; }
+ while( isspace(zB[j]) ){ j++; }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(zA[i]==0 && zB[j]==0));
+ return TCL_OK;
+}
+
/*
** Usage: sqlite3_release_memory ?N?
**
@@ -6655,7 +6791,7 @@ static int SQLITE_TCLAPI file_control_lockproxy_test(
{
char *testPath;
int rc;
- int nPwd;
+ Tcl_Size nPwd;
const char *zPwd;
char proxyPath[400];
@@ -7925,145 +8061,6 @@ static int SQLITE_TCLAPI win32_file_lock(
CloseHandle(ev);
return TCL_OK;
}
-
-/*
-** exists_win32_path PATH
-**
-** Returns non-zero if the specified path exists, whose fully qualified name
-** may exceed 260 characters if it is prefixed with "\\?\".
-*/
-static int SQLITE_TCLAPI win32_exists_path(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PATH");
- return TCL_ERROR;
- }
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
- GetFileAttributesW( Tcl_GetUnicode(objv[1]))!=INVALID_FILE_ATTRIBUTES ));
- return TCL_OK;
-}
-
-/*
-** find_win32_file PATTERN
-**
-** Returns a list of entries in a directory that match the specified pattern,
-** whose fully qualified name may exceed 248 characters if it is prefixed with
-** "\\?\".
-*/
-static int SQLITE_TCLAPI win32_find_file(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- HANDLE hFindFile = INVALID_HANDLE_VALUE;
- WIN32_FIND_DATAW findData;
- Tcl_Obj *listObj;
- DWORD lastErrno;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "PATTERN");
- return TCL_ERROR;
- }
- hFindFile = FindFirstFileW(Tcl_GetUnicode(objv[1]), &findData);
- if( hFindFile==INVALID_HANDLE_VALUE ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- listObj = Tcl_NewObj();
- Tcl_IncrRefCount(listObj);
- do {
- Tcl_ListObjAppendElement(interp, listObj, Tcl_NewUnicodeObj(
- findData.cFileName, -1));
- Tcl_ListObjAppendElement(interp, listObj, Tcl_NewWideIntObj(
- findData.dwFileAttributes));
- } while( FindNextFileW(hFindFile, &findData) );
- lastErrno = GetLastError();
- if( lastErrno!=NO_ERROR && lastErrno!=ERROR_NO_MORE_FILES ){
- FindClose(hFindFile);
- Tcl_DecrRefCount(listObj);
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- FindClose(hFindFile);
- Tcl_SetObjResult(interp, listObj);
- return TCL_OK;
-}
-
-/*
-** delete_win32_file FILENAME
-**
-** Deletes the specified file, whose fully qualified name may exceed 260
-** characters if it is prefixed with "\\?\".
-*/
-static int SQLITE_TCLAPI win32_delete_file(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
- return TCL_ERROR;
- }
- if( !DeleteFileW(Tcl_GetUnicode(objv[1])) ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/*
-** make_win32_dir DIRECTORY
-**
-** Creates the specified directory, whose fully qualified name may exceed 248
-** characters if it is prefixed with "\\?\".
-*/
-static int SQLITE_TCLAPI win32_mkdir(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
- return TCL_ERROR;
- }
- if( !CreateDirectoryW(Tcl_GetUnicode(objv[1]), NULL) ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/*
-** remove_win32_dir DIRECTORY
-**
-** Removes the specified directory, whose fully qualified name may exceed 248
-** characters if it is prefixed with "\\?\".
-*/
-static int SQLITE_TCLAPI win32_rmdir(
- void *clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DIRECTORY");
- return TCL_ERROR;
- }
- if( !RemoveDirectoryW(Tcl_GetUnicode(objv[1])) ){
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(GetLastError()));
- return TCL_ERROR;
- }
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
#endif
@@ -8370,7 +8367,7 @@ static int SQLITE_TCLAPI test_user_authenticate(
){
char *zUser = 0;
char *zPasswd = 0;
- int nPasswd = 0;
+ Tcl_Size nPasswd = 0;
sqlite3 *db;
int rc;
@@ -8383,7 +8380,7 @@ static int SQLITE_TCLAPI test_user_authenticate(
}
zUser = Tcl_GetString(objv[2]);
zPasswd = Tcl_GetStringFromObj(objv[3], &nPasswd);
- rc = sqlite3_user_authenticate(db, zUser, zPasswd, nPasswd);
+ rc = sqlite3_user_authenticate(db, zUser, zPasswd, (int)nPasswd);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
@@ -8733,7 +8730,7 @@ static int SQLITE_TCLAPI test_write_db(
sqlite3 *db = 0;
Tcl_WideInt iOff = 0;
const unsigned char *aData = 0;
- int nData = 0;
+ Tcl_Size nData = 0;
sqlite3_file *pFile = 0;
int rc;
@@ -8746,7 +8743,7 @@ static int SQLITE_TCLAPI test_write_db(
aData = Tcl_GetByteArrayFromObj(objv[3], &nData);
sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFile);
- rc = pFile->pMethods->xWrite(pFile, aData, nData, iOff);
+ rc = pFile->pMethods->xWrite(pFile, aData, (int)(nData&0x7fffffff), iOff);
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
return TCL_OK;
@@ -9158,11 +9155,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "optimization_control", optimization_control,0},
#if SQLITE_OS_WIN
{ "lock_win32_file", win32_file_lock, 0 },
- { "exists_win32_path", win32_exists_path, 0 },
- { "find_win32_file", win32_find_file, 0 },
- { "delete_win32_file", win32_delete_file, 0 },
- { "make_win32_dir", win32_mkdir, 0 },
- { "remove_win32_dir", win32_rmdir, 0 },
#endif
{ "tcl_objproc", runAsObjProc, 0 },
@@ -9237,6 +9229,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
#endif
{ "sqlite3_test_errstr", test_errstr, 0 },
{ "tcl_variable_type", tcl_variable_type, 0 },
+ { "fpnum_compare", fpnum_compare, 0 },
#ifndef SQLITE_OMIT_SHARED_CACHE
{ "sqlite3_enable_shared_cache", test_enable_shared, 0 },
{ "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
diff --git a/src/test2.c b/src/test2.c
index c75fa2eba..a9549aa7f 100644
--- a/src/test2.c
+++ b/src/test2.c
@@ -14,11 +14,7 @@
** testing of the SQLite library.
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
diff --git a/src/test3.c b/src/test3.c
index 7fd766247..f1b2b0168 100644
--- a/src/test3.c
+++ b/src/test3.c
@@ -15,11 +15,7 @@
*/
#include "sqliteInt.h"
#include "btreeInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
@@ -623,6 +619,7 @@ static int SQLITE_TCLAPI btree_insert(
BtCursor *pCur;
int rc;
BtreePayload x;
+ Tcl_Size n;
if( objc!=4 && objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "?-intkey? CSR KEY VALUE");
@@ -633,10 +630,11 @@ static int SQLITE_TCLAPI btree_insert(
if( objc==4 ){
if( Tcl_GetIntFromObj(interp, objv[2], &rc) ) return TCL_ERROR;
x.nKey = rc;
- x.pData = (void*)Tcl_GetByteArrayFromObj(objv[3], &x.nData);
+ x.pData = (void*)Tcl_GetByteArrayFromObj(objv[3], &n);
+ x.nData = (int)n;
}else{
- x.pKey = (void*)Tcl_GetByteArrayFromObj(objv[2], &rc);
- x.nKey = rc;
+ x.pKey = (void*)Tcl_GetByteArrayFromObj(objv[2], &n);
+ x.nKey = (int)n;
}
pCur = (BtCursor*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
diff --git a/src/test4.c b/src/test4.c
index 2043a3383..8a68f7d3e 100644
--- a/src/test4.c
+++ b/src/test4.c
@@ -12,11 +12,7 @@
** Code for testing the SQLite library in a multithreaded environment.
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
#include <stdlib.h>
#include <string.h>
diff --git a/src/test5.c b/src/test5.c
index 0d9242862..334b5d07f 100644
--- a/src/test5.c
+++ b/src/test5.c
@@ -17,11 +17,7 @@
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
@@ -36,7 +32,7 @@ static int SQLITE_TCLAPI binarize(
int objc,
Tcl_Obj *CONST objv[]
){
- int len;
+ Tcl_Size len;
char *bytes;
Tcl_Obj *pRet;
assert(objc==2);
@@ -133,7 +129,7 @@ static int SQLITE_TCLAPI test_translate(
sqlite3_value *pVal;
char *z;
- int len;
+ Tcl_Size len;
void (*xDel)(void *p) = SQLITE_STATIC;
if( objc!=4 && objc!=5 ){
@@ -164,7 +160,7 @@ static int SQLITE_TCLAPI test_translate(
z = (char*)Tcl_GetByteArrayFromObj(objv[1], &len);
if( objc==5 ){
char *zTmp = z;
- z = sqlite3_malloc(len);
+ z = sqlite3_malloc64(len);
memcpy(z, zTmp, len);
}
sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel);
diff --git a/src/test6.c b/src/test6.c
index 5d8e6b9be..76db640c4 100644
--- a/src/test6.c
+++ b/src/test6.c
@@ -16,11 +16,7 @@
*/
#if SQLITE_TEST /* This file is used for testing only */
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#ifndef SQLITE_OMIT_DISKIO /* This file is a no-op if disk I/O is disabled */
@@ -751,7 +747,7 @@ static int processDevSymArgs(
int setDeviceChar = 0;
for(i=0; i<objc; i+=2){
- int nOpt;
+ Tcl_Size nOpt;
char *zOpt = Tcl_GetStringFromObj(objv[i], &nOpt);
if( (nOpt>11 || nOpt<2 || strncmp("-sectorsize", zOpt, nOpt))
@@ -776,11 +772,11 @@ static int processDevSymArgs(
}else{
int j;
Tcl_Obj **apObj;
- int nObj;
+ Tcl_Size nObj;
if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){
return TCL_ERROR;
}
- for(j=0; j<nObj; j++){
+ for(j=0; j<(int)nObj; j++){
int rc;
int iChoice;
Tcl_Obj *pFlag = Tcl_DuplicateObj(apObj[j]);
@@ -925,7 +921,8 @@ static int SQLITE_TCLAPI crashParamsObjCmd(
){
int iDelay;
const char *zCrashFile;
- int nCrashFile, iDc, iSectorSize;
+ Tcl_Size nCrashFile;
+ int iDc, iSectorSize;
iDc = -1;
iSectorSize = -1;
diff --git a/src/test8.c b/src/test8.c
index 4aeb555c7..8a13f5d55 100644
--- a/src/test8.c
+++ b/src/test8.c
@@ -14,11 +14,7 @@
** testing of the SQLite library.
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
diff --git a/src/test9.c b/src/test9.c
index 5b139e8a5..b5362adb7 100644
--- a/src/test9.c
+++ b/src/test9.c
@@ -15,11 +15,7 @@
** as there is not much point in binding to Tcl.
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
diff --git a/src/test_async.c b/src/test_async.c
index c32c74c66..afe401ac6 100644
--- a/src/test_async.c
+++ b/src/test_async.c
@@ -14,15 +14,8 @@
** (defined in ext/async/sqlite3async.h) to Tcl.
*/
-#define TCL_THREADS
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#define TCL_THREADS
+#include "tclsqlite.h"
#ifdef SQLITE_ENABLE_ASYNCIO
diff --git a/src/test_autoext.c b/src/test_autoext.c
index e23e41a08..74ca55879 100644
--- a/src/test_autoext.c
+++ b/src/test_autoext.c
@@ -11,14 +11,7 @@
*************************************************************************
** Test extension for testing the sqlite3_auto_extension() function.
*/
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
#include "sqlite3ext.h"
#ifndef SQLITE_OMIT_LOAD_EXTENSION
diff --git a/src/test_backup.c b/src/test_backup.c
index 9b684a28f..8051888ee 100644
--- a/src/test_backup.c
+++ b/src/test_backup.c
@@ -13,14 +13,7 @@
**
*/
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
#include "sqlite3.h"
#include <assert.h>
diff --git a/src/test_bestindex.c b/src/test_bestindex.c
index c89cab2e3..2f9203d85 100644
--- a/src/test_bestindex.c
+++ b/src/test_bestindex.c
@@ -93,11 +93,7 @@
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -352,14 +348,14 @@ static int tclFilter(
*/
Tcl_Obj *pRes = Tcl_GetObjResult(interp);
Tcl_Obj **apElem = 0;
- int nElem;
+ Tcl_Size nElem;
rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem);
if( rc!=TCL_OK ){
const char *zErr = Tcl_GetStringResult(interp);
rc = SQLITE_ERROR;
pTab->base.zErrMsg = sqlite3_mprintf("%s", zErr);
}else{
- for(ii=0; rc==SQLITE_OK && ii<nElem; ii+=2){
+ for(ii=0; rc==SQLITE_OK && ii<(int)nElem; ii+=2){
const char *zCmd = Tcl_GetString(apElem[ii]);
Tcl_Obj *p = apElem[ii+1];
if( sqlite3_stricmp("sql", zCmd)==0 ){
@@ -664,7 +660,7 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
*/
Tcl_Obj *pRes = Tcl_GetObjResult(interp);
Tcl_Obj **apElem = 0;
- int nElem;
+ Tcl_Size nElem;
rc = Tcl_ListObjGetElements(interp, pRes, &nElem, &apElem);
if( rc!=TCL_OK ){
const char *zErr = Tcl_GetStringResult(interp);
@@ -673,7 +669,7 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
}else{
int ii;
int iArgv = 1;
- for(ii=0; rc==SQLITE_OK && ii<nElem; ii+=2){
+ for(ii=0; rc==SQLITE_OK && ii<(int)nElem; ii+=2){
const char *zCmd = Tcl_GetString(apElem[ii]);
Tcl_Obj *p = apElem[ii+1];
if( sqlite3_stricmp("cost", zCmd)==0 ){
diff --git a/src/test_blob.c b/src/test_blob.c
index cbdf9f069..bddad240c 100644
--- a/src/test_blob.c
+++ b/src/test_blob.c
@@ -12,11 +12,7 @@
**
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@@ -58,7 +54,7 @@ static int blobHandleFromObj(
sqlite3_blob **ppBlob
){
char *z;
- int n;
+ Tcl_Size n;
z = Tcl_GetStringFromObj(pObj, &n);
if( n==0 ){
@@ -88,7 +84,7 @@ static int blobHandleFromObj(
** NULL Pointer is returned.
*/
static char *blobStringFromObj(Tcl_Obj *pObj){
- int n;
+ Tcl_Size n;
char *z;
z = Tcl_GetStringFromObj(pObj, &n);
return (n ? z : 0);
@@ -112,7 +108,7 @@ static int SQLITE_TCLAPI test_blob_open(
Tcl_WideInt iRowid;
int flags;
const char *zVarname;
- int nVarname;
+ Tcl_Size nVarname;
sqlite3_blob *pBlob = (sqlite3_blob*)&flags; /* Non-zero initialization */
int rc;
@@ -281,7 +277,8 @@ static int SQLITE_TCLAPI test_blob_write(
int rc;
unsigned char *zBuf;
- int nBuf;
+ Tcl_Size nBuf;
+ int n;
if( objc!=4 && objc!=5 ){
Tcl_WrongNumArgs(interp, 1, objv, "HANDLE OFFSET DATA ?NDATA?");
@@ -294,10 +291,11 @@ static int SQLITE_TCLAPI test_blob_write(
}
zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
- if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
+ n = (int)(nBuf & 0x7fffffff);
+ if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &n) ){
return TCL_ERROR;
}
- rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
+ rc = sqlite3_blob_write(pBlob, zBuf, n, iOffset);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
}
diff --git a/src/test_btree.c b/src/test_btree.c
index 03b8b207c..168a10f1f 100644
--- a/src/test_btree.c
+++ b/src/test_btree.c
@@ -14,11 +14,7 @@
** testing of the SQLite library.
*/
#include "btreeInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
/*
** Usage: sqlite3_shared_cache_report
diff --git a/src/test_config.c b/src/test_config.c
index 76904e5bf..58de5a462 100644
--- a/src/test_config.c
+++ b/src/test_config.c
@@ -24,11 +24,7 @@
# include "os_win.h"
#endif
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
diff --git a/src/test_demovfs.c b/src/test_demovfs.c
index e990e98f2..e92fd5613 100644
--- a/src/test_demovfs.c
+++ b/src/test_demovfs.c
@@ -645,14 +645,7 @@ sqlite3_vfs *sqlite3_demovfs(void){
#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
#if SQLITE_OS_UNIX
static int SQLITE_TCLAPI register_demovfs(
diff --git a/src/test_fs.c b/src/test_fs.c
index f88f3a942..d821a83b9 100644
--- a/src/test_fs.c
+++ b/src/test_fs.c
@@ -62,12 +62,7 @@
** SELECT * FROM fstree WHERE path LIKE '/home/dan/sqlite/%'
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
-
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
diff --git a/src/test_func.c b/src/test_func.c
index 80df48828..8c06705ae 100644
--- a/src/test_func.c
+++ b/src/test_func.c
@@ -13,11 +13,7 @@
** implements new SQL functions used by the test scripts.
*/
#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
diff --git a/src/test_hexio.c b/src/test_hexio.c
index 61a41d5b1..8999d84d2 100644
--- a/src/test_hexio.c
+++ b/src/test_hexio.c
@@ -18,11 +18,7 @@
** easier and safer to build our own mechanism.
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@@ -155,7 +151,8 @@ static int SQLITE_TCLAPI hexio_write(
Tcl_Obj *CONST objv[]
){
int offset;
- int nIn, nOut, written;
+ Tcl_Size nIn;
+ int nOut, written;
const char *zFile;
const unsigned char *zIn;
unsigned char *aOut;
@@ -168,11 +165,11 @@ static int SQLITE_TCLAPI hexio_write(
if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR;
zFile = Tcl_GetString(objv[1]);
zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[3], &nIn);
- aOut = sqlite3_malloc( 1 + nIn/2 );
+ aOut = sqlite3_malloc64( 1 + nIn/2 );
if( aOut==0 ){
return TCL_ERROR;
}
- nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
+ nOut = sqlite3TestHexToBin(zIn, (int)nIn, aOut);
out = fopen(zFile, "r+b");
if( out==0 ){
out = fopen(zFile, "r+");
@@ -203,7 +200,8 @@ static int SQLITE_TCLAPI hexio_get_int(
Tcl_Obj *CONST objv[]
){
int val;
- int nIn, nOut;
+ Tcl_Size nIn;
+ int nOut;
const unsigned char *zIn;
unsigned char *aOut;
unsigned char aNum[4];
@@ -213,11 +211,11 @@ static int SQLITE_TCLAPI hexio_get_int(
return TCL_ERROR;
}
zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn);
- aOut = sqlite3_malloc( 1 + nIn/2 );
+ aOut = sqlite3_malloc64( 1 + nIn/2 );
if( aOut==0 ){
return TCL_ERROR;
}
- nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
+ nOut = sqlite3TestHexToBin(zIn, (int)nIn, aOut);
if( nOut>=4 ){
memcpy(aNum, aOut, 4);
}else{
@@ -300,7 +298,7 @@ static int SQLITE_TCLAPI utf8_to_utf8(
Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_DEBUG
- int n;
+ Tcl_Size n;
int nOut;
const unsigned char *zOrig;
unsigned char *z;
@@ -309,8 +307,8 @@ static int SQLITE_TCLAPI utf8_to_utf8(
return TCL_ERROR;
}
zOrig = (unsigned char *)Tcl_GetStringFromObj(objv[1], &n);
- z = sqlite3_malloc( n+4 );
- n = sqlite3TestHexToBin(zOrig, n, z);
+ z = sqlite3_malloc64( n+4 );
+ n = sqlite3TestHexToBin(zOrig, (int)n, z);
z[n] = 0;
nOut = sqlite3Utf8To8(z);
sqlite3TestBinToHex(z,nOut);
@@ -361,7 +359,7 @@ static int SQLITE_TCLAPI read_fts3varint(
int objc,
Tcl_Obj *CONST objv[]
){
- int nBlob;
+ Tcl_Size nBlob;
unsigned char *zBlob;
sqlite3_int64 iVal;
int nVal;
@@ -388,10 +386,10 @@ static int SQLITE_TCLAPI make_fts3record(
Tcl_Obj *CONST objv[]
){
Tcl_Obj **aArg = 0;
- int nArg = 0;
+ Tcl_Size nArg = 0;
unsigned char *aOut = 0;
- int nOut = 0;
- int nAlloc = 0;
+ sqlite3_int64 nOut = 0;
+ sqlite3_int64 nAlloc = 0;
int i;
if( objc!=2 ){
@@ -402,7 +400,7 @@ static int SQLITE_TCLAPI make_fts3record(
return TCL_ERROR;
}
- for(i=0; i<nArg; i++){
+ for(i=0; i<(int)nArg; i++){
sqlite3_int64 iVal;
if( TCL_OK==Tcl_GetWideIntFromObj(0, aArg[i], &iVal) ){
if( nOut+10>nAlloc ){
@@ -417,11 +415,11 @@ static int SQLITE_TCLAPI make_fts3record(
}
nOut += putFts3Varint((char*)&aOut[nOut], iVal);
}else{
- int nVal = 0;
+ Tcl_Size nVal = 0;
char *zVal = Tcl_GetStringFromObj(aArg[i], &nVal);
while( (nOut + nVal)>nAlloc ){
- int nNew = nAlloc?nAlloc*2:128;
- unsigned char *aNew = sqlite3_realloc(aOut, nNew);
+ sqlite3_int64 nNew = nAlloc?nAlloc*2:128;
+ unsigned char *aNew = sqlite3_realloc64(aOut, nNew);
if( aNew==0 ){
sqlite3_free(aOut);
return TCL_ERROR;
diff --git a/src/test_init.c b/src/test_init.c
index 400ab9a2b..f7b85875b 100644
--- a/src/test_init.c
+++ b/src/test_init.c
@@ -27,11 +27,7 @@
#include "sqliteInt.h"
#include <string.h>
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
static struct Wrapped {
sqlite3_pcache_methods2 pcache;
diff --git a/src/test_intarray.c b/src/test_intarray.c
index a978ed585..16c1df2e9 100644
--- a/src/test_intarray.c
+++ b/src/test_intarray.c
@@ -279,14 +279,7 @@ SQLITE_API int sqlite3_intarray_bind(
** Everything below is interface for testing this module.
*/
#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
/*
** Routines to encode and decode pointers
diff --git a/src/test_malloc.c b/src/test_malloc.c
index 8146501c9..21faa0d29 100644
--- a/src/test_malloc.c
+++ b/src/test_malloc.c
@@ -14,11 +14,7 @@
** memory allocation subsystem.
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@@ -387,7 +383,8 @@ static int SQLITE_TCLAPI test_memset(
Tcl_Obj *CONST objv[]
){
void *p;
- int size, n, i;
+ int size, i;
+ Tcl_Size n;
char *zHex;
char *zOut;
char zBin[100];
@@ -409,7 +406,7 @@ static int SQLITE_TCLAPI test_memset(
}
zHex = Tcl_GetStringFromObj(objv[3], &n);
if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;
- n = sqlite3TestHexToBin(zHex, n, zBin);
+ n = sqlite3TestHexToBin(zHex, (int)n, zBin);
if( n==0 ){
Tcl_AppendResult(interp, "no data", (char*)0);
return TCL_ERROR;
@@ -624,7 +621,7 @@ static int SQLITE_TCLAPI test_memdebug_fail(
if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR;
for(ii=2; ii<objc; ii+=2){
- int nOption;
+ Tcl_Size nOption;
char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption);
char *zErr = 0;
diff --git a/src/test_md5.c b/src/test_md5.c
index 7903797db..a09f1ad6c 100644
--- a/src/test_md5.c
+++ b/src/test_md5.c
@@ -16,14 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
/*
* This code implements the MD5 message-digest algorithm.
diff --git a/src/test_multiplex.c b/src/test_multiplex.c
index d06ed2f79..e5b43f4cc 100644
--- a/src/test_multiplex.c
+++ b/src/test_multiplex.c
@@ -1219,14 +1219,7 @@ int sqlite3_multiplex_shutdown(int eForce){
/***************************** Test Code ***********************************/
#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
extern const char *sqlite3ErrName(int);
diff --git a/src/test_mutex.c b/src/test_mutex.c
index a203208ab..e60a06df3 100644
--- a/src/test_mutex.c
+++ b/src/test_mutex.c
@@ -11,12 +11,7 @@
*************************************************************************
** This file contains test logic for the sqlite3_mutex interfaces.
*/
-
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include "sqlite3.h"
#include "sqliteInt.h"
#include <stdlib.h>
diff --git a/src/test_osinst.c b/src/test_osinst.c
index 062e83159..2d03d2bbc 100644
--- a/src/test_osinst.c
+++ b/src/test_osinst.c
@@ -1109,14 +1109,7 @@ int sqlite3_vfslog_register(sqlite3 *db){
#if defined(SQLITE_TEST) || defined(TCLSH)
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
static int SQLITE_TCLAPI test_vfslog(
void *clientData,
diff --git a/src/test_pcache.c b/src/test_pcache.c
index 5266d6769..ceefa13e5 100644
--- a/src/test_pcache.c
+++ b/src/test_pcache.c
@@ -99,7 +99,7 @@ static void testpcacheShutdown(void *pArg){
*/
typedef struct testpcache testpcache;
struct testpcache {
- int szPage; /* Size of each page. Multiple of 8. */
+ sqlite3_int64 szPage; /* Size of each page. Multiple of 8. */
int szExtra; /* Size of extra data that accompanies each page */
int bPurgeable; /* True if the page cache is purgeable */
int nFree; /* Number of unused slots in a[] */
@@ -141,6 +141,7 @@ static sqlite3_pcache *testpcacheCreate(
int i;
assert( testpcacheGlobal.pDummy!=0 );
szPage = (szPage+7)&~7;
+ szExtra = (szPage+7)&~7;
nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*(szPage+szExtra);
p = sqlite3_malloc( nMem );
if( p==0 ) return 0;
diff --git a/src/test_quota.c b/src/test_quota.c
index b436de466..1bfc5ce11 100644
--- a/src/test_quota.c
+++ b/src/test_quota.c
@@ -1278,14 +1278,7 @@ int sqlite3_quota_remove(const char *zFilename){
/***************************** Test Code ***********************************/
#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
/*
** Argument passed to a TCL quota-over-limit callback.
@@ -1420,7 +1413,7 @@ static int SQLITE_TCLAPI test_quota_set(
Tcl_Obj *pScript; /* Tcl script to invoke to increase quota */
int rc; /* Value returned by quota_set() */
TclQuotaCallback *p; /* Callback object */
- int nScript; /* Length of callback script */
+ Tcl_Size nScript; /* Length of callback script */
void (*xDestroy)(void*); /* Optional destructor for pArg */
void (*xCallback)(const char *, sqlite3_int64 *, sqlite3_int64, void *);
diff --git a/src/test_rtree.c b/src/test_rtree.c
index 0c6dbf3cd..53af6e5cf 100644
--- a/src/test_rtree.c
+++ b/src/test_rtree.c
@@ -14,11 +14,7 @@
*/
#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
/* Solely for the UNUSED_PARAMETER() macro. */
#include "sqliteInt.h"
@@ -357,11 +353,7 @@ static int bfs_query_func(sqlite3_rtree_query_info *p){
*************************************************************************/
#include <assert.h>
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
typedef struct Cube Cube;
struct Cube {
diff --git a/src/test_schema.c b/src/test_schema.c
index 2cbc18e2b..660d21ea4 100644
--- a/src/test_schema.c
+++ b/src/test_schema.c
@@ -36,11 +36,7 @@
*/
#ifdef SQLITE_TEST
# include "sqliteInt.h"
-# if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-# else
-# include "tcl.h"
-# endif
+# include "tclsqlite.h"
#else
# include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
diff --git a/src/test_superlock.c b/src/test_superlock.c
index 45d0d623a..7f3bf163a 100644
--- a/src/test_superlock.c
+++ b/src/test_superlock.c
@@ -256,14 +256,7 @@ int sqlite3demo_superlock(
#ifdef SQLITE_TEST
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
struct InterpAndScript {
Tcl_Interp *interp;
diff --git a/src/test_syscall.c b/src/test_syscall.c
index 3cd1034d3..af2ae1001 100644
--- a/src/test_syscall.c
+++ b/src/test_syscall.c
@@ -76,11 +76,7 @@
#include "sqliteInt.h"
#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@@ -197,7 +193,7 @@ static int tsIsFail(void){
*/
static int tsErrno(const char *zFunc){
int i;
- int nFunc = strlen(zFunc);
+ size_t nFunc = strlen(zFunc);
for(i=0; aSyscall[i].zName; i++){
if( strlen(aSyscall[i].zName)!=nFunc ) continue;
if( memcmp(aSyscall[i].zName, zFunc, nFunc) ) continue;
@@ -429,7 +425,7 @@ static int SQLITE_TCLAPI test_syscall_install(
Tcl_Obj *CONST objv[]
){
sqlite3_vfs *pVfs;
- int nElem;
+ Tcl_Size nElem;
int i;
Tcl_Obj **apElem;
@@ -442,7 +438,7 @@ static int SQLITE_TCLAPI test_syscall_install(
}
pVfs = sqlite3_vfs_find(0);
- for(i=0; i<nElem; i++){
+ for(i=0; i<(int)nElem; i++){
int iCall;
int rc = Tcl_GetIndexFromObjStruct(interp,
apElem[i], aSyscall, sizeof(aSyscall[0]), "system-call", 0, &iCall
@@ -502,7 +498,7 @@ static int SQLITE_TCLAPI test_syscall_reset(
rc = pVfs->xSetSystemCall(pVfs, 0, 0);
for(i=0; aSyscall[i].zName; i++) aSyscall[i].xOrig = 0;
}else{
- int nFunc;
+ Tcl_Size nFunc;
char *zFunc = Tcl_GetStringFromObj(objv[2], &nFunc);
rc = pVfs->xSetSystemCall(pVfs, Tcl_GetString(objv[2]), 0);
for(i=0; rc==SQLITE_OK && aSyscall[i].zName; i++){
diff --git a/src/test_tclsh.c b/src/test_tclsh.c
index 4697c3b85..db362049e 100644
--- a/src/test_tclsh.c
+++ b/src/test_tclsh.c
@@ -20,14 +20,7 @@
** in an effort to keep the tclsqlite.c file pure.
*/
#include "sqlite3.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-# ifndef SQLITE_TCLAPI
-# define SQLITE_TCLAPI
-# endif
-#endif
+#include "tclsqlite.h"
/* Needed for the setrlimit() system call on unix */
#if defined(unix)
diff --git a/src/test_tclvar.c b/src/test_tclvar.c
index 36165bc27..9be877449 100644
--- a/src/test_tclvar.c
+++ b/src/test_tclvar.c
@@ -36,11 +36,7 @@
** according to "fullname" and "value" only.
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#include <stdlib.h>
#include <string.h>
@@ -150,10 +146,10 @@ static int next2(Tcl_Interp *interp, tclvar_cursor *pCur, Tcl_Obj *pObj){
Tcl_IncrRefCount(pCur->pList2);
assert( pCur->i2==0 );
}else{
- int n = 0;
+ Tcl_Size n = 0;
pCur->i2++;
Tcl_ListObjLength(0, pCur->pList2, &n);
- if( pCur->i2>=n ){
+ if( pCur->i2>=(int)n ){
Tcl_DecrRefCount(pCur->pList2);
pCur->pList2 = 0;
pCur->i2 = 0;
@@ -167,14 +163,14 @@ static int next2(Tcl_Interp *interp, tclvar_cursor *pCur, Tcl_Obj *pObj){
static int tclvarNext(sqlite3_vtab_cursor *cur){
Tcl_Obj *pObj;
- int n = 0;
+ Tcl_Size n = 0;
int ok = 0;
tclvar_cursor *pCur = (tclvar_cursor *)cur;
Tcl_Interp *interp = ((tclvar_vtab *)(cur->pVtab))->interp;
Tcl_ListObjLength(0, pCur->pList1, &n);
- while( !ok && pCur->i1<n ){
+ while( !ok && pCur->i1<(int)n ){
Tcl_ListObjIndex(0, pCur->pList1, pCur->i1, &pObj);
ok = next2(interp, pCur, pObj);
if( !ok ){
diff --git a/src/test_thread.c b/src/test_thread.c
index 126fd9836..7c06d110a 100644
--- a/src/test_thread.c
+++ b/src/test_thread.c
@@ -16,11 +16,7 @@
*/
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#if SQLITE_THREADSAFE
@@ -94,7 +90,7 @@ static int SQLITE_TCLAPI tclScriptEvent(Tcl_Event *evPtr, int flags){
static void postToParent(SqlThread *p, Tcl_Obj *pScript){
EvalEvent *pEvent;
char *zMsg;
- int nMsg;
+ Tcl_Size nMsg;
zMsg = Tcl_GetStringFromObj(pScript, &nMsg);
pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1);
@@ -181,8 +177,8 @@ static int SQLITE_TCLAPI sqlthread_spawn(
SqlThread *pNew;
int rc;
- int nVarname; char *zVarname;
- int nScript; char *zScript;
+ Tcl_Size nVarname; char *zVarname;
+ Tcl_Size nScript; char *zScript;
/* Parameters for thread creation */
const int nStack = TCL_THREAD_STACK_DEFAULT;
@@ -232,7 +228,7 @@ static int SQLITE_TCLAPI sqlthread_parent(
){
EvalEvent *pEvent;
char *zMsg;
- int nMsg;
+ Tcl_Size nMsg;
SqlThread *p = (SqlThread *)clientData;
assert(objc==3);
diff --git a/src/test_vdbecov.c b/src/test_vdbecov.c
index a001b1df0..283936aeb 100644
--- a/src/test_vdbecov.c
+++ b/src/test_vdbecov.c
@@ -15,11 +15,7 @@
#include "sqlite3.h"
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
#ifdef SQLITE_VDBE_COVERAGE
diff --git a/src/test_vfs.c b/src/test_vfs.c
index 312e1a1be..9f84b4f80 100644
--- a/src/test_vfs.c
+++ b/src/test_vfs.c
@@ -28,11 +28,7 @@
#include "sqlite3.h"
#include "sqliteInt.h"
-#if defined(INCLUDE_SQLITE_TCL_H)
-# include "sqlite_tcl.h"
-#else
-# include "tcl.h"
-#endif
+#include "tclsqlite.h"
typedef struct Testvfs Testvfs;
typedef struct TestvfsShm TestvfsShm;
@@ -1150,15 +1146,15 @@ static int SQLITE_TCLAPI testvfs_obj_cmd(
return TCL_ERROR;
}
if( objc==4 ){
- int n;
+ Tcl_Size n;
u8 *a = Tcl_GetByteArrayFromObj(objv[3], &n);
int pgsz = pBuffer->pgsz;
if( pgsz==0 ) pgsz = 65536;
- for(i=0; i*pgsz<n; i++){
+ for(i=0; i*pgsz<(int)n; i++){
int nByte = pgsz;
tvfsAllocPage(pBuffer, i, pgsz);
if( n-i*pgsz<pgsz ){
- nByte = n;
+ nByte = (int)n;
}
memcpy(pBuffer->aPage[i], &a[i*pgsz], nByte);
}
@@ -1203,7 +1199,7 @@ static int SQLITE_TCLAPI testvfs_obj_cmd(
{ "xFileControl", TESTVFS_FCNTL_MASK },
};
Tcl_Obj **apElem = 0;
- int nElem = 0;
+ Tcl_Size nElem = 0;
int mask = 0;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "LIST");
@@ -1213,7 +1209,7 @@ static int SQLITE_TCLAPI testvfs_obj_cmd(
return TCL_ERROR;
}
Tcl_ResetResult(interp);
- for(i=0; i<nElem; i++){
+ for(i=0; i<(int)nElem; i++){
int iMethod;
char *zElem = Tcl_GetString(apElem[i]);
for(iMethod=0; iMethod<ArraySize(vfsmethod); iMethod++){
@@ -1239,7 +1235,7 @@ static int SQLITE_TCLAPI testvfs_obj_cmd(
*/
case CMD_SCRIPT: {
if( objc==3 ){
- int nByte;
+ Tcl_Size nByte;
if( p->pScript ){
Tcl_DecrRefCount(p->pScript);
p->pScript = 0;
@@ -1337,13 +1333,13 @@ static int SQLITE_TCLAPI testvfs_obj_cmd(
int j;
int iNew = 0;
Tcl_Obj **flags = 0;
- int nFlags = 0;
+ Tcl_Size nFlags = 0;
if( Tcl_ListObjGetElements(interp, objv[2], &nFlags, &flags) ){
return TCL_ERROR;
}
- for(j=0; j<nFlags; j++){
+ for(j=0; j<(int)nFlags; j++){
int idx = 0;
if( Tcl_GetIndexFromObjStruct(interp, flags[j], aFlag,
sizeof(aFlag[0]), "flag", 0, &idx)
@@ -1491,7 +1487,7 @@ static int SQLITE_TCLAPI testvfs_cmd(
if( objc<2 || 0!=(objc%2) ) goto bad_args;
for(i=2; i<objc; i += 2){
- int nSwitch;
+ Tcl_Size nSwitch;
char *zSwitch;
zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch);
diff --git a/src/test_window.c b/src/test_window.c
index 48ab02211..631b20162 100644
--- a/src/test_window.c
+++ b/src/test_window.c
@@ -16,7 +16,7 @@
#ifdef SQLITE_TEST
#include "sqliteInt.h"
-#include <tcl.h>
+#include "tclsqlite.h"
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
extern const char *sqlite3ErrName(int);
diff --git a/src/treeview.c b/src/treeview.c
index 054265338..3960d2859 100644
--- a/src/treeview.c
+++ b/src/treeview.c
@@ -237,14 +237,12 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
}
if( pItem->pSelect ){
- sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
if( pItem->pTab ){
Table *pTab = pItem->pTab;
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
}
assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
- sqlite3TreeViewPop(&pView);
}
if( pItem->fg.isTabFunc ){
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
@@ -286,7 +284,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
n = 1000;
}else{
n = 0;
- if( p->pSrc && p->pSrc->nSrc ) n++;
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
@@ -312,7 +310,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
sqlite3TreeViewPop(&pView);
}
#endif
- if( p->pSrc && p->pSrc->nSrc ){
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){
sqlite3TreeViewPush(&pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
sqlite3TreeViewSrcList(pView, p->pSrc);
diff --git a/src/vdbe.c b/src/vdbe.c
index 28f12e054..d097bfd8b 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -5308,6 +5308,7 @@ case OP_Found: { /* jump, in3, ncycle */
r.pKeyInfo = pC->pKeyInfo;
r.default_rc = 0;
#ifdef SQLITE_DEBUG
+ (void)sqlite3FaultSim(50); /* For use by --counter in TH3 */
for(ii=0; ii<r.nField; ii++){
assert( memIsValid(&r.aMem[ii]) );
assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
@@ -7670,18 +7671,29 @@ case OP_AggInverse:
case OP_AggStep: {
int n;
sqlite3_context *pCtx;
+ u64 nAlloc;
assert( pOp->p4type==P4_FUNCDEF );
n = pOp->p5;
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) +
- (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*)));
+
+ /* Allocate space for (a) the context object and (n-1) extra pointers
+ ** to append to the sqlite3_context.argv[1] array, and (b) a memory
+ ** cell in which to store the accumulation. Be careful that the memory
+ ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits.
+ **
+ ** Note: We could avoid this by using a regular memory cell from aMem[] for
+ ** the accumulator, instead of allocating one here. */
+ nAlloc = ROUND8P( sizeof(pCtx[0]) + (n-1)*sizeof(sqlite3_value*) );
+ pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
if( pCtx==0 ) goto no_mem;
- pCtx->pMem = 0;
- pCtx->pOut = (Mem*)&(pCtx->argv[n]);
+ pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
+ assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) );
+
sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
+ pCtx->pMem = 0;
pCtx->pFunc = pOp->p4.pFunc;
pCtx->iOp = (int)(pOp - aOp);
pCtx->pVdbe = p;
diff --git a/src/vdbe.h b/src/vdbe.h
index 9001ace2e..f40f68d24 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -32,6 +32,19 @@ typedef struct Vdbe Vdbe;
*/
typedef struct sqlite3_value Mem;
typedef struct SubProgram SubProgram;
+typedef struct SubrtnSig SubrtnSig;
+
+/*
+** A signature for a reusable subroutine that materializes the RHS of
+** an IN operator.
+*/
+struct SubrtnSig {
+ int selId; /* SELECT-id for the SELECT statement on the RHS */
+ char *zAff; /* Affinity of the overall IN expression */
+ int iTable; /* Ephemeral table generated by the subroutine */
+ int iAddr; /* Subroutine entry address */
+ int regReturn; /* Register used to hold return address */
+};
/*
** A single instruction of the virtual machine has an opcode
@@ -60,6 +73,7 @@ struct VdbeOp {
u32 *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
Table *pTab; /* Used when p4type is P4_TABLE */
+ SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
@@ -127,6 +141,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
+#define P4_SUBRTNSIG (-17) /* P4 is a SubrtnSig pointer */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 665f6cd17..f1e0cccdc 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1413,6 +1413,12 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4);
break;
}
+ case P4_SUBRTNSIG: {
+ SubrtnSig *pSig = (SubrtnSig*)p4;
+ sqlite3DbFree(db, pSig->zAff);
+ sqlite3DbFree(db, pSig);
+ break;
+ }
}
}
@@ -1992,6 +1998,11 @@ char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
zP4 = pOp->p4.pTab->zName;
break;
}
+ case P4_SUBRTNSIG: {
+ SubrtnSig *pSig = pOp->p4.pSubrtnSig;
+ sqlite3_str_appendf(&x, "subrtnsig:%d,%s", pSig->selId, pSig->zAff);
+ break;
+ }
default: {
zP4 = pOp->p4.z;
}
diff --git a/src/where.c b/src/where.c
index ba4631c6c..a9a258995 100644
--- a/src/where.c
+++ b/src/where.c
@@ -719,6 +719,12 @@ static void translateColumnToCopy(
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
if( pParse->db->mallocFailed ) return;
+#ifdef SQLITE_DEBUG
+ if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
+ printf("CHECKING for column-to-copy on cursor %d for %d..%d\n",
+ iTabCur, iStart, iEnd);
+ }
+#endif
for(; iStart<iEnd; iStart++, pOp++){
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){