|
15 | 15 | #include <set>
|
16 | 16 | #include <string>
|
17 | 17 |
|
| 18 | +#include "catalog/catalog_cache.h" |
| 19 | +#include "catalog/database_catalog.h" |
| 20 | +#include "catalog/table_catalog.h" |
| 21 | +#include "catalog/column_catalog.h" |
| 22 | +#include "catalog/index_catalog.h" |
| 23 | + |
| 24 | +#include "parser/delete_statement.h" |
| 25 | +#include "parser/insert_statement.h" |
| 26 | +#include "parser/sql_statement.h" |
| 27 | +#include "parser/update_statement.h" |
| 28 | + |
18 | 29 | #include "planner/abstract_plan.h"
|
19 | 30 | #include "planner/abstract_scan_plan.h"
|
20 | 31 | #include "planner/delete_plan.h"
|
@@ -44,6 +55,15 @@ class PlanUtil {
|
44 | 55 | static const std::set<oid_t> GetTablesReferenced(
|
45 | 56 | const planner::AbstractPlan *plan);
|
46 | 57 |
|
| 58 | + /** |
| 59 | + * @brief Get the indexes affected by a given query |
| 60 | + * @param CatalogCache |
| 61 | + * @param SQLStatement |
| 62 | + * @return set of affected index object ids |
| 63 | + */ |
| 64 | + static const std::set<oid_t> GetAffectedIndexes( |
| 65 | + catalog::CatalogCache& catalog_cache, parser::SQLStatement* sql_stmt); |
| 66 | + |
47 | 67 | private:
|
48 | 68 | ///
|
49 | 69 | /// Helpers for GetInfo() and GetTablesReferenced()
|
@@ -149,5 +169,92 @@ inline void PlanUtil::GetTablesReferenced(const planner::AbstractPlan *plan,
|
149 | 169 | }
|
150 | 170 | }
|
151 | 171 |
|
| 172 | +namespace { |
| 173 | + |
| 174 | +template <typename T> |
| 175 | +bool isDisjoint(const std::set<T> &setA, const std::set<T> &setB) { |
| 176 | + bool disjoint = true; |
| 177 | + if (setA.empty() || setB.empty()) |
| 178 | + return disjoint; |
| 179 | + |
| 180 | + typename std::set<T>::const_iterator setA_it = setA.begin(); |
| 181 | + typename std::set<T>::const_iterator setB_it = setB.begin(); |
| 182 | + while (setA_it != setA.end() && setB_it != setB.end() && disjoint) { |
| 183 | + if (*setA_it == *setB_it) |
| 184 | + disjoint = false; |
| 185 | + else if (*setA_it < *setB_it) |
| 186 | + setA_it++; |
| 187 | + else |
| 188 | + setB_it++; |
| 189 | + } |
| 190 | + |
| 191 | + return disjoint; |
| 192 | +} |
| 193 | + |
| 194 | +} // namespace |
| 195 | + |
| 196 | +inline const std::set<oid_t> PlanUtil::GetAffectedIndexes( |
| 197 | + catalog::CatalogCache &catalog_cache, parser::SQLStatement *sql_stmt) { |
| 198 | + std::set<oid_t> index_oids; |
| 199 | + std::string db_name, table_name; |
| 200 | + switch (sql_stmt->GetType()) { |
| 201 | + // For INSERT, DELETE, all indexes are affected |
| 202 | + case StatementType::INSERT: { |
| 203 | + auto insert_stmt = static_cast<parser::InsertStatement *>(sql_stmt); |
| 204 | + db_name = insert_stmt->GetDatabaseName(); |
| 205 | + table_name = insert_stmt->GetTableName(); |
| 206 | + } |
| 207 | + PELOTON_FALLTHROUGH; |
| 208 | + case StatementType::DELETE: { |
| 209 | + if (table_name.empty() || db_name.empty()) { |
| 210 | + auto delete_stmt = static_cast<parser::DeleteStatement *>(sql_stmt); |
| 211 | + db_name = delete_stmt->GetDatabaseName(); |
| 212 | + table_name = delete_stmt->GetTableName(); |
| 213 | + } |
| 214 | + auto indexes_map = catalog_cache.GetDatabaseObject(db_name) |
| 215 | + ->GetTableObject(table_name) |
| 216 | + ->GetIndexObjects(); |
| 217 | + for (auto &index : indexes_map) { |
| 218 | + index_oids.insert(index.first); |
| 219 | + } |
| 220 | + } |
| 221 | + break; |
| 222 | + case StatementType::UPDATE: { |
| 223 | + auto update_stmt = static_cast<parser::UpdateStatement *>(sql_stmt); |
| 224 | + db_name = update_stmt->table->GetDatabaseName(); |
| 225 | + table_name = update_stmt->table->GetTableName(); |
| 226 | + auto db_object = catalog_cache.GetDatabaseObject(db_name); |
| 227 | + auto table_object = db_object->GetTableObject(table_name); |
| 228 | + |
| 229 | + auto &update_clauses = update_stmt->updates; |
| 230 | + std::set<oid_t> update_oids; |
| 231 | + for (const auto &update_clause : update_clauses) { |
| 232 | + LOG_TRACE("Affected column name for table(%s) in UPDATE query: %s", |
| 233 | + table_name.c_str(), update_clause->column.c_str()); |
| 234 | + auto col_object = table_object->GetColumnObject(update_clause->column); |
| 235 | + update_oids.insert(col_object->GetColumnId()); |
| 236 | + } |
| 237 | + |
| 238 | + auto indexes_map = table_object->GetIndexObjects(); |
| 239 | + for (auto &index : indexes_map) { |
| 240 | + LOG_TRACE("Checking if UPDATE query affects index: %s", |
| 241 | + index.second->GetIndexName().c_str()); |
| 242 | + const std::vector<oid_t> &key_attrs = |
| 243 | + index.second->GetKeyAttrs(); // why it's a vector, and not set? |
| 244 | + const std::set<oid_t> key_attrs_set(key_attrs.begin(), key_attrs.end()); |
| 245 | + if (!isDisjoint(key_attrs_set, update_oids)) { |
| 246 | + LOG_TRACE("Index (%s) is affected", |
| 247 | + index.second->GetIndexName().c_str()); |
| 248 | + index_oids.insert(index.first); |
| 249 | + } |
| 250 | + } |
| 251 | + } break; |
| 252 | + default: |
| 253 | + LOG_TRACE("Does not support finding affected indexes for query type: %d", |
| 254 | + static_cast<int>(sql_stmt->GetType())); |
| 255 | + } |
| 256 | + return (index_oids); |
| 257 | +} |
| 258 | + |
152 | 259 | } // namespace planner
|
153 | 260 | } // namespace peloton
|
0 commit comments