indexes WIP
This commit is contained in:
203
usql_dml.cpp
203
usql_dml.cpp
@@ -7,64 +7,7 @@
|
||||
namespace usql {
|
||||
|
||||
|
||||
std::unique_ptr<Table> USql::execute_select(SelectFromTableNode &node) const {
|
||||
// find source table
|
||||
Table *table = find_table(node.table_name);
|
||||
|
||||
// expand *
|
||||
expand_asterix_char(node, table);
|
||||
|
||||
// create result table
|
||||
std::vector<ColDefNode> result_tbl_col_defs{};
|
||||
std::vector<int> source_table_col_index{};
|
||||
for (int i = 0; i < node.cols_names->size(); i++) {
|
||||
SelectColNode * col_node = &node.cols_names->operator[](i);
|
||||
auto [src_tbl_col_index, rst_tbl_col_def] = get_column_definition(table, col_node, i);
|
||||
|
||||
source_table_col_index.push_back(src_tbl_col_index);
|
||||
result_tbl_col_defs.push_back(rst_tbl_col_def);
|
||||
}
|
||||
|
||||
// check for aggregate function
|
||||
bool is_aggregated = check_for_aggregate_only_functions(node, result_tbl_col_defs.size());
|
||||
|
||||
// prepare result table structure
|
||||
auto result = std::make_unique<Table>("result", result_tbl_col_defs);
|
||||
|
||||
// replace possible order by col names to col indexes and validate
|
||||
setup_order_columns(node.order_by, result.get());
|
||||
|
||||
|
||||
// execute access plan
|
||||
Row* new_row = nullptr;
|
||||
|
||||
// look for index to use
|
||||
auto [use_index, rowids] = probe_index_scan(node.where.get(), table);
|
||||
|
||||
// index scan
|
||||
if (use_index) {
|
||||
for (int & rowid : rowids) {
|
||||
evalRowWhere(node, table, (Row *) &table->get_row(rowid), result.get(), new_row, result_tbl_col_defs, source_table_col_index, is_aggregated);
|
||||
}
|
||||
|
||||
// full scan
|
||||
} else {
|
||||
for (auto row = table->fs_begin(); row != table->fs_end(); ++row) {
|
||||
evalRowWhere(node, table, &(*row), result.get(), new_row, result_tbl_col_defs, source_table_col_index, is_aggregated);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
execute_distinct(node, result.get());
|
||||
|
||||
execute_order_by(node, table, result.get());
|
||||
|
||||
execute_offset_limit(node.offset_limit, result.get());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::pair<bool, std::vector<int>> USql::probe_index_scan(const Node *where, Table *table) const {
|
||||
std::pair<bool, std::vector<rowid_t>> USql::probe_index_scan(const Node *where, Table *table) const {
|
||||
bool indexscan_possible = normalize_where(where);
|
||||
|
||||
if (indexscan_possible && Settings::get_bool_setting("USE_INDEXSCAN")) {
|
||||
@@ -73,10 +16,10 @@ std::pair<bool, std::vector<int>> USql::probe_index_scan(const Node *where, Tabl
|
||||
}
|
||||
|
||||
// no index scan
|
||||
return std::make_pair(false, std::vector<int>{});
|
||||
return std::make_pair(false, std::vector<rowid_t>{});
|
||||
}
|
||||
|
||||
std::pair<bool, std::vector<int>> USql::look_for_usable_index(const Node *where, Table *table) const {
|
||||
std::pair<bool, std::vector<rowid_t>> USql::look_for_usable_index(const Node *where, Table *table) const {
|
||||
if (where->node_type == NodeType::relational_operator) {
|
||||
auto * ron = (RelationalOperatorNode *)where;
|
||||
if (ron->op == RelationalOperatorType::equal) {
|
||||
@@ -87,7 +30,7 @@ std::pair<bool, std::vector<int>> USql::look_for_usable_index(const Node *where,
|
||||
|
||||
Index<IndexValue> * used_index = table->get_index_for_column(col_name);
|
||||
if (used_index != nullptr) {
|
||||
std::vector<int> rowids;
|
||||
std::vector<rowid_t> rowids;
|
||||
|
||||
if (used_index->get_data_type() == IndexedDataType::integer)
|
||||
rowids = used_index->search(((ValueNode *) ron->right.get())->getIntegerValue());
|
||||
@@ -111,7 +54,7 @@ std::pair<bool, std::vector<int>> USql::look_for_usable_index(const Node *where,
|
||||
}
|
||||
|
||||
// no index available
|
||||
return std::make_pair(false, std::vector<int>{});
|
||||
return std::make_pair(false, std::vector<rowid_t>{});
|
||||
}
|
||||
|
||||
bool USql::normalize_where(const Node *node) const {
|
||||
@@ -137,12 +80,12 @@ bool USql::normalize_where(const Node *node) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void USql::evalRowWhere(SelectFromTableNode &where_node,
|
||||
Table *src_table, Row *src_row,
|
||||
Table *rslt_table, Row *rslt_row,
|
||||
const std::vector<ColDefNode> &rslt_tbl_col_defs,
|
||||
const std::vector<int> &src_table_col_index,
|
||||
bool is_aggregated) {
|
||||
void USql::eval_where_on_row(SelectFromTableNode &where_node,
|
||||
Table *src_table, Row *src_row,
|
||||
Table *rslt_table, Row *rslt_row,
|
||||
const std::vector<ColDefNode> &rslt_tbl_col_defs,
|
||||
const std::vector<int> &src_table_col_index,
|
||||
bool is_aggregated) {
|
||||
|
||||
if (eval_where(where_node.where.get(), src_table, *src_row)) {
|
||||
// prepare empty src_row and copy column values
|
||||
@@ -224,7 +167,7 @@ void USql::execute_distinct(SelectFromTableNode &node, Table *result) {
|
||||
result->m_rows.erase(std::unique(result->m_rows.begin(), result->m_rows.end()), result->m_rows.end());
|
||||
}
|
||||
|
||||
void USql::execute_order_by(SelectFromTableNode &node, Table *table, Table *result) {
|
||||
void USql::execute_order_by(SelectFromTableNode &node, Table *result) {
|
||||
if (node.order_by.empty()) return;
|
||||
|
||||
auto compare_rows = [&node, &result](const Row &a, const Row &b) {
|
||||
@@ -252,6 +195,21 @@ void USql::execute_offset_limit(OffsetLimitNode &node, Table *result) {
|
||||
result->m_rows.erase(result->m_rows.begin() + node.limit, result->m_rows.end());
|
||||
}
|
||||
|
||||
bool USql::eval_where(Node *where, Table *table, Row &row)
|
||||
{
|
||||
switch (where->node_type)
|
||||
{
|
||||
case NodeType::true_node:
|
||||
return true;
|
||||
case NodeType::relational_operator: // just one condition
|
||||
return eval_relational_operator(*((RelationalOperatorNode *)where), table, row);
|
||||
case NodeType::logical_operator:
|
||||
return eval_logical_operator(*((LogicalOperatorNode *)where), table, row);
|
||||
default:
|
||||
throw Exception("Wrong node type");
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<int, ColDefNode> USql::get_column_definition(Table *table, SelectColNode *select_col_node, int col_order ) {
|
||||
return get_node_definition(table, select_col_node->value.get(), select_col_node->name, col_order );
|
||||
}
|
||||
@@ -341,8 +299,7 @@ std::tuple<int, ColDefNode> USql::get_node_definition(Table *table, Node * node,
|
||||
|
||||
|
||||
|
||||
|
||||
std::unique_ptr<Table> USql::execute_insert_into_table(InsertIntoTableNode &node) {
|
||||
std::unique_ptr<Table> USql::execute_insert_into_table(const InsertIntoTableNode &node) {
|
||||
// find table
|
||||
Table *table_def = find_table(node.table_name);
|
||||
|
||||
@@ -368,45 +325,54 @@ std::unique_ptr<Table> USql::execute_insert_into_table(InsertIntoTableNode &node
|
||||
|
||||
|
||||
|
||||
std::unique_ptr<Table> USql::execute_delete(DeleteFromTableNode &node) {
|
||||
std::unique_ptr<Table> USql::execute_delete(const DeleteFromTableNode &node) {
|
||||
size_t affected_rows = 0;
|
||||
|
||||
// find source table
|
||||
Table *table = find_table(node.table_name);
|
||||
|
||||
// execute access plan
|
||||
auto affected_rows = table->rows_count();
|
||||
Table::rows_scanner i = get_iterator(table, node.where.get());
|
||||
while(Row *row = i.next()) {
|
||||
bool to_delete = eval_where(node.where.get(), table, *row);
|
||||
if (to_delete) {
|
||||
row->set_deleted();
|
||||
table->unindex_row(*row);
|
||||
|
||||
table->m_rows.erase(
|
||||
std::remove_if(table->m_rows.begin(), table->m_rows.end(),
|
||||
[&node, table](Row &row){return eval_where(node.where.get(), table, row);}),
|
||||
table->m_rows.end());
|
||||
|
||||
affected_rows -= table->rows_count();
|
||||
affected_rows++;
|
||||
}
|
||||
}
|
||||
|
||||
return create_stmt_result_table(0, "delete succeeded", affected_rows);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Table> USql::execute_update(UpdateTableNode &node) {
|
||||
std::unique_ptr<Table> USql::execute_update(const UpdateTableNode &node) {
|
||||
size_t affected_rows = 0;
|
||||
|
||||
// find source table
|
||||
Table *table = find_table(node.table_name);
|
||||
|
||||
// execute access plan
|
||||
int affected_rows = 0;
|
||||
for (auto row = begin(table->m_rows); row != end(table->m_rows); ++row) {
|
||||
// eval where for row
|
||||
if (eval_where(node.where.get(), table, *row)) {
|
||||
int i = 0;
|
||||
Table::rows_scanner i = get_iterator(table, node.where.get());
|
||||
while(Row *row = i.next()) {
|
||||
bool to_update = eval_where(node.where.get(), table, *row);
|
||||
if (to_update) {
|
||||
Row old_row = * row;
|
||||
|
||||
int col_idx = 0;
|
||||
for (const auto& col : node.cols_names) {
|
||||
// TODO cache it like in select
|
||||
ColDefNode col_def = table->get_column_def(col.col_name);
|
||||
std::unique_ptr<ValueNode> new_val = eval_arithmetic_operator(col_def.type,
|
||||
static_cast<ArithmeticalOperatorNode &>(*node.values[i]),
|
||||
table, *row);
|
||||
static_cast<ArithmeticalOperatorNode &>(*node.values[col_idx]), table, *row);
|
||||
|
||||
usql::Table::validate_column(&col_def, new_val.get());
|
||||
row->setColumnValue(&col_def, new_val.get());
|
||||
i++;
|
||||
col_idx++;
|
||||
}
|
||||
table->reindex_row(old_row, *row);
|
||||
|
||||
affected_rows++;
|
||||
// TODO tady je problem, ze kdyz to zfajluje na jednom radku ostatni by se nemely provest
|
||||
}
|
||||
@@ -416,20 +382,59 @@ std::unique_ptr<Table> USql::execute_update(UpdateTableNode &node) {
|
||||
}
|
||||
|
||||
|
||||
bool USql::eval_where(Node *where, Table *table, Row &row) {
|
||||
switch (where->node_type) {
|
||||
case NodeType::true_node:
|
||||
return true;
|
||||
case NodeType::relational_operator: // just one condition
|
||||
return eval_relational_operator(*((RelationalOperatorNode *) where), table, row);
|
||||
case NodeType::logical_operator:
|
||||
return eval_logical_operator(*((LogicalOperatorNode *) where), table, row);
|
||||
default:
|
||||
throw Exception("Wrong node type");
|
||||
std::unique_ptr<Table> USql::execute_select(SelectFromTableNode &node) const {
|
||||
// find source table
|
||||
Table *table = find_table(node.table_name);
|
||||
|
||||
// expand *
|
||||
expand_asterix_char(node, table);
|
||||
|
||||
// create result table
|
||||
std::vector<ColDefNode> result_tbl_col_defs{};
|
||||
std::vector<int> source_table_col_index{};
|
||||
for (int i = 0; i < node.cols_names->size(); i++) {
|
||||
SelectColNode *col_node = &node.cols_names->operator[](i);
|
||||
auto [src_tbl_col_index, rst_tbl_col_def] = get_column_definition(table, col_node, i);
|
||||
|
||||
source_table_col_index.push_back(src_tbl_col_index);
|
||||
result_tbl_col_defs.push_back(rst_tbl_col_def);
|
||||
}
|
||||
|
||||
return false;
|
||||
// check for aggregate function
|
||||
bool is_aggregated = check_for_aggregate_only_functions(node, result_tbl_col_defs.size());
|
||||
|
||||
// prepare result table structure
|
||||
auto result = std::make_unique<Table>("result", result_tbl_col_defs);
|
||||
|
||||
// replace possible order by col names to col indexes and validate
|
||||
setup_order_columns(node.order_by, result.get());
|
||||
|
||||
// execute access plan
|
||||
Row *new_row = nullptr;
|
||||
|
||||
|
||||
Table::rows_scanner i = get_iterator(table, node.where.get());
|
||||
while(Row *row = i.next()) {
|
||||
eval_where_on_row(node, table, row, result.get(), new_row, result_tbl_col_defs, source_table_col_index, is_aggregated);
|
||||
}
|
||||
|
||||
execute_distinct(node, result.get());
|
||||
|
||||
execute_order_by(node, result.get());
|
||||
|
||||
execute_offset_limit(node.offset_limit, result.get());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Table::rows_scanner USql::get_iterator(Table *table, const Node *where) const {
|
||||
auto[use_index, rowids] = probe_index_scan(where, table);
|
||||
|
||||
if (use_index)
|
||||
return Table::rows_scanner(table, rowids);
|
||||
else
|
||||
return Table::rows_scanner(table);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user