Ejemplo n.º 1
0
        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));
        }