mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Merge trunk changes into this branch.
FossilOrigin-Name: 63e8846ac1dc1cf1f7071c4634ccbfec3c13560db6afec376cd91515b62430d3
This commit is contained in:
@@ -872,7 +872,7 @@ static void statGet(
|
||||
if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
|
||||
sqlite3_str_appendf(&sStat, " %llu", iVal);
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
assert( p->current.anEq[i] );
|
||||
assert( p->current.anEq[i] || p->nRow==0 );
|
||||
#endif
|
||||
}
|
||||
sqlite3ResultStrAccum(context, &sStat);
|
||||
@@ -1057,7 +1057,7 @@ static void analyzeOneTable(
|
||||
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
int nCol; /* Number of columns in pIdx. "N" */
|
||||
int addrRewind; /* Address of "OP_Rewind iIdxCur" */
|
||||
int addrGotoEnd; /* Address of "OP_Rewind iIdxCur" */
|
||||
int addrNextRow; /* Address of "next_row:" */
|
||||
const char *zIdxName; /* Name of the index */
|
||||
int nColTest; /* Number of columns to test for changes */
|
||||
@@ -1081,9 +1081,14 @@ static void analyzeOneTable(
|
||||
/*
|
||||
** Pseudo-code for loop that calls stat_push():
|
||||
**
|
||||
** Rewind csr
|
||||
** if eof(csr) goto end_of_scan;
|
||||
** regChng = 0
|
||||
** Rewind csr
|
||||
** if eof(csr){
|
||||
** stat_init() with count = 0;
|
||||
** goto end_of_scan;
|
||||
** }
|
||||
** count()
|
||||
** stat_init()
|
||||
** goto chng_addr_0;
|
||||
**
|
||||
** next_row:
|
||||
@@ -1122,41 +1127,36 @@ static void analyzeOneTable(
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
|
||||
/* Invoke the stat_init() function. The arguments are:
|
||||
**
|
||||
/* Implementation of the following:
|
||||
**
|
||||
** regChng = 0
|
||||
** Rewind csr
|
||||
** if eof(csr){
|
||||
** stat_init() with count = 0;
|
||||
** goto end_of_scan;
|
||||
** }
|
||||
** count()
|
||||
** stat_init()
|
||||
** goto chng_addr_0;
|
||||
*/
|
||||
assert( regTemp2==regStat+4 );
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
|
||||
|
||||
/* Arguments to stat_init():
|
||||
** (1) the number of columns in the index including the rowid
|
||||
** (or for a WITHOUT ROWID table, the number of PK columns),
|
||||
** (2) the number of columns in the key without the rowid/pk
|
||||
** (3) estimated number of rows in the index,
|
||||
*/
|
||||
** (3) estimated number of rows in the index. */
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1);
|
||||
assert( regRowid==regStat+2 );
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid);
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
if( OptimizationEnabled(db, SQLITE_Stat4) ){
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regTemp);
|
||||
addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
|
||||
VdbeCoverage(v);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, 1);
|
||||
}
|
||||
assert( regTemp2==regStat+4 );
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
|
||||
sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp,
|
||||
OptimizationDisabled(db, SQLITE_Stat4));
|
||||
sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4,
|
||||
&statInitFuncdef, 0);
|
||||
addrGotoEnd = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
|
||||
VdbeCoverage(v);
|
||||
|
||||
/* Implementation of the following:
|
||||
**
|
||||
** Rewind csr
|
||||
** if eof(csr) goto end_of_scan;
|
||||
** regChng = 0
|
||||
** goto next_push_0;
|
||||
**
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
|
||||
addrNextRow = sqlite3VdbeCurrentAddr(v);
|
||||
|
||||
@@ -1263,6 +1263,12 @@ static void analyzeOneTable(
|
||||
}
|
||||
|
||||
/* Add the entry to the stat1 table. */
|
||||
if( pIdx->pPartIdxWhere ){
|
||||
/* Partial indexes might get a zero-entry in sqlite_stat1. But
|
||||
** an empty table is omitted from sqlite_stat1. */
|
||||
sqlite3VdbeJumpHere(v, addrGotoEnd);
|
||||
addrGotoEnd = 0;
|
||||
}
|
||||
callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1);
|
||||
assert( "BBB"[0]==SQLITE_AFF_TEXT );
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
|
||||
@@ -1286,6 +1292,12 @@ static void analyzeOneTable(
|
||||
int addrIsNull;
|
||||
u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
|
||||
|
||||
/* No STAT4 data is generated if the number of rows is zero */
|
||||
if( addrGotoEnd==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Cast, regStat1, SQLITE_AFF_INTEGER);
|
||||
addrGotoEnd = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1);
|
||||
}
|
||||
|
||||
if( doOnce ){
|
||||
int mxCol = nCol;
|
||||
Index *pX;
|
||||
@@ -1338,7 +1350,7 @@ static void analyzeOneTable(
|
||||
#endif /* SQLITE_ENABLE_STAT4 */
|
||||
|
||||
/* End of analysis */
|
||||
sqlite3VdbeJumpHere(v, addrRewind);
|
||||
if( addrGotoEnd ) sqlite3VdbeJumpHere(v, addrGotoEnd);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -6182,10 +6182,10 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
|
||||
/* Currently this interface is only called by the OP_IfSmaller
|
||||
** opcode, and it that case the cursor will always be valid and
|
||||
** will always point to a leaf node. */
|
||||
if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1;
|
||||
/* Currently this interface is only called by the OP_IfSizeBetween
|
||||
** opcode and the OP_Count opcode with P3=1. In either case,
|
||||
** the cursor will always be valid unless the btree is empty. */
|
||||
if( pCur->eState!=CURSOR_VALID ) return 0;
|
||||
if( NEVER(pCur->pPage->leaf==0) ) return -1;
|
||||
|
||||
n = pCur->pPage->nCell;
|
||||
|
@@ -2923,11 +2923,11 @@ void sqlite3EndTable(
|
||||
/* Test for cycles in generated columns and illegal expressions
|
||||
** in CHECK constraints and in DEFAULT clauses. */
|
||||
if( p->tabFlags & TF_HasGenerated ){
|
||||
sqlite3VdbeAddOp4(v, OP_SqlExec, 1, 0, 0,
|
||||
sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
|
||||
sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"",
|
||||
db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_SqlExec, 1, 0, 0,
|
||||
sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0,
|
||||
sqlite3MPrintf(db, "PRAGMA \"%w\".integrity_check(%Q)",
|
||||
db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC);
|
||||
}
|
||||
|
@@ -1295,8 +1295,12 @@ static int unixLogErrorAtLine(
|
||||
** available, the error message will often be an empty string. Not a
|
||||
** huge problem. Incorrectly concluding that the GNU version is available
|
||||
** could lead to a segfault though.
|
||||
**
|
||||
** Forum post 3f13857fa4062301 reports that the Android SDK may use
|
||||
** int-type return, depending on its version.
|
||||
*/
|
||||
#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
|
||||
#if (defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)) \
|
||||
&& !defined(ANDROID) && !defined(__ANDROID__)
|
||||
zErr =
|
||||
# endif
|
||||
strerror_r(iErrno, aErr, sizeof(aErr)-1);
|
||||
|
187
src/pragma.c
187
src/pragma.c
@@ -30,6 +30,34 @@
|
||||
** ../tool/mkpragmatab.tcl. */
|
||||
#include "pragma.h"
|
||||
|
||||
/*
|
||||
** When the 0x10 bit of PRAGMA optimize is set, any ANALYZE commands
|
||||
** will be run with an analysis_limit set to the lessor of the value of
|
||||
** the following macro or to the actual analysis_limit if it is non-zero,
|
||||
** in order to prevent PRAGMA optimize from running for too long.
|
||||
**
|
||||
** The value of 2000 is chosen emperically so that the worst-case run-time
|
||||
** for PRAGMA optimize does not exceed 100 milliseconds against a variety
|
||||
** of test databases on a RaspberryPI-4 compiled using -Os and without
|
||||
** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of
|
||||
** his paragraph, "worst-case" means that ANALYZE ends up being
|
||||
** run on every table in the database. The worst case typically only
|
||||
** happens if PRAGMA optimize is run on a database file for which ANALYZE
|
||||
** has not been previously run and the 0x10000 flag is included so that
|
||||
** all tables are analyzed. The usual case for PRAGMA optimize is that
|
||||
** no ANALYZE commands will be run at all, or if any ANALYZE happens it
|
||||
** will be against a single table, so that expected timing for PRAGMA
|
||||
** optimize on a PI-4 is more like 1 millisecond or less with the 0x10000
|
||||
** flag or less than 100 microseconds without the 0x10000 flag.
|
||||
**
|
||||
** An analysis limit of 2000 is almost always sufficient for the query
|
||||
** planner to fully characterize an index. The additional accuracy from
|
||||
** a larger analysis is not usually helpful.
|
||||
*/
|
||||
#ifndef SQLITE_DEFAULT_OPTIMIZE_LIMIT
|
||||
# define SQLITE_DEFAULT_OPTIMIZE_LIMIT 2000
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Interpret the given string as a safety level. Return 0 for OFF,
|
||||
** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or
|
||||
@@ -2383,44 +2411,63 @@ void sqlite3Pragma(
|
||||
**
|
||||
** The optional argument is a bitmask of optimizations to perform:
|
||||
**
|
||||
** 0x0001 Debugging mode. Do not actually perform any optimizations
|
||||
** but instead return one line of text for each optimization
|
||||
** that would have been done. Off by default.
|
||||
** 0x00001 Debugging mode. Do not actually perform any optimizations
|
||||
** but instead return one line of text for each optimization
|
||||
** that would have been done. Off by default.
|
||||
**
|
||||
** 0x0002 Run ANALYZE on tables that might benefit. On by default.
|
||||
** See below for additional information.
|
||||
** 0x00002 Run ANALYZE on tables that might benefit. On by default.
|
||||
** See below for additional information.
|
||||
**
|
||||
** 0x0004 (Not yet implemented) Record usage and performance
|
||||
** information from the current session in the
|
||||
** database file so that it will be available to "optimize"
|
||||
** pragmas run by future database connections.
|
||||
** 0x00010 Run all ANALYZE operations using an analysis_limit that
|
||||
** is the lessor of the current analysis_limit and the
|
||||
** SQLITE_DEFAULT_OPTIMIZE_LIMIT compile-time option.
|
||||
** The default value of SQLITE_DEFAULT_OPTIMIZE_LIMIT is
|
||||
** currently (2024-02-19) set to 2000, which is such that
|
||||
** the worst case run-time for PRAGMA optimize on a 100MB
|
||||
** database will usually be less than 100 milliseconds on
|
||||
** a RaspberryPI-4 class machine. On by default.
|
||||
**
|
||||
** 0x0008 (Not yet implemented) Create indexes that might have
|
||||
** been helpful to recent queries
|
||||
** 0x10000 Look at tables to see if they need to be reanalyzed
|
||||
** due to growth or shrinkage even if they have not been
|
||||
** queried during the current connection. Off by default.
|
||||
**
|
||||
** The default MASK is and always shall be 0xfffe. 0xfffe means perform all
|
||||
** of the optimizations listed above except Debug Mode, including new
|
||||
** optimizations that have not yet been invented. If new optimizations are
|
||||
** ever added that should be off by default, those off-by-default
|
||||
** optimizations will have bitmasks of 0x10000 or larger.
|
||||
** The default MASK is and always shall be 0x0fffe. In the current
|
||||
** implementation, the default mask only covers the 0x00002 optimization,
|
||||
** though additional optimizations that are covered by 0x0fffe might be
|
||||
** added in the future. Optimizations that are off by default and must
|
||||
** be explicitly requested have masks of 0x10000 or greater.
|
||||
**
|
||||
** DETERMINATION OF WHEN TO RUN ANALYZE
|
||||
**
|
||||
** In the current implementation, a table is analyzed if only if all of
|
||||
** the following are true:
|
||||
**
|
||||
** (1) MASK bit 0x02 is set.
|
||||
** (1) MASK bit 0x00002 is set.
|
||||
**
|
||||
** (2) The query planner used sqlite_stat1-style statistics for one or
|
||||
** more indexes of the table at some point during the lifetime of
|
||||
** the current connection.
|
||||
** (2) The table is an ordinary table, not a virtual table or view.
|
||||
**
|
||||
** (3) One or more indexes of the table are currently unanalyzed OR
|
||||
** the number of rows in the table has increased by 25 times or more
|
||||
** since the last time ANALYZE was run.
|
||||
** (3) The table name does not begin with "sqlite_".
|
||||
**
|
||||
** (4) One or more of the following is true:
|
||||
** (4a) The 0x10000 MASK bit is set.
|
||||
** (4b) One or more indexes on the table lacks an entry
|
||||
** in the sqlite_stat1 table.
|
||||
** (4c) The query planner used sqlite_stat1-style statistics for one
|
||||
** or more indexes of the table at some point during the lifetime
|
||||
** of the current connection.
|
||||
**
|
||||
** (5) One or more of the following is true:
|
||||
** (5a) One or more indexes on the table lacks an entry
|
||||
** in the sqlite_stat1 table. (Same as 4a)
|
||||
** (5b) The number of rows in the table has increased or decreased by
|
||||
** 10-fold. In other words, the current size of the table is
|
||||
** 10 times larger than the size in sqlite_stat1 or else the
|
||||
** current size is less than 1/10th the size in sqlite_stat1.
|
||||
**
|
||||
** The rules for when tables are analyzed are likely to change in
|
||||
** future releases.
|
||||
** future releases. Future versions of SQLite might accept a string
|
||||
** literal argument to this pragma that contains a mnemonic description
|
||||
** of the options rather than a bitmap.
|
||||
*/
|
||||
case PragTyp_OPTIMIZE: {
|
||||
int iDbLast; /* Loop termination point for the schema loop */
|
||||
@@ -2432,6 +2479,10 @@ void sqlite3Pragma(
|
||||
LogEst szThreshold; /* Size threshold above which reanalysis needed */
|
||||
char *zSubSql; /* SQL statement for the OP_SqlExec opcode */
|
||||
u32 opMask; /* Mask of operations to perform */
|
||||
int nLimit; /* Analysis limit to use */
|
||||
int nCheck = 0; /* Number of tables to be optimized */
|
||||
int nBtree = 0; /* Number of btrees to scan */
|
||||
int nIndex; /* Number of indexes on the current table */
|
||||
|
||||
if( zRight ){
|
||||
opMask = (u32)sqlite3Atoi(zRight);
|
||||
@@ -2439,6 +2490,14 @@ void sqlite3Pragma(
|
||||
}else{
|
||||
opMask = 0xfffe;
|
||||
}
|
||||
if( (opMask & 0x10)==0 ){
|
||||
nLimit = 0;
|
||||
}else if( db->nAnalysisLimit>0
|
||||
&& db->nAnalysisLimit<SQLITE_DEFAULT_OPTIMIZE_LIMIT ){
|
||||
nLimit = 0;
|
||||
}else{
|
||||
nLimit = SQLITE_DEFAULT_OPTIMIZE_LIMIT;
|
||||
}
|
||||
iTabCur = pParse->nTab++;
|
||||
for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){
|
||||
if( iDb==1 ) continue;
|
||||
@@ -2447,23 +2506,61 @@ void sqlite3Pragma(
|
||||
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||
pTab = (Table*)sqliteHashData(k);
|
||||
|
||||
/* If table pTab has not been used in a way that would benefit from
|
||||
** having analysis statistics during the current session, then skip it.
|
||||
** This also has the effect of skipping virtual tables and views */
|
||||
if( (pTab->tabFlags & TF_MaybeReanalyze)==0 ) continue;
|
||||
/* This only works for ordinary tables */
|
||||
if( !IsOrdinaryTable(pTab) ) continue;
|
||||
|
||||
/* Reanalyze if the table is 25 times larger than the last analysis */
|
||||
szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 );
|
||||
/* Do not scan system tables */
|
||||
if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ) continue;
|
||||
|
||||
/* Find the size of the table as last recorded in sqlite_stat1.
|
||||
** If any index is unanalyzed, then the threshold is -1 to
|
||||
** indicate a new, unanalyzed index
|
||||
*/
|
||||
szThreshold = pTab->nRowLogEst;
|
||||
nIndex = 0;
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
nIndex++;
|
||||
if( !pIdx->hasStat1 ){
|
||||
szThreshold = 0; /* Always analyze if any index lacks statistics */
|
||||
break;
|
||||
szThreshold = -1; /* Always analyze if any index lacks statistics */
|
||||
}
|
||||
}
|
||||
if( szThreshold ){
|
||||
sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
|
||||
sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur,
|
||||
sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold);
|
||||
|
||||
/* If table pTab has not been used in a way that would benefit from
|
||||
** having analysis statistics during the current session, then skip it,
|
||||
** unless the 0x10000 MASK bit is set. */
|
||||
if( (pTab->tabFlags & TF_MaybeReanalyze)!=0 ){
|
||||
/* Check for size change if stat1 has been used for a query */
|
||||
}else if( opMask & 0x10000 ){
|
||||
/* Check for size change if 0x10000 is set */
|
||||
}else if( pTab->pIndex!=0 && szThreshold<0 ){
|
||||
/* Do analysis if unanalyzed indexes exists */
|
||||
}else{
|
||||
/* Otherwise, we can skip this table */
|
||||
continue;
|
||||
}
|
||||
|
||||
nCheck++;
|
||||
if( nCheck==2 ){
|
||||
/* If ANALYZE might be invoked two or more times, hold a write
|
||||
** transaction for efficiency */
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
}
|
||||
nBtree += nIndex+1;
|
||||
|
||||
/* Reanalyze if the table is 10 times larger or smaller than
|
||||
** the last analysis. Unconditional reanalysis if there are
|
||||
** unanalyzed indexes. */
|
||||
sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
|
||||
if( szThreshold>=0 ){
|
||||
const LogEst iRange = 33; /* 10x size change */
|
||||
sqlite3VdbeAddOp4Int(v, OP_IfSizeBetween, iTabCur,
|
||||
sqlite3VdbeCurrentAddr(v)+2+(opMask&1),
|
||||
szThreshold>=iRange ? szThreshold-iRange : -1,
|
||||
szThreshold+iRange);
|
||||
VdbeCoverage(v);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, iTabCur,
|
||||
sqlite3VdbeCurrentAddr(v)+2+(opMask&1));
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"",
|
||||
@@ -2473,11 +2570,27 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1);
|
||||
}else{
|
||||
sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC);
|
||||
sqlite3VdbeAddOp4(v, OP_SqlExec, nLimit ? 0x02 : 00, nLimit, 0,
|
||||
zSubSql, P4_DYNAMIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp0(v, OP_Expire);
|
||||
|
||||
/* In a schema with a large number of tables and indexes, scale back
|
||||
** the analysis_limit to avoid excess run-time in the worst case.
|
||||
*/
|
||||
if( !db->mallocFailed && nLimit>0 && nBtree>100 ){
|
||||
int iAddr, iEnd;
|
||||
VdbeOp *aOp;
|
||||
nLimit = 100*nLimit/nBtree;
|
||||
if( nLimit<100 ) nLimit = 100;
|
||||
aOp = sqlite3VdbeGetOp(v, 0);
|
||||
iEnd = sqlite3VdbeCurrentAddr(v);
|
||||
for(iAddr=0; iAddr<iEnd; iAddr++){
|
||||
if( aOp[iAddr].opcode==OP_SqlExec ) aOp[iAddr].p2 = nLimit;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -534,13 +534,14 @@ void sqlite3_str_vappendf(
|
||||
}
|
||||
|
||||
exp = s.iDP-1;
|
||||
if( xtype==etGENERIC && precision>0 ) precision--;
|
||||
|
||||
/*
|
||||
** If the field type is etGENERIC, then convert to either etEXP
|
||||
** or etFLOAT, as appropriate.
|
||||
*/
|
||||
if( xtype==etGENERIC ){
|
||||
assert( precision>0 );
|
||||
precision--;
|
||||
flag_rtz = !flag_alternateform;
|
||||
if( exp<-4 || exp>precision ){
|
||||
xtype = etEXP;
|
||||
|
44
src/vdbe.c
44
src/vdbe.c
@@ -2086,7 +2086,7 @@ case OP_RealAffinity: { /* in1 */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_ANALYZE)
|
||||
/* Opcode: Cast P1 P2 * * *
|
||||
** Synopsis: affinity(r[P1])
|
||||
**
|
||||
@@ -6192,28 +6192,37 @@ case OP_Last: { /* jump, ncycle */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IfSmaller P1 P2 P3 * *
|
||||
/* Opcode: IfSizeBetween P1 P2 P3 P4 *
|
||||
**
|
||||
** Estimate the number of rows in the table P1. Jump to P2 if that
|
||||
** estimate is less than approximately 2**(0.1*P3).
|
||||
** Let N be the approximate number of rows in the table or index
|
||||
** with cursor P1 and let X be 10*log2(N) if N is positive or -1
|
||||
** if N is zero. Thus X will be within the range of -1 to 640, inclusive
|
||||
** Jump to P2 if X is in between P3 and P4, inclusive.
|
||||
*/
|
||||
case OP_IfSmaller: { /* jump */
|
||||
case OP_IfSizeBetween: { /* jump */
|
||||
VdbeCursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
int res;
|
||||
i64 sz;
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
assert( pOp->p3>=-1 && pOp->p3<=640 );
|
||||
assert( pOp->p4.i>=-1 && pOp->p4.i<=640 );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
pCrsr = pC->uc.pCursor;
|
||||
assert( pCrsr );
|
||||
rc = sqlite3BtreeFirst(pCrsr, &res);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
if( res==0 ){
|
||||
if( res!=0 ){
|
||||
sz = -1; /* -Infinity encoding */
|
||||
}else{
|
||||
sz = sqlite3BtreeRowCountEst(pCrsr);
|
||||
if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)<pOp->p3 ) res = 1;
|
||||
assert( sz>0 );
|
||||
sz = sqlite3LogEst((u64)sz);
|
||||
}
|
||||
res = sz>=pOp->p3 && sz<=pOp->p4.i;
|
||||
VdbeBranchTaken(res!=0,2);
|
||||
if( res ) goto jump_to_p2;
|
||||
break;
|
||||
@@ -6913,11 +6922,18 @@ case OP_CreateBtree: { /* out2 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SqlExec * * * P4 *
|
||||
/* Opcode: SqlExec P1 P2 * P4 *
|
||||
**
|
||||
** Run the SQL statement or statements specified in the P4 string.
|
||||
** Disable Auth and Trace callbacks while those statements are running if
|
||||
** P1 is true.
|
||||
**
|
||||
** The P1 parameter is a bitmask of options:
|
||||
**
|
||||
** 0x0001 Disable Auth and Trace callbacks while the statements
|
||||
** in P4 are running.
|
||||
**
|
||||
** 0x0002 Set db->nAnalysisLimit to P2 while the statements in
|
||||
** P4 are running.
|
||||
**
|
||||
*/
|
||||
case OP_SqlExec: {
|
||||
char *zErr;
|
||||
@@ -6925,6 +6941,7 @@ case OP_SqlExec: {
|
||||
sqlite3_xauth xAuth;
|
||||
#endif
|
||||
u8 mTrace;
|
||||
int savedAnalysisLimit;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
db->nSqlExec++;
|
||||
@@ -6933,18 +6950,23 @@ case OP_SqlExec: {
|
||||
xAuth = db->xAuth;
|
||||
#endif
|
||||
mTrace = db->mTrace;
|
||||
if( pOp->p1 ){
|
||||
savedAnalysisLimit = db->nAnalysisLimit;
|
||||
if( pOp->p1 & 0x0001 ){
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
db->xAuth = 0;
|
||||
#endif
|
||||
db->mTrace = 0;
|
||||
}
|
||||
if( pOp->p1 & 0x0002 ){
|
||||
db->nAnalysisLimit = pOp->p2;
|
||||
}
|
||||
rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr);
|
||||
db->nSqlExec--;
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
db->xAuth = xAuth;
|
||||
#endif
|
||||
db->mTrace = mTrace;
|
||||
db->nAnalysisLimit = savedAnalysisLimit;
|
||||
if( zErr || rc ){
|
||||
sqlite3VdbeError(p, "%s", zErr);
|
||||
sqlite3_free(zErr);
|
||||
|
Reference in New Issue
Block a user