1 /* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef TABLE_H 17 #define TABLE_H 18 19 #include <memory> 20 #include <set> 21 #include <string> 22 #include <vector> 23 24 #include "filter_constraints.h" 25 #include "index_map.h" 26 #include "sqlite3.h" 27 #include "trace_data_cache.h" 28 namespace SysTuning { 29 namespace TraceStreamer { 30 class TableBase; 31 using TabTemplate = std::unique_ptr<TableBase> (*)(const TraceDataCache *dataCache); 32 class TableBase : public sqlite3_vtab { 33 public: 34 virtual ~TableBase(); 35 TableBase(const TableBase &) = delete; 36 TableBase &operator=(const TableBase &) = delete; 37 38 template <typename T> TableDeclare(sqlite3 & db,TraceDataCache * dataCache,const std::string & tableName)39 static void TableDeclare(sqlite3 &db, TraceDataCache *dataCache, const std::string &tableName) 40 { 41 TableRegister(db, dataCache, tableName, [](const TraceDataCache *cache) { 42 return std::unique_ptr<TableBase>(std::make_unique<T>(cache)); 43 }); 44 dataCache->AppendNewTable(tableName); 45 } 46 std::string CreateTableSql() const; 47 bool CanFilterId(const char op, size_t &rowCount); 48 bool CanFilterSorted(const char op, size_t &rowCount); 49 50 class Cursor : public sqlite3_vtab_cursor { 51 public: 52 Cursor(const TraceDataCache *dataCache, TableBase *table, uint32_t rowCount); 53 virtual ~Cursor(); Reset()54 virtual void Reset() 55 { 56 indexMap_ = std::make_unique<IndexMap>(0, rowCount_); 57 } 58 59 virtual int32_t Next(); 60 61 virtual int32_t Eof(); 62 63 virtual uint32_t CurrentRow() const; 64 virtual void FilterTS(unsigned char op, sqlite3_value *argv, const std::deque<InternalTime> ×); 65 66 virtual int32_t RowId(sqlite3_int64 *id); Filter(const FilterConstraints & fc,sqlite3_value ** argv)67 virtual int32_t Filter(const FilterConstraints &fc, sqlite3_value **argv) 68 { 69 Unused(fc); 70 Unused(argv); 71 return 0; 72 } 73 virtual int32_t Column(int32_t n) const = 0; 74 template <typename T1, typename T2> SetTypeColumnInt64(const T1 & data,const T2 & invalidValue)75 void SetTypeColumnInt64(const T1 &data, const T2 &invalidValue) const 76 { 77 if (data != invalidValue) { 78 sqlite3_result_int64(context_, static_cast<int64_t>(data)); 79 } 80 } 81 template <typename T1, typename T2> SetTypeColumnInt32(const T1 & data,const T2 & invalidValue)82 void SetTypeColumnInt32(const T1 &data, const T2 &invalidValue) const 83 { 84 if (data != invalidValue) { 85 sqlite3_result_int(context_, static_cast<int32_t>(data)); 86 } 87 } 88 template <typename T> SetTypeColumnInt64NotZero(const T & data)89 void SetTypeColumnInt64NotZero(const T &data) const 90 { 91 if (data) { 92 sqlite3_result_int64(context_, static_cast<int64_t>(data)); 93 } 94 } 95 template <typename T1, typename T2> SetTypeColumnText(const T1 & data,const T2 & invalidValue)96 void SetTypeColumnText(const T1 &data, const T2 &invalidValue) const 97 { 98 if (data != invalidValue) { 99 sqlite3_result_text(context_, dataCache_->GetDataFromDict(data).c_str(), STR_DEFAULT_LEN, nullptr); 100 } 101 } 102 template <typename T1, typename T2, typename T3> SetTypeColumn(const T1 & data,const T2 & invalidValue,const T3 invalidTypeId)103 void SetTypeColumn(const T1 &data, const T2 &invalidValue, const T3 invalidTypeId) const 104 { 105 if (data != invalidValue) { 106 sqlite3_result_int64(context_, static_cast<int64_t>(data)); 107 } else { 108 sqlite3_result_int64(context_, static_cast<int64_t>(invalidTypeId)); 109 } 110 } 111 template <typename T1, typename T2> SetTypeColumnTextNotEmpty(const T1 & data,const T2 & dataToString)112 void SetTypeColumnTextNotEmpty(const T1 &data, const T2 &dataToString) const 113 { 114 if (!data) { 115 sqlite3_result_text(context_, dataToString, STR_DEFAULT_LEN, nullptr); 116 } 117 } 118 virtual void FilterId(unsigned char op, sqlite3_value *argv); 119 virtual void FilterEnd(); SwapIndexFront(std::vector<FilterConstraints::Constraint> & cs,const std::set<uint32_t> & sId)120 void SwapIndexFront(std::vector<FilterConstraints::Constraint> &cs, const std::set<uint32_t> &sId) 121 { 122 uint32_t index = 0; 123 for (size_t i = 0; i < cs.size(); i++) { 124 const auto &c = cs[i]; 125 if (sId.count(c.col)) { 126 std::swap(cs[index], cs[i]); 127 index++; 128 break; 129 } 130 } 131 } 132 133 public: 134 sqlite3_context *context_; 135 TableBase *table_ = nullptr; 136 137 protected: 138 const TraceDataCache *dataCache_; 139 std::unique_ptr<IndexMap> indexMap_; 140 uint32_t rowCount_; 141 }; 142 143 struct ColumnInfo { ColumnInfoColumnInfo144 ColumnInfo(const std::string &name, const std::string &type) : name_(name), type_(type) {} 145 std::string name_; 146 std::string type_; 147 }; 148 149 protected: TableBase(const TraceDataCache * dataCache)150 explicit TableBase(const TraceDataCache *dataCache) : dataCache_(dataCache), cursor_(nullptr) {} 151 152 struct EstimatedIndexInfo { 153 int64_t estimatedRows = 0; 154 double estimatedCost = 0.0; 155 bool isOrdered = false; 156 }; 157 158 static void TableRegister(sqlite3 &db, TraceDataCache *cache, const std::string &tableName, TabTemplate tmplate); 159 static void SetModuleCallbacks(sqlite3_module &module, const std::string &tableName); Update(int32_t argc,sqlite3_value ** argv,sqlite3_int64 * pRowid)160 virtual int32_t Update(int32_t argc, sqlite3_value **argv, sqlite3_int64 *pRowid) 161 { 162 return SQLITE_READONLY; 163 } 164 165 int32_t BestIndex(sqlite3_index_info *idxInfo); 166 // needs to correspond to Cursor::Filter() FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount,uint32_t currenti)167 virtual void FilterByConstraint(FilterConstraints &fc, double &filterCost, size_t rowCount, uint32_t currenti) 168 { 169 Unused(fc); 170 Unused(filterCost); 171 Unused(rowCount); 172 Unused(currenti); 173 } 174 GetSize()175 virtual int64_t GetSize() 176 { 177 return -1; 178 } 179 GetOrbyes(FilterConstraints & fc,EstimatedIndexInfo & ei)180 virtual void GetOrbyes(FilterConstraints &fc, EstimatedIndexInfo &ei) 181 { 182 Unused(fc); 183 Unused(ei); 184 } 185 // needs to correspond to Cursor::Filter() 186 virtual void EstimateFilterCost(FilterConstraints &fc, EstimatedIndexInfo &ei); 187 double CalculateFilterCost(int64_t rowCount, FilterConstraints &fc); 188 189 virtual std::unique_ptr<Cursor> CreateCursor() = 0; 190 int32_t Open(sqlite3_vtab_cursor **ppCursor); Init(int32_t,const char * const *)191 virtual void Init(int32_t, const char *const *) 192 { 193 return; 194 }; 195 196 public: 197 std::string name_; 198 199 protected: 200 std::vector<ColumnInfo> tableColumn_ = {}; 201 std::vector<std::string> tablePriKey_ = {}; 202 const TraceDataCache *dataCache_; 203 TraceDataCache *wdataCache_ = nullptr; 204 std::unique_ptr<Cursor> cursor_; 205 206 private: 207 uint16_t bestIndexNum_ = 0; 208 int32_t cacheIdxNum_ = 0; 209 FilterConstraints cacheConstraint_; 210 }; 211 } // namespace TraceStreamer 212 } // namespace SysTuning 213 214 #endif // TABLE_H 215