static RC LoadStat3(Context ctx, string dbName) { Debug.Assert(!ctx.Lookaside.Enabled); if (sqlite3FindTable(ctx, "sqlite_stat3", dbName) == null) { return(RC.OK); } string sql = SysEx.Mprintf(ctx, "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx", dbName); // Text of the SQL statement if (!sql) { return(RC_NOMEM); } Vdbe stmt = null; // An SQL statement being run RC rc = Vdbe.Prepare(ctx, sql, -1, stmt, 0); // Result codes from subroutines C._tagfree(ctx, sql); if (rc) { return(rc); } while (stmt.Step() == RC.ROW) { string indexName = (string)Vdbe.Column_Text(stmt, 0); // Index name if (!indexName) { continue; } int samplesLength = Vdbe.Column_Int(stmt, 1); // Number of samples Index idx = sqlite3FindIndex(ctx, indexName, dbName); // Pointer to the index object if (!idx) { continue; } _assert(idx->Samples.length == 0); idx.Samples.length = samplesLength; idx.Samples.data = new IndexSample[samplesLength]; idx.AvgEq = idx.RowEsts[1]; if (!idx->Samples.data) { ctx->MallocFailed = true; Vdbe.Finalize(stmt); return(RC.NOMEM); } } rc = Vdbe.Finalize(stmt); if (rc) { return(rc); } sql = C._mtagprintf(ctx, "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", dbName); if (!sql) { return(RC.NOMEM); } rc = Vdbe.Prepare(ctx, sql, -1, &stmt, 0); C._tagfree(ctx, sql); if (rc) { return(rc); } Index prevIdx = null; // Previous index in the loop int idxId = 0; // slot in pIdx->aSample[] for next sample while (stmt.Step() == RC.ROW) { string indexName = (string)Vdbe.Column_Text(stmt, 0); // Index name if (indexName == null) { continue; } Index idx = sqlite3FindIndex(ctx, indexName, dbName); // Pointer to the index object if (idx == null) { continue; } if (idx == prevIdx) { idxId++; } else { prevIdx = idx; idxId = 0; } Debug.Assert(idxId < idx.Samples.length); IndexSample sample = idx.Samples[idxId]; // A slot in pIdx->aSample[] sample.Eq = (tRowcnt)Vdbe.Column_Int64(stmt, 1); sample.Lt = (tRowcnt)Vdbe.Column_Int64(stmt, 2); sample.DLt = (tRowcnt)Vdbe.Column_Int64(stmt, 3); if (idxId == idx.Samples.length - 1) { tRowcnt sumEq; // Sum of the nEq values if (sample.DLt > 0) { for (int i = 0, sumEq = 0; i <= idxId - 1; i++) { sumEq += idx.Samples[i].Eq; } idx.AvgEq = (sample.Lt - sumEq) / sample.DLt; } if (idx.AvgEq <= 0) { idx.AvgEq = 1; } } TYPE type = Vdbe.Column_Type(stmt, 4); // Datatype of a sample sample.Type = type; switch (type) { case TYPE.INTEGER: { sample.u.I = Vdbe.Column_Int64(stmt, 4); break; } case TYPE.FLOAT: { sample.u.R = Vdbe.Column_Double(stmt, 4); break; } case TYPE.NULL: { break; } default: Debug.Assert(type == TYPE.TEXT || type == TYPE.BLOB); { string z = (string)(type == TYPE_BLOB ? Vdbe.Column_Blob(stmt, 4) : Vdbe.Column_Text(stmt, 4)); int n = (z ? Vdbe.Column_Bytes(stmt, 4) : 0); sample.Bytes = n; if (n < 1) { sample.u.Z = null; } else { sample.u.Z = C._tagalloc(ctx, n); if (sample->u.Z == null) { ctx.MallocFailed = true; Vdbe.Finalize(stmt); return(RC.NOMEM); } Buffer.BlockCopy(sample.u.Z, z, n); } } } } return(Vdbe.Finalize(stmt)); }