1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ci#include "table_base.h"
17fb726d48Sopenharmony_ci
18fb726d48Sopenharmony_ci#include <cctype>
19fb726d48Sopenharmony_ci#include <cmath>
20fb726d48Sopenharmony_ci#include <cstring>
21fb726d48Sopenharmony_ci
22fb726d48Sopenharmony_cinamespace SysTuning {
23fb726d48Sopenharmony_cinamespace TraceStreamer {
24fb726d48Sopenharmony_cinamespace {
25fb726d48Sopenharmony_cistruct TableContext {
26fb726d48Sopenharmony_ci    TabTemplate tmplate;
27fb726d48Sopenharmony_ci    TraceDataCache *dataCache;
28fb726d48Sopenharmony_ci    sqlite3_module module;
29fb726d48Sopenharmony_ci    std::string tableName;
30fb726d48Sopenharmony_ci};
31fb726d48Sopenharmony_ci} // namespace
32fb726d48Sopenharmony_ci
33fb726d48Sopenharmony_ciTableBase::~TableBase()
34fb726d48Sopenharmony_ci{
35fb726d48Sopenharmony_ci    dataCache_ = nullptr;
36fb726d48Sopenharmony_ci    cursor_ = nullptr;
37fb726d48Sopenharmony_ci}
38fb726d48Sopenharmony_ci
39fb726d48Sopenharmony_civoid TableBase::TableRegister(sqlite3 &db, TraceDataCache *cache, const std::string &tableName, TabTemplate tmplate)
40fb726d48Sopenharmony_ci{
41fb726d48Sopenharmony_ci    std::unique_ptr<TableContext> context(std::make_unique<TableContext>());
42fb726d48Sopenharmony_ci    context->dataCache = cache;
43fb726d48Sopenharmony_ci    context->tmplate = tmplate;
44fb726d48Sopenharmony_ci    context->tableName = tableName;
45fb726d48Sopenharmony_ci    sqlite3_module &module = context->module;
46fb726d48Sopenharmony_ci    module = {0};
47fb726d48Sopenharmony_ci
48fb726d48Sopenharmony_ci    auto createFn = [](sqlite3 *xdb, void *pAux, int32_t argc, const char *const *argv, sqlite3_vtab **ppVTab,
49fb726d48Sopenharmony_ci                       char **pzErr) {
50fb726d48Sopenharmony_ci        Unused(argc);
51fb726d48Sopenharmony_ci        Unused(argv);
52fb726d48Sopenharmony_ci        Unused(pzErr);
53fb726d48Sopenharmony_ci        auto xdesc = static_cast<const TableContext *>(pAux);
54fb726d48Sopenharmony_ci        auto table = xdesc->tmplate(xdesc->dataCache);
55fb726d48Sopenharmony_ci        table->name_ = xdesc->tableName;
56fb726d48Sopenharmony_ci        if (table->name_ == "process" || table->name_ == "thread") {
57fb726d48Sopenharmony_ci            table->wdataCache_ = xdesc->dataCache;
58fb726d48Sopenharmony_ci        }
59fb726d48Sopenharmony_ci
60fb726d48Sopenharmony_ci        table->Init(argc, argv);
61fb726d48Sopenharmony_ci        std::string createStmt = table->CreateTableSql();
62fb726d48Sopenharmony_ci        TS_LOGD("xCreate table %s, statement: %s", table->name_.c_str(), createStmt.c_str());
63fb726d48Sopenharmony_ci        int32_t ret = sqlite3_declare_vtab(xdb, createStmt.c_str());
64fb726d48Sopenharmony_ci        if (ret != SQLITE_OK) {
65fb726d48Sopenharmony_ci            if ((table->name_ == "span_join") || (table->name_ == "_span_join")) {
66fb726d48Sopenharmony_ci                return ret;
67fb726d48Sopenharmony_ci            }
68fb726d48Sopenharmony_ci            TS_LOGE("sqlite3_declare_vtab %s faild: %s", table->name_.c_str(), createStmt.c_str());
69fb726d48Sopenharmony_ci            return ret;
70fb726d48Sopenharmony_ci        }
71fb726d48Sopenharmony_ci        *ppVTab = table.release();
72fb726d48Sopenharmony_ci        return SQLITE_OK;
73fb726d48Sopenharmony_ci    };
74fb726d48Sopenharmony_ci
75fb726d48Sopenharmony_ci    auto destroyFn = [](sqlite3_vtab *t) {
76fb726d48Sopenharmony_ci        TS_LOGD("xDestroy table %s", static_cast<TableBase *>(t)->name_.c_str());
77fb726d48Sopenharmony_ci        delete static_cast<TableBase *>(t);
78fb726d48Sopenharmony_ci        return SQLITE_OK;
79fb726d48Sopenharmony_ci    };
80fb726d48Sopenharmony_ci    module.xCreate = createFn;
81fb726d48Sopenharmony_ci    module.xConnect = createFn;
82fb726d48Sopenharmony_ci    module.xDisconnect = destroyFn;
83fb726d48Sopenharmony_ci    module.xDestroy = destroyFn;
84fb726d48Sopenharmony_ci
85fb726d48Sopenharmony_ci    SetModuleCallbacks(module, tableName);
86fb726d48Sopenharmony_ci    sqlite3_create_module_v2(&db, tableName.c_str(), &module, context.release(),
87fb726d48Sopenharmony_ci                             [](void *arg) { delete static_cast<TableContext *>(arg); });
88fb726d48Sopenharmony_ci}
89fb726d48Sopenharmony_ci
90fb726d48Sopenharmony_civoid TableBase::SetModuleCallbacks(sqlite3_module &module, const std::string &tableName)
91fb726d48Sopenharmony_ci{
92fb726d48Sopenharmony_ci    module.xOpen = [](sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
93fb726d48Sopenharmony_ci        TS_LOGD("xOpen: %s", static_cast<TableBase *>(pVTab)->name_.c_str());
94fb726d48Sopenharmony_ci        return static_cast<TableBase *>(pVTab)->Open(ppCursor);
95fb726d48Sopenharmony_ci    };
96fb726d48Sopenharmony_ci
97fb726d48Sopenharmony_ci    module.xClose = [](sqlite3_vtab_cursor *vc) {
98fb726d48Sopenharmony_ci        TS_LOGD("xClose: %s", static_cast<Cursor *>(vc)->table_->name_.c_str());
99fb726d48Sopenharmony_ci        delete static_cast<Cursor *>(vc);
100fb726d48Sopenharmony_ci        return SQLITE_OK;
101fb726d48Sopenharmony_ci    };
102fb726d48Sopenharmony_ci    module.xBestIndex = [](sqlite3_vtab *pVTab, sqlite3_index_info *idxInfo) {
103fb726d48Sopenharmony_ci        TS_LOGD("xBestIndex: %s %d", static_cast<TableBase *>(pVTab)->name_.c_str(), idxInfo->nConstraint);
104fb726d48Sopenharmony_ci        return static_cast<TableBase *>(pVTab)->BestIndex(idxInfo);
105fb726d48Sopenharmony_ci    };
106fb726d48Sopenharmony_ci
107fb726d48Sopenharmony_ci    module.xFilter = [](sqlite3_vtab_cursor *vc, int32_t idxNum, const char *idxStr, int32_t argc,
108fb726d48Sopenharmony_ci                        sqlite3_value **argv) {
109fb726d48Sopenharmony_ci        auto *c = static_cast<Cursor *>(vc);
110fb726d48Sopenharmony_ci        c->Reset();
111fb726d48Sopenharmony_ci        TS_LOGD("xFilter %s: [%d]%s", static_cast<Cursor *>(vc)->table_->name_.c_str(), idxNum, idxStr);
112fb726d48Sopenharmony_ci        if (c->table_->cacheIdxNum_ != idxNum) {
113fb726d48Sopenharmony_ci            c->table_->cacheConstraint_.Clear();
114fb726d48Sopenharmony_ci            c->table_->cacheConstraint_.FromString(idxStr);
115fb726d48Sopenharmony_ci            c->table_->cacheIdxNum_ = idxNum;
116fb726d48Sopenharmony_ci        }
117fb726d48Sopenharmony_ci        return c->Filter(c->table_->cacheConstraint_, argv);
118fb726d48Sopenharmony_ci    };
119fb726d48Sopenharmony_ci    module.xNext = [](sqlite3_vtab_cursor *vc) { return static_cast<TableBase::Cursor *>(vc)->Next(); };
120fb726d48Sopenharmony_ci    module.xEof = [](sqlite3_vtab_cursor *vc) { return static_cast<TableBase::Cursor *>(vc)->Eof(); };
121fb726d48Sopenharmony_ci    module.xColumn = [](sqlite3_vtab_cursor *vc, sqlite3_context *ctx, int32_t col) {
122fb726d48Sopenharmony_ci        static_cast<TableBase::Cursor *>(vc)->context_ = ctx;
123fb726d48Sopenharmony_ci        return static_cast<TableBase::Cursor *>(vc)->Column(col);
124fb726d48Sopenharmony_ci    };
125fb726d48Sopenharmony_ci    if (tableName == "process" || tableName == "thread") {
126fb726d48Sopenharmony_ci        module.xUpdate = [](sqlite3_vtab *pVTab, int32_t argc, sqlite3_value **argv, sqlite3_int64 *pRowid) {
127fb726d48Sopenharmony_ci            TS_LOGD("xUpdate: %s", static_cast<TableBase *>(pVTab)->name_.c_str());
128fb726d48Sopenharmony_ci            return static_cast<TableBase *>(pVTab)->Update(argc, argv, pRowid);
129fb726d48Sopenharmony_ci        };
130fb726d48Sopenharmony_ci    }
131fb726d48Sopenharmony_ci}
132fb726d48Sopenharmony_ci
133fb726d48Sopenharmony_cistd::string TableBase::CreateTableSql() const
134fb726d48Sopenharmony_ci{
135fb726d48Sopenharmony_ci    std::string stmt = "CREATE TABLE x(";
136fb726d48Sopenharmony_ci    for (const auto &col : tableColumn_) {
137fb726d48Sopenharmony_ci        stmt += " " + col.name_ + " " + col.type_;
138fb726d48Sopenharmony_ci        stmt += ",";
139fb726d48Sopenharmony_ci    }
140fb726d48Sopenharmony_ci    stmt += " PRIMARY KEY(";
141fb726d48Sopenharmony_ci    for (size_t i = 0; i < tablePriKey_.size(); i++) {
142fb726d48Sopenharmony_ci        if (i != 0)
143fb726d48Sopenharmony_ci            stmt += ", ";
144fb726d48Sopenharmony_ci        stmt += tablePriKey_.at(i);
145fb726d48Sopenharmony_ci    }
146fb726d48Sopenharmony_ci    stmt += ")) WITHOUT ROWID;";
147fb726d48Sopenharmony_ci    return stmt;
148fb726d48Sopenharmony_ci}
149fb726d48Sopenharmony_ciint32_t TableBase::Cursor::Next()
150fb726d48Sopenharmony_ci{
151fb726d48Sopenharmony_ci    indexMap_->Next();
152fb726d48Sopenharmony_ci    return SQLITE_OK;
153fb726d48Sopenharmony_ci}
154fb726d48Sopenharmony_ci
155fb726d48Sopenharmony_ciint32_t TableBase::Cursor::Eof()
156fb726d48Sopenharmony_ci{
157fb726d48Sopenharmony_ci    return dataCache_->Cancel() || indexMap_->Eof();
158fb726d48Sopenharmony_ci}
159fb726d48Sopenharmony_ciuint32_t TableBase::Cursor::CurrentRow() const
160fb726d48Sopenharmony_ci{
161fb726d48Sopenharmony_ci    return indexMap_->CurrentRow();
162fb726d48Sopenharmony_ci}
163fb726d48Sopenharmony_civoid TableBase::Cursor::FilterEnd()
164fb726d48Sopenharmony_ci{
165fb726d48Sopenharmony_ci    indexMap_->Sort();
166fb726d48Sopenharmony_ci}
167fb726d48Sopenharmony_ciint32_t TableBase::BestIndex(sqlite3_index_info *idxInfo)
168fb726d48Sopenharmony_ci{
169fb726d48Sopenharmony_ci    FilterConstraints filterConstraints;
170fb726d48Sopenharmony_ci    for (int32_t i = 0; i < idxInfo->nConstraint; i++) {
171fb726d48Sopenharmony_ci        const auto &constraint = idxInfo->aConstraint[i];
172fb726d48Sopenharmony_ci        if (constraint.usable) {
173fb726d48Sopenharmony_ci            filterConstraints.AddConstraint(i, constraint.iColumn, constraint.op);
174fb726d48Sopenharmony_ci        }
175fb726d48Sopenharmony_ci    }
176fb726d48Sopenharmony_ci    for (int32_t i = 0; i < idxInfo->nOrderBy; i++) {
177fb726d48Sopenharmony_ci        filterConstraints.AddOrderBy(idxInfo->aOrderBy[i].iColumn, idxInfo->aOrderBy[i].desc);
178fb726d48Sopenharmony_ci    }
179fb726d48Sopenharmony_ci
180fb726d48Sopenharmony_ci    EstimatedIndexInfo estimate = {idxInfo->estimatedRows, idxInfo->estimatedCost, false};
181fb726d48Sopenharmony_ci    EstimateFilterCost(filterConstraints, estimate);
182fb726d48Sopenharmony_ci    idxInfo->orderByConsumed = estimate.isOrdered;
183fb726d48Sopenharmony_ci    idxInfo->estimatedCost = estimate.estimatedCost;
184fb726d48Sopenharmony_ci    idxInfo->estimatedRows = estimate.estimatedRows;
185fb726d48Sopenharmony_ci
186fb726d48Sopenharmony_ci    auto cs = filterConstraints.GetConstraints();
187fb726d48Sopenharmony_ci    for (size_t i = 0; i < cs.size(); i++) {
188fb726d48Sopenharmony_ci        auto &c = cs[i];
189fb726d48Sopenharmony_ci        idxInfo->aConstraintUsage[c.idxInaConstraint].argvIndex = static_cast<int32_t>(i + 1);
190fb726d48Sopenharmony_ci        idxInfo->aConstraintUsage[c.idxInaConstraint].omit = c.isSupport;
191fb726d48Sopenharmony_ci    }
192fb726d48Sopenharmony_ci
193fb726d48Sopenharmony_ci    std::string str;
194fb726d48Sopenharmony_ci    filterConstraints.ToString(str);
195fb726d48Sopenharmony_ci    char *pIdxStr = static_cast<char *>(sqlite3_malloc(str.size() + 1));
196fb726d48Sopenharmony_ci    std::copy(str.begin(), str.end(), pIdxStr);
197fb726d48Sopenharmony_ci    pIdxStr[str.size()] = '\0';
198fb726d48Sopenharmony_ci    idxInfo->idxStr = pIdxStr;
199fb726d48Sopenharmony_ci    idxInfo->needToFreeIdxStr = true;
200fb726d48Sopenharmony_ci    idxInfo->idxNum = ++bestIndexNum_;
201fb726d48Sopenharmony_ci
202fb726d48Sopenharmony_ci    TS_LOGD("%s BestIndex return: %d: %s", name_.c_str(), idxInfo->idxNum, str.c_str());
203fb726d48Sopenharmony_ci    TS_LOGD("%s, aConstraintUsage[%d]", idxInfo->idxStr, idxInfo->nConstraint);
204fb726d48Sopenharmony_ci    for (int32_t i = 0; i < idxInfo->nConstraint; i++) {
205fb726d48Sopenharmony_ci        TS_LOGD("col: %d op: %d, argvindex: %d omit: %d", idxInfo->aConstraint[i].iColumn, idxInfo->aConstraint[i].op,
206fb726d48Sopenharmony_ci                idxInfo->aConstraintUsage[i].argvIndex, idxInfo->aConstraintUsage[i].omit);
207fb726d48Sopenharmony_ci    }
208fb726d48Sopenharmony_ci    TS_LOGD("estimated: %lld cost:%.3f", idxInfo->estimatedRows, idxInfo->estimatedCost);
209fb726d48Sopenharmony_ci
210fb726d48Sopenharmony_ci    return SQLITE_OK;
211fb726d48Sopenharmony_ci}
212fb726d48Sopenharmony_ci
213fb726d48Sopenharmony_ciint32_t TableBase::Open(sqlite3_vtab_cursor **ppCursor)
214fb726d48Sopenharmony_ci{
215fb726d48Sopenharmony_ci    *ppCursor = static_cast<sqlite3_vtab_cursor *>(CreateCursor().release());
216fb726d48Sopenharmony_ci    return SQLITE_OK;
217fb726d48Sopenharmony_ci}
218fb726d48Sopenharmony_ci
219fb726d48Sopenharmony_ciTableBase::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table, uint32_t rowCount)
220fb726d48Sopenharmony_ci    : context_(nullptr),
221fb726d48Sopenharmony_ci      table_(table),
222fb726d48Sopenharmony_ci      dataCache_(dataCache),
223fb726d48Sopenharmony_ci      indexMap_(std::make_unique<IndexMap>(0, rowCount)),
224fb726d48Sopenharmony_ci      rowCount_(rowCount)
225fb726d48Sopenharmony_ci{
226fb726d48Sopenharmony_ci}
227fb726d48Sopenharmony_ci
228fb726d48Sopenharmony_cibool TableBase::CanFilterId(const char op, size_t &rowCount)
229fb726d48Sopenharmony_ci{
230fb726d48Sopenharmony_ci    switch (op) {
231fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_EQ:
232fb726d48Sopenharmony_ci            rowCount = 1;
233fb726d48Sopenharmony_ci            break;
234fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_GT:
235fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_GE:
236fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_LE:
237fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_LT:
238fb726d48Sopenharmony_ci            // assume filter out a half of rows
239fb726d48Sopenharmony_ci            rowCount = (rowCount >> 1);
240fb726d48Sopenharmony_ci            break;
241fb726d48Sopenharmony_ci        default:
242fb726d48Sopenharmony_ci            return false;
243fb726d48Sopenharmony_ci    }
244fb726d48Sopenharmony_ci    return true;
245fb726d48Sopenharmony_ci}
246fb726d48Sopenharmony_ci
247fb726d48Sopenharmony_cibool TableBase::CanFilterSorted(const char op, size_t &rowCount)
248fb726d48Sopenharmony_ci{
249fb726d48Sopenharmony_ci    switch (op) {
250fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_EQ:
251fb726d48Sopenharmony_ci            rowCount = log2(rowCount);
252fb726d48Sopenharmony_ci            break;
253fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_GT:
254fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_GE:
255fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_LE:
256fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_LT:
257fb726d48Sopenharmony_ci            rowCount = (rowCount >> 1);
258fb726d48Sopenharmony_ci            break;
259fb726d48Sopenharmony_ci        default:
260fb726d48Sopenharmony_ci            return false;
261fb726d48Sopenharmony_ci    }
262fb726d48Sopenharmony_ci    return true;
263fb726d48Sopenharmony_ci}
264fb726d48Sopenharmony_ci
265fb726d48Sopenharmony_ciTableBase::Cursor::~Cursor()
266fb726d48Sopenharmony_ci{
267fb726d48Sopenharmony_ci    context_ = nullptr;
268fb726d48Sopenharmony_ci    dataCache_ = nullptr;
269fb726d48Sopenharmony_ci}
270fb726d48Sopenharmony_civoid TableBase::Cursor::FilterTS(unsigned char op, sqlite3_value *argv, const std::deque<InternalTime> &times)
271fb726d48Sopenharmony_ci{
272fb726d48Sopenharmony_ci    auto v = static_cast<uint64_t>(sqlite3_value_int64(argv));
273fb726d48Sopenharmony_ci    auto getValue = [](const uint64_t &row) { return row; };
274fb726d48Sopenharmony_ci    switch (op) {
275fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_EQ:
276fb726d48Sopenharmony_ci            indexMap_->IntersectabcEqual(times, v, getValue);
277fb726d48Sopenharmony_ci            break;
278fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_GT:
279fb726d48Sopenharmony_ci            v++;
280fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_GE: {
281fb726d48Sopenharmony_ci            indexMap_->IntersectGreaterEqual(times, v, getValue);
282fb726d48Sopenharmony_ci            break;
283fb726d48Sopenharmony_ci        }
284fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_LE:
285fb726d48Sopenharmony_ci            v++;
286fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_LT: {
287fb726d48Sopenharmony_ci            indexMap_->IntersectLessEqual(times, v, getValue);
288fb726d48Sopenharmony_ci            break;
289fb726d48Sopenharmony_ci        }
290fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: {
291fb726d48Sopenharmony_ci            indexMap_->RemoveNullElements(times, v);
292fb726d48Sopenharmony_ci            break;
293fb726d48Sopenharmony_ci        }
294fb726d48Sopenharmony_ci        default:
295fb726d48Sopenharmony_ci            break;
296fb726d48Sopenharmony_ci    } // end of switch (op)
297fb726d48Sopenharmony_ci}
298fb726d48Sopenharmony_ci
299fb726d48Sopenharmony_ciint32_t TableBase::Cursor::RowId(sqlite3_int64 *id)
300fb726d48Sopenharmony_ci{
301fb726d48Sopenharmony_ci    if (dataCache_->Cancel() || indexMap_->Eof()) {
302fb726d48Sopenharmony_ci        return SQLITE_ERROR;
303fb726d48Sopenharmony_ci    }
304fb726d48Sopenharmony_ci    *id = static_cast<sqlite3_int64>(indexMap_->CurrentRow());
305fb726d48Sopenharmony_ci    return SQLITE_OK;
306fb726d48Sopenharmony_ci}
307fb726d48Sopenharmony_civoid TableBase::Cursor::FilterId(unsigned char op, sqlite3_value *argv)
308fb726d48Sopenharmony_ci{
309fb726d48Sopenharmony_ci    auto type = sqlite3_value_type(argv);
310fb726d48Sopenharmony_ci    if (type != SQLITE_INTEGER) {
311fb726d48Sopenharmony_ci        // other type consider it NULL
312fb726d48Sopenharmony_ci        indexMap_->Intersect(0, 0);
313fb726d48Sopenharmony_ci        return;
314fb726d48Sopenharmony_ci    }
315fb726d48Sopenharmony_ci    if (indexMap_->HasData()) {
316fb726d48Sopenharmony_ci        indexMap_->ConvertToIndexMap();
317fb726d48Sopenharmony_ci    }
318fb726d48Sopenharmony_ci
319fb726d48Sopenharmony_ci    auto v = static_cast<TableRowId>(sqlite3_value_int64(argv));
320fb726d48Sopenharmony_ci    switch (op) {
321fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_EQ:
322fb726d48Sopenharmony_ci            indexMap_->Intersect(v, v + 1);
323fb726d48Sopenharmony_ci            break;
324fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_GE:
325fb726d48Sopenharmony_ci            indexMap_->Intersect(v, rowCount_);
326fb726d48Sopenharmony_ci            break;
327fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_GT:
328fb726d48Sopenharmony_ci            v++;
329fb726d48Sopenharmony_ci            indexMap_->Intersect(v, rowCount_);
330fb726d48Sopenharmony_ci            break;
331fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_LE:
332fb726d48Sopenharmony_ci            v++;
333fb726d48Sopenharmony_ci            indexMap_->Intersect(0, v);
334fb726d48Sopenharmony_ci            break;
335fb726d48Sopenharmony_ci        case SQLITE_INDEX_CONSTRAINT_LT:
336fb726d48Sopenharmony_ci            indexMap_->Intersect(0, v);
337fb726d48Sopenharmony_ci            break;
338fb726d48Sopenharmony_ci        default:
339fb726d48Sopenharmony_ci            // can't filter, all rows
340fb726d48Sopenharmony_ci            break;
341fb726d48Sopenharmony_ci    }
342fb726d48Sopenharmony_ci}
343fb726d48Sopenharmony_ci
344fb726d48Sopenharmony_cidouble TableBase::CalculateFilterCost(int64_t rowCount, FilterConstraints &fc)
345fb726d48Sopenharmony_ci{
346fb726d48Sopenharmony_ci    auto constraints = fc.GetConstraints();
347fb726d48Sopenharmony_ci    if (constraints.empty()) { // scan all rows
348fb726d48Sopenharmony_ci        return rowCount;
349fb726d48Sopenharmony_ci    }
350fb726d48Sopenharmony_ci    double filterCost = 0.0;
351fb726d48Sopenharmony_ci    for (int32_t i = 0; i < static_cast<int32_t>(constraints.size()); i++) {
352fb726d48Sopenharmony_ci        if (rowCount <= 1) {
353fb726d48Sopenharmony_ci            // only one row or nothing, needn't filter by constraint
354fb726d48Sopenharmony_ci            filterCost += rowCount;
355fb726d48Sopenharmony_ci            break;
356fb726d48Sopenharmony_ci        }
357fb726d48Sopenharmony_ci        FilterByConstraint(fc, filterCost, rowCount, i);
358fb726d48Sopenharmony_ci    }
359fb726d48Sopenharmony_ci    return filterCost;
360fb726d48Sopenharmony_ci}
361fb726d48Sopenharmony_civoid TableBase::EstimateFilterCost(FilterConstraints &fc, EstimatedIndexInfo &ei)
362fb726d48Sopenharmony_ci{
363fb726d48Sopenharmony_ci    constexpr double filterBaseCost = 1000.0; // set-up and tear-down
364fb726d48Sopenharmony_ci    constexpr double indexCost = 2.0;
365fb726d48Sopenharmony_ci    ei.estimatedCost = filterBaseCost;
366fb726d48Sopenharmony_ci    auto rowCount = GetSize();
367fb726d48Sopenharmony_ci    if (rowCount > -1) {
368fb726d48Sopenharmony_ci        if (rowCount == 0 || rowCount == 1) {
369fb726d48Sopenharmony_ci            ei.estimatedRows = rowCount;
370fb726d48Sopenharmony_ci            ei.estimatedCost += indexCost * rowCount;
371fb726d48Sopenharmony_ci            return;
372fb726d48Sopenharmony_ci        }
373fb726d48Sopenharmony_ci        ei.estimatedCost += CalculateFilterCost(rowCount, fc);
374fb726d48Sopenharmony_ci        ei.estimatedRows = rowCount;
375fb726d48Sopenharmony_ci        ei.estimatedCost += rowCount * indexCost;
376fb726d48Sopenharmony_ci        ei.isOrdered = true;
377fb726d48Sopenharmony_ci
378fb726d48Sopenharmony_ci        GetOrbyes(fc, ei);
379fb726d48Sopenharmony_ci    }
380fb726d48Sopenharmony_ci}
381fb726d48Sopenharmony_ci
382fb726d48Sopenharmony_ci} // namespace TraceStreamer
383fb726d48Sopenharmony_ci} // namespace SysTuning
384