| Index: third_party/sqlite/src/src/analyze.c
|
| diff --git a/third_party/sqlite/src/src/analyze.c b/third_party/sqlite/src/src/analyze.c
|
| index 06918eb7442ef3ddbc9e915bde02ff160c7927f6..890ae7c3b2da8d331963fb1e286d99f65c09695f 100644
|
| --- a/third_party/sqlite/src/src/analyze.c
|
| +++ b/third_party/sqlite/src/src/analyze.c
|
| @@ -210,14 +210,14 @@ static void openStatTable(
|
| for(i=0; i<ArraySize(aTable); i++){
|
| const char *zTab = aTable[i].zName;
|
| Table *pStat;
|
| - if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
|
| + if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
|
| if( aTable[i].zCols ){
|
| /* The sqlite_statN table does not exist. Create it. Note that a
|
| ** side-effect of the CREATE TABLE statement is to leave the rootpage
|
| ** of the new table in register pParse->regRoot. This is important
|
| ** because the OpenWrite opcode below will be needing it. */
|
| sqlite3NestedParse(pParse,
|
| - "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
|
| + "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
|
| );
|
| aRoot[i] = pParse->regRoot;
|
| aCreateTbl[i] = OPFLAG_P2ISREG;
|
| @@ -232,7 +232,7 @@ static void openStatTable(
|
| if( zWhere ){
|
| sqlite3NestedParse(pParse,
|
| "DELETE FROM %Q.%s WHERE %s=%Q",
|
| - pDb->zName, zTab, zWhereType, zWhere
|
| + pDb->zDbSName, zTab, zWhereType, zWhere
|
| );
|
| }else{
|
| /* The sqlite_stat[134] table already exists. Delete all rows. */
|
| @@ -313,7 +313,7 @@ static void sampleClear(sqlite3 *db, Stat4Sample *p){
|
| static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
|
| assert( db!=0 );
|
| if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
|
| - p->u.aRowid = sqlite3DbMallocRaw(db, n);
|
| + p->u.aRowid = sqlite3DbMallocRawNN(db, n);
|
| if( p->u.aRowid ){
|
| p->nRowid = n;
|
| memcpy(p->u.aRowid, pData, n);
|
| @@ -478,12 +478,10 @@ static const FuncDef statInitFuncdef = {
|
| SQLITE_UTF8, /* funcFlags */
|
| 0, /* pUserData */
|
| 0, /* pNext */
|
| - statInit, /* xFunc */
|
| - 0, /* xStep */
|
| + statInit, /* xSFunc */
|
| 0, /* xFinalize */
|
| "stat_init", /* zName */
|
| - 0, /* pHash */
|
| - 0 /* pDestructor */
|
| + {0}
|
| };
|
|
|
| #ifdef SQLITE_ENABLE_STAT4
|
| @@ -779,12 +777,10 @@ static const FuncDef statPushFuncdef = {
|
| SQLITE_UTF8, /* funcFlags */
|
| 0, /* pUserData */
|
| 0, /* pNext */
|
| - statPush, /* xFunc */
|
| - 0, /* xStep */
|
| + statPush, /* xSFunc */
|
| 0, /* xFinalize */
|
| "stat_push", /* zName */
|
| - 0, /* pHash */
|
| - 0 /* pDestructor */
|
| + {0}
|
| };
|
|
|
| #define STAT_GET_STAT1 0 /* "stat" column of stat1 table */
|
| @@ -801,6 +797,12 @@ static const FuncDef statPushFuncdef = {
|
| ** The content to returned is determined by the parameter J
|
| ** which is one of the STAT_GET_xxxx values defined above.
|
| **
|
| +** The stat_get(P,J) function is not available to generic SQL. It is
|
| +** inserted as part of a manually constructed bytecode program. (See
|
| +** the callStatGet() routine below.) It is guaranteed that the P
|
| +** parameter will always be a poiner to a Stat4Accum object, never a
|
| +** NULL.
|
| +**
|
| ** If neither STAT3 nor STAT4 are enabled, then J is always
|
| ** STAT_GET_STAT1 and is hence omitted and this routine becomes
|
| ** a one-parameter function, stat_get(P), that always returns the
|
| @@ -926,12 +928,10 @@ static const FuncDef statGetFuncdef = {
|
| SQLITE_UTF8, /* funcFlags */
|
| 0, /* pUserData */
|
| 0, /* pNext */
|
| - statGet, /* xFunc */
|
| - 0, /* xStep */
|
| + statGet, /* xSFunc */
|
| 0, /* xFinalize */
|
| "stat_get", /* zName */
|
| - 0, /* pHash */
|
| - 0 /* pDestructor */
|
| + {0}
|
| };
|
|
|
| static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
|
| @@ -943,8 +943,8 @@ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
|
| #else
|
| UNUSED_PARAMETER( iParam );
|
| #endif
|
| - sqlite3VdbeAddOp3(v, OP_Function0, 0, regStat4, regOut);
|
| - sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
|
| + sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut,
|
| + (char*)&statGetFuncdef, P4_FUNCDEF);
|
| sqlite3VdbeChangeP5(v, 1 + IsStat34);
|
| }
|
|
|
| @@ -1000,7 +1000,7 @@ static void analyzeOneTable(
|
| assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
| #ifndef SQLITE_OMIT_AUTHORIZATION
|
| if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
|
| - db->aDb[iDb].zName ) ){
|
| + db->aDb[iDb].zDbSName ) ){
|
| return;
|
| }
|
| #endif
|
| @@ -1098,8 +1098,8 @@ static void analyzeOneTable(
|
| #endif
|
| sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
|
| sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
|
| - sqlite3VdbeAddOp3(v, OP_Function0, 0, regStat4+1, regStat4);
|
| - sqlite3VdbeChangeP4(v, -1, (char*)&statInitFuncdef, P4_FUNCDEF);
|
| + sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4,
|
| + (char*)&statInitFuncdef, P4_FUNCDEF);
|
| sqlite3VdbeChangeP5(v, 2+IsStat34);
|
|
|
| /* Implementation of the following:
|
| @@ -1118,7 +1118,7 @@ static void analyzeOneTable(
|
| if( nColTest>0 ){
|
| int endDistinctTest = sqlite3VdbeMakeLabel(v);
|
| int *aGotoChng; /* Array of jump instruction addresses */
|
| - aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest);
|
| + aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest);
|
| if( aGotoChng==0 ) continue;
|
|
|
| /*
|
| @@ -1195,8 +1195,8 @@ static void analyzeOneTable(
|
| }
|
| #endif
|
| assert( regChng==(regStat4+1) );
|
| - sqlite3VdbeAddOp3(v, OP_Function0, 1, regStat4, regTemp);
|
| - sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF);
|
| + sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp,
|
| + (char*)&statPushFuncdef, P4_FUNCDEF);
|
| sqlite3VdbeChangeP5(v, 2+IsStat34);
|
| sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
|
|
|
| @@ -1390,7 +1390,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
|
| /* Form 3: Analyze the fully qualified table name */
|
| iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
|
| if( iDb>=0 ){
|
| - zDb = db->aDb[iDb].zName;
|
| + zDb = db->aDb[iDb].zDbSName;
|
| z = sqlite3NameFromToken(db, pTableName);
|
| if( z ){
|
| if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
|
| @@ -1526,7 +1526,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
| ** the old data with the new instead of allocating a new array. */
|
| if( pIndex->aiRowEst==0 ){
|
| pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol);
|
| - if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1;
|
| + if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db);
|
| }
|
| aiRowEst = pIndex->aiRowEst;
|
| #endif
|
| @@ -1621,7 +1621,7 @@ static void initAvgEq(Index *pIdx){
|
| }
|
| }
|
|
|
| - if( nDist100>nSum100 ){
|
| + if( nDist100>nSum100 && sumEq<nRow ){
|
| avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100);
|
| }
|
| if( avgEq==0 ) avgEq = 1;
|
| @@ -1673,10 +1673,10 @@ static int loadStatTbl(
|
| Index *pPrevIdx = 0; /* Previous index in the loop */
|
| IndexSample *pSample; /* A slot in pIdx->aSample[] */
|
|
|
| - assert( db->lookaside.bEnabled==0 );
|
| + assert( db->lookaside.bDisable );
|
| zSql = sqlite3MPrintf(db, zSql1, zDb);
|
| if( !zSql ){
|
| - return SQLITE_NOMEM;
|
| + return SQLITE_NOMEM_BKPT;
|
| }
|
| rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
|
| sqlite3DbFree(db, zSql);
|
| @@ -1716,7 +1716,7 @@ static int loadStatTbl(
|
| pIdx->aSample = sqlite3DbMallocZero(db, nByte);
|
| if( pIdx->aSample==0 ){
|
| sqlite3_finalize(pStmt);
|
| - return SQLITE_NOMEM;
|
| + return SQLITE_NOMEM_BKPT;
|
| }
|
| pSpace = (tRowcnt*)&pIdx->aSample[nSample];
|
| pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
|
| @@ -1732,7 +1732,7 @@ static int loadStatTbl(
|
|
|
| zSql = sqlite3MPrintf(db, zSql2, zDb);
|
| if( !zSql ){
|
| - return SQLITE_NOMEM;
|
| + return SQLITE_NOMEM_BKPT;
|
| }
|
| rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
|
| sqlite3DbFree(db, zSql);
|
| @@ -1770,9 +1770,11 @@ static int loadStatTbl(
|
| pSample->p = sqlite3DbMallocZero(db, pSample->n + 2);
|
| if( pSample->p==0 ){
|
| sqlite3_finalize(pStmt);
|
| - return SQLITE_NOMEM;
|
| + return SQLITE_NOMEM_BKPT;
|
| + }
|
| + if( pSample->n ){
|
| + memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
|
| }
|
| - memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
|
| pIdx->nSample++;
|
| }
|
| rc = sqlite3_finalize(pStmt);
|
| @@ -1787,7 +1789,7 @@ static int loadStatTbl(
|
| static int loadStat4(sqlite3 *db, const char *zDb){
|
| int rc = SQLITE_OK; /* Result codes from subroutines */
|
|
|
| - assert( db->lookaside.bEnabled==0 );
|
| + assert( db->lookaside.bDisable );
|
| if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
|
| rc = loadStatTbl(db, 0,
|
| "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx",
|
| @@ -1832,7 +1834,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
| analysisInfo sInfo;
|
| HashElem *i;
|
| char *zSql;
|
| - int rc;
|
| + int rc = SQLITE_OK;
|
|
|
| assert( iDb>=0 && iDb<db->nDb );
|
| assert( db->aDb[iDb].pBt!=0 );
|
| @@ -1841,38 +1843,40 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
| assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
| for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
| Index *pIdx = sqliteHashData(i);
|
| - sqlite3DefaultRowEst(pIdx);
|
| + pIdx->aiRowLogEst[0] = 0;
|
| #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
| sqlite3DeleteIndexSamples(db, pIdx);
|
| pIdx->aSample = 0;
|
| #endif
|
| }
|
|
|
| - /* Check to make sure the sqlite_stat1 table exists */
|
| + /* Load new statistics out of the sqlite_stat1 table */
|
| sInfo.db = db;
|
| - sInfo.zDatabase = db->aDb[iDb].zName;
|
| - if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
|
| - return SQLITE_ERROR;
|
| + sInfo.zDatabase = db->aDb[iDb].zDbSName;
|
| + if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){
|
| + zSql = sqlite3MPrintf(db,
|
| + "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
|
| + if( zSql==0 ){
|
| + rc = SQLITE_NOMEM_BKPT;
|
| + }else{
|
| + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
|
| + sqlite3DbFree(db, zSql);
|
| + }
|
| }
|
|
|
| - /* Load new statistics out of the sqlite_stat1 table */
|
| - zSql = sqlite3MPrintf(db,
|
| - "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
|
| - if( zSql==0 ){
|
| - rc = SQLITE_NOMEM;
|
| - }else{
|
| - rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
|
| - sqlite3DbFree(db, zSql);
|
| + /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */
|
| + assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
| + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
| + Index *pIdx = sqliteHashData(i);
|
| + if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx);
|
| }
|
|
|
| -
|
| /* Load the statistics from the sqlite_stat4 table. */
|
| #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
| if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){
|
| - int lookasideEnabled = db->lookaside.bEnabled;
|
| - db->lookaside.bEnabled = 0;
|
| + db->lookaside.bDisable++;
|
| rc = loadStat4(db, sInfo.zDatabase);
|
| - db->lookaside.bEnabled = lookasideEnabled;
|
| + db->lookaside.bDisable--;
|
| }
|
| for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
| Index *pIdx = sqliteHashData(i);
|
| @@ -1882,7 +1886,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
| #endif
|
|
|
| if( rc==SQLITE_NOMEM ){
|
| - db->mallocFailed = 1;
|
| + sqlite3OomFault(db);
|
| }
|
| return rc;
|
| }
|
|
|