another ugly basic implementation

This commit is contained in:
VaclavT 2021-07-04 15:03:13 +02:00
parent b55115f7c3
commit b4711985b3
12 changed files with 417 additions and 60 deletions

View File

@ -12,7 +12,7 @@ project(msql)
set(PROJECT_NAME msql) set(PROJECT_NAME msql)
set(SOURCE set(SOURCE
exception.cpp lexer.cpp parser.cpp executor.cpp main.cpp table.cpp table.h) exception.cpp lexer.cpp parser.cpp executor.cpp main.cpp table.cpp table.h row.cpp row.h)
add_executable(${PROJECT_NAME} ${SOURCE}) add_executable(${PROJECT_NAME} ${SOURCE})

10
Readme.md Normal file
View File

@ -0,0 +1,10 @@
### TODO
- rename it to usql
- rename Exception to UException, Table to UTable, Row to URow etc
- unify using of float and double keywords
- add constructors
- add exceptions
- class members should have prefix m_O
- add pipe | token
- add logging

View File

@ -14,7 +14,7 @@ Table* Executor::find_table(const std::string name) {
if (table_def != std::end(m_tables)) { if (table_def != std::end(m_tables)) {
return table_def.operator->(); return table_def.operator->();
} else { } else {
// TODO throw exception throw Exception("table not found (" + name + ")");
} }
} }
@ -50,25 +50,28 @@ bool Executor::execute_insert_into_table(InsertIntoTableNode& node) {
Table* table_def = find_table(node.table_name); Table* table_def = find_table(node.table_name);
// prepare empty new_row // prepare empty new_row
std::vector<std::string> new_row; Row new_row = table_def->createEmptyRow();
new_row.reserve(table_def->columns_count());
for(size_t i=0; i<table_def->columns_count(); i++) {
new_row.push_back(std::string {""});
}
// copy values // copy values
for(size_t i=0; i<node.cols_names.size(); i++) { for(size_t i=0; i<node.cols_names.size(); i++) {
auto colNameNode = node.cols_names[i]; auto colNameNode = node.cols_names[i];
ColDefNode col_def = table_def->get_column_def(colNameNode.name); ColDefNode col_def = table_def->get_column_def(colNameNode.name);
// TODO validate // TODO validate value
new_row[col_def.order] = node.cols_values[i].value;
if (col_def.type == ColumnType::integer_type) {
new_row.setColumnValue(col_def.order, std::stoi(node.cols_values[i].value));
} else if (col_def.type == ColumnType::float_type) {
new_row.setColumnValue(col_def.order, std::stof(node.cols_values[i].value));
} else {
new_row.setColumnValue(col_def.order, node.cols_values[i].value);
}
} }
// TODO check not null columns // TODO check not null columns
// append new_row // append new_row
table_def->m_rows.push_back(new_row); table_def->addRow(new_row);
return true; return true;
} }
@ -99,18 +102,56 @@ bool Executor::execute_select(SelectFromTableNode& node) {
for (auto row = begin (table->m_rows); row != end (table->m_rows); ++row) { for (auto row = begin (table->m_rows); row != end (table->m_rows); ++row) {
// eval there for row // eval where for row
bool where_true = true; bool where_true = true;
if (node.where->node_type == NodeType::true_node) { // no where clause
if (where_true) { where_true = true;
// prepare empty row } else { // evaluate where
std::vector<std::string> new_row; RelationalOperatorNode& filter = static_cast<RelationalOperatorNode &>(*node.where);
new_row.reserve(result.columns_count()); if (filter.op == RelationalOperatorType::greater) {
for(auto i=0; i<result.columns_count(); i++) { std::unique_ptr<Node> left_value;
new_row.push_back(row->at(source_table_col_index[i])); if ((*filter.left).node_type == NodeType::database_value) {
DatabaseValueNode *dvl = static_cast<DatabaseValueNode*>(filter.left.get());
ColDefNode col_def = table->get_column_def(dvl->col_name); // TODO optimize it to just get this def once
auto db_value = row->ithColum(col_def.order);
if (col_def.type == ColumnType::integer_type) {
left_value = std::make_unique<IntValueNode>(db_value->integerValue());
}
// TODO other cases
} }
result.m_rows.push_back(new_row);
std::unique_ptr<Node> right_value;
if ((*filter.right).node_type == NodeType::int_value) {
IntValueNode *ivl = static_cast<IntValueNode*>(filter.right.get());
right_value = std::make_unique<IntValueNode>(ivl->value);
}
IntValueNode* left_int_value = static_cast<IntValueNode *>(left_value.get());
IntValueNode* right_int_value = static_cast<IntValueNode *>(right_value.get());
where_true = left_int_value->value > right_int_value->value;
} }
}
if (where_true) {
// prepare empty row
Row new_row = result.createEmptyRow();
// copy column values
for(auto idx=0; idx<result.columns_count(); idx++) {
auto row_col_index = source_table_col_index[idx];
ColValue *col_value = row->ithColum(row_col_index);
if (result_tbl_col_defs[idx].type == ColumnType::integer_type)
new_row.setColumnValue(idx, ((ColIntegerValue*)col_value)->integerValue());
if (result_tbl_col_defs[idx].type == ColumnType::float_type)
new_row.setColumnValue(idx, col_value->floatValue());
if (result_tbl_col_defs[idx].type == ColumnType::varchar_type)
new_row.setColumnValue(idx, col_value->stringValue());
}
// add row to result
result.m_rows.push_back(new_row);
}
} }
result.print(); result.print();

View File

@ -24,7 +24,7 @@ void Lexer::parse(const std::string &code) {
// TODO make it constant // TODO make it constant
std::regex words_regex("[0-9]+\\.[0-9]+|[0-9][0-9_]+[0-9]|[0-9]+|[A-Za-z]+[A-Za-z0-9_#]*|[\\(\\)\\[\\]\\{\\}]|[-\\+\\*/" std::regex words_regex("[0-9]+\\.[0-9]+|[0-9][0-9_]+[0-9]|[0-9]+|[A-Za-z]+[A-Za-z0-9_#]*|[\\(\\)\\[\\]\\{\\}]|[-\\+\\*/"
",;:\?]|==|>=|<=|~=|>|<|=|;|~|\\|\\||&&|\n|\r|\r\n|'([^']|'')*'|\".*?\"|%.*?\n"); ",;:\?]|==|>=|<=|~=|>|<|=|;|~|\\||or|and|\n|\r|\r\n|'([^']|'')*'|\".*?\"|%.*?\n");
auto words_begin = std::sregex_iterator(m_code_str.begin(), m_code_str.end(), words_regex); auto words_begin = std::sregex_iterator(m_code_str.begin(), m_code_str.end(), words_regex);
auto words_end = std::sregex_iterator(); auto words_end = std::sregex_iterator();
@ -55,6 +55,12 @@ void Lexer::debugTokens() {
Token Lexer::currentToken() { return m_tokens[m_index]; } Token Lexer::currentToken() { return m_tokens[m_index]; }
Token Lexer::consumeCurrentToken() {
int i = m_index;
nextToken();
return m_tokens[i];
}
void Lexer::nextToken() { void Lexer::nextToken() {
if (m_index < m_tokens.size()) { if (m_index < m_tokens.size()) {
m_index++; m_index++;
@ -65,7 +71,7 @@ void Lexer::skipToken(TokenType type) {
if (tokenType() == type) { if (tokenType() == type) {
nextToken(); nextToken();
} else { } else {
throw Exception("ERROR unexpected token " + currentToken().token_string + ", instead of " + typeToString(type)); throw Exception("ERROR unexpected token " + consumeCurrentToken().token_string + ", instead of " + typeToString(type));
} }
} }
@ -177,10 +183,10 @@ TokenType Lexer::type(const std::string &token) {
if (token == "varchar") if (token == "varchar")
return TokenType::keyword_varchar; return TokenType::keyword_varchar;
if (token == "||") if (token == "or")
return TokenType::logical_or; return TokenType::logical_or;
if (token == "&&") if (token == "and")
return TokenType::logical_and; return TokenType::logical_and;
if (token == ",") if (token == ",")

View File

@ -40,6 +40,7 @@ enum class TokenType {
close_paren, close_paren,
logical_and, logical_and,
logical_or, logical_or,
pipe,
semicolon, semicolon,
comma, comma,
newline, newline,
@ -61,7 +62,8 @@ public:
void debugTokens(); void debugTokens();
Token currentToken(); Token currentToken();
Token consumeCurrentToken();
void nextToken(); void nextToken();
@ -72,7 +74,8 @@ public:
TokenType nextTokenType(); TokenType nextTokenType();
TokenType prevTokenType(); TokenType prevTokenType();
static bool isRelationalOperator(TokenType token_type); static bool isRelationalOperator(TokenType token_type);
static bool isLogicalOperator(TokenType token_type);
private: private:
TokenType type(const std::string &token); TokenType type(const std::string &token);

View File

@ -16,7 +16,8 @@ int main(int argc, char *argv[]) {
"insert into a (i, s) values(1, 'one')", "insert into a (i, s) values(1, 'one')",
"insert into a (i, s) values(2, 'two')", "insert into a (i, s) values(2, 'two')",
"insert into a (i, s) values(3, 'two')", "insert into a (i, s) values(3, 'two')",
"select i, s from a where i > 0" "insert into a (i, s) values(4, 'four')",
"select i, s from a where i > 2"
// "update a set s = 'three' where i = 3" // "update a set s = 'three' where i = 3"
// "delete from a where i = 3" // "delete from a where i = 3"
// "select i, s from a where i > 0" // "select i, s from a where i > 0"
@ -25,7 +26,7 @@ int main(int argc, char *argv[]) {
for(auto command : sql_commands) { for(auto command : sql_commands) {
auto node = parser.parse(command); auto node = parser.parse(command);
executor.execute(*node.get()); executor.execute(*node);
} }
return 0; return 0;

View File

@ -19,6 +19,7 @@ std::unique_ptr<Node> Parser::parse(const std::string &code) {
return parse_select_from_table(); return parse_select_from_table();
} }
std::cout << "ERROR, token:" << lexer.currentToken().token_string << std::endl;
return std::make_unique<Node>(NodeType::error); return std::make_unique<Node>(NodeType::error);
} }
@ -29,9 +30,8 @@ std::unique_ptr<Node> Parser::parse_create_table() {
lexer.skipToken(TokenType::keyword_table); lexer.skipToken(TokenType::keyword_table);
if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ } if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ }
std::string table_name = lexer.currentToken().token_string; std::string table_name = lexer.consumeCurrentToken().token_string;
lexer.nextToken();
lexer.skipToken(TokenType::open_paren); lexer.skipToken(TokenType::open_paren);
int column_order = 0; int column_order = 0;
do { do {
@ -42,8 +42,7 @@ std::unique_ptr<Node> Parser::parse_create_table() {
// column name // column name
if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ } if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ }
column_name = lexer.currentToken().token_string; column_name = lexer.consumeCurrentToken().token_string;
lexer.nextToken();
// column type and optionaly len // column type and optionaly len
if (lexer.tokenType() == TokenType::keyword_int) { if (lexer.tokenType() == TokenType::keyword_int) {
@ -57,8 +56,7 @@ std::unique_ptr<Node> Parser::parse_create_table() {
lexer.nextToken(); lexer.nextToken();
lexer.skipToken(TokenType::open_paren); lexer.skipToken(TokenType::open_paren);
if (lexer.tokenType() == TokenType::int_number) { if (lexer.tokenType() == TokenType::int_number) {
column_len = std::stoi(lexer.currentToken().token_string); column_len = std::stoi(lexer.consumeCurrentToken().token_string);
lexer.nextToken();
} else { /* TODO handle error */ } } else { /* TODO handle error */ }
lexer.skipToken(TokenType::close_paren); lexer.skipToken(TokenType::close_paren);
} else { /* TODO handle error */ } } else { /* TODO handle error */ }
@ -94,15 +92,13 @@ std::unique_ptr<Node> Parser::parse_insert_into_table() {
// table name // table name
if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ } if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ }
std::string table_name = lexer.currentToken().token_string; std::string table_name = lexer.consumeCurrentToken().token_string;
lexer.nextToken();
// column names // column names
lexer.skipToken(TokenType::open_paren); lexer.skipToken(TokenType::open_paren);
do { do {
if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ } if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ }
cols_names.push_back(lexer.currentToken().token_string); cols_names.push_back(lexer.consumeCurrentToken().token_string);
lexer.nextToken();
lexer.skipTokenOptional(TokenType::comma); lexer.skipTokenOptional(TokenType::comma);
} while (lexer.tokenType() != TokenType::close_paren); } while (lexer.tokenType() != TokenType::close_paren);
@ -113,8 +109,7 @@ std::unique_ptr<Node> Parser::parse_insert_into_table() {
// column values // column values
lexer.skipToken(TokenType::open_paren); lexer.skipToken(TokenType::open_paren);
do { do {
cols_values.push_back(lexer.currentToken().token_string); cols_values.push_back(lexer.consumeCurrentToken().token_string);
lexer.nextToken();
lexer.skipTokenOptional(TokenType::comma); lexer.skipTokenOptional(TokenType::comma);
} while (lexer.tokenType() != TokenType::close_paren); } while (lexer.tokenType() != TokenType::close_paren);
@ -124,25 +119,69 @@ std::unique_ptr<Node> Parser::parse_insert_into_table() {
} }
std::unique_ptr<Node> Parser::parse_select_from_table() { std::unique_ptr<Node> Parser::parse_select_from_table() {
std::vector<Node> where {};
std::vector<ColNameNode> cols_names {}; std::vector<ColNameNode> cols_names {};
std::unique_ptr<Node> where_node;
lexer.skipToken(TokenType::keyword_select); lexer.skipToken(TokenType::keyword_select);
// TODO support also numbers and expressions // TODO support also numbers and expressions
while (lexer.tokenType() != TokenType::keyword_from) { while (lexer.tokenType() != TokenType::keyword_from) {
// TODO add consumeToken() which returns token and advances to next token // TODO add consumeToken() which returns token and advances to next token
cols_names.push_back(lexer.currentToken().token_string); cols_names.push_back(lexer.consumeCurrentToken().token_string);
lexer.nextToken();
lexer.skipTokenOptional(TokenType::comma); lexer.skipTokenOptional(TokenType::comma);
} }
lexer.skipToken(TokenType::keyword_from); lexer.skipToken(TokenType::keyword_from);
std::string table_name = lexer.currentToken().token_string; std::string table_name = lexer.consumeCurrentToken().token_string;
lexer.nextToken();
if (lexer.tokenType() == TokenType::keyword_where) {} if (lexer.tokenType() == TokenType::keyword_where) {
lexer.skipToken(TokenType::keyword_where);
where_node = parse_where_clause();
} else {
where_node = std::make_unique<TrueNode>();
}
// if (lexer.tokenType() == TokenType::keyword_order_by) {} // if (lexer.tokenType() == TokenType::keyword_order_by) {}
// if (lexer.tokenType() == TokenType::keyword_offset) {} // if (lexer.tokenType() == TokenType::keyword_offset) {}
// if (lexer.tokenType() == TokenType::keyword_limit) {} // if (lexer.tokenType() == TokenType::keyword_limit) {}
return std::make_unique<SelectFromTableNode>(table_name, cols_names, where); return std::make_unique<SelectFromTableNode>(table_name, cols_names, std::move(where_node));
}
std::unique_ptr<Node> Parser::parse_where_clause() {
// TODO add support for multiple filters
// TODO add support for parenthises
auto left = parse_operand_node();
auto operation = parse_operator();
auto right = parse_operand_node();
return std::make_unique<RelationalOperatorNode>(operation, std::move(left), std::move(right));
}
std::unique_ptr<Node> Parser::parse_operand_node() {
// while not end or order or limit
auto token_type = lexer.tokenType();
std::string tokenString = lexer.consumeCurrentToken().token_string;
switch (token_type) {
case TokenType::int_number:
return std::make_unique<IntValueNode>(std::stoi(tokenString));
case TokenType::double_number:
return std::make_unique<FloatValueNode>(std::stod(tokenString));
case TokenType::string_literal:
return std::make_unique<StringValueNode>(tokenString);
case TokenType::identifier:
return std::make_unique<DatabaseValueNode>(tokenString);
default: ;
// Throw exception
}
}
RelationalOperatorType Parser::parse_operator() {
auto op = lexer.consumeCurrentToken();
switch (op.type) {
case TokenType::equal:
return RelationalOperatorType::equal;
case TokenType::greater:
return RelationalOperatorType::greater;
default: ;
// Throw exception
}
} }

View File

@ -14,6 +14,13 @@ enum class ColumnType {
}; };
enum class NodeType { enum class NodeType {
true_node,
int_value,
float_value,
string_value,
database_value,
logical_operator,
relational_operator,
create_table, create_table,
insert_into, insert_into,
select_from, select_from,
@ -56,6 +63,59 @@ struct ColDefNode : Node {
Node(NodeType::column_def), name(col_name), type(col_type), order(col_order), length(col_len), null(nullable) {} Node(NodeType::column_def), name(col_name), type(col_type), order(col_order), length(col_len), null(nullable) {}
}; };
struct TrueNode : Node {
TrueNode() : Node(NodeType::true_node) {}
};
struct IntValueNode : Node {
int value;
IntValueNode(int value) : Node(NodeType::int_value), value(value) {}
};
struct FloatValueNode : Node {
double value;
FloatValueNode(double value) : Node(NodeType::float_value), value(value) {}
};
struct StringValueNode : Node {
std::string value;
StringValueNode(std::string value) : Node(NodeType::string_value), value(value) {}
};
struct DatabaseValueNode : Node {
std::string col_name;
DatabaseValueNode(std::string name) : Node(NodeType::database_value), col_name(name) {}
};
struct LogicalOperatorNode : Node {
// and_operator,
// or_operator,
// not_operator,
// and / or / not
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
};
enum class RelationalOperatorType {
equal,
greater
// =, !=, >, >=, <, <=, like
};
struct RelationalOperatorNode : Node {
RelationalOperatorType op;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
RelationalOperatorNode(RelationalOperatorType op, std::unique_ptr<Node> left, std::unique_ptr<Node> right) :
Node(NodeType::relational_operator), op(op), left(std::move(left)), right(std::move(right)) {};
};
struct CreateTableNode : Node { struct CreateTableNode : Node {
std::string table_name; std::string table_name;
std::vector<ColDefNode> cols_defs; std::vector<ColDefNode> cols_defs;
@ -76,10 +136,10 @@ struct InsertIntoTableNode : Node {
struct SelectFromTableNode : Node { struct SelectFromTableNode : Node {
std::string table_name; std::string table_name;
std::vector<ColNameNode> cols_names; std::vector<ColNameNode> cols_names;
std::vector<Node> where; std::unique_ptr<Node> where;
SelectFromTableNode(const std::string name, std::vector<ColNameNode> names, std::vector<Node> where_clause) : SelectFromTableNode(const std::string name, std::vector<ColNameNode> names, std::unique_ptr<Node> where_clause) :
Node(NodeType::select_from), table_name(name), cols_names(names), where(where_clause) {} Node(NodeType::select_from), table_name(name), cols_names(names), where(std::move(where_clause)) {}
}; };
struct UpdateTableNode : Node { }; struct UpdateTableNode : Node { };
@ -101,6 +161,10 @@ private:
std::unique_ptr<Node> parse_insert_into_table(); std::unique_ptr<Node> parse_insert_into_table();
std::unique_ptr<Node> parse_select_from_table(); std::unique_ptr<Node> parse_select_from_table();
std::unique_ptr<Node> parse_where_clause();
std::unique_ptr<Node> parse_operand_node();
RelationalOperatorType parse_operator();
private: private:
Lexer lexer; Lexer lexer;
}; };

48
row.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "row.h"
Row::Row(int cols_count) {
m_columns.reserve(cols_count);
for (int i = 0; i < cols_count; i++) {
m_columns.push_back(std::make_unique<ColValue>());
}
}
Row::Row(const Row &other) {
m_columns.reserve(other.m_columns.size());
// TODO fixme this is nonsense
for (int i = 0; i < other.m_columns.size(); i++) {
m_columns.push_back(std::make_unique<ColNullValue>());
}
for (int i = 0; i < other.m_columns.size(); i++) {
if (ColIntegerValue* other_v = dynamic_cast<ColIntegerValue*>(other.m_columns[i].get())) {
setColumnValue(i, other_v->integerValue());
}
if (ColFloatValue* other_v = dynamic_cast<ColFloatValue*>(other.m_columns[i].get())) {
setColumnValue(i, other_v->floatValue());
}
if (ColStringValue* other_v = dynamic_cast<ColStringValue*>(other.m_columns[i].get())) {
setColumnValue(i, other_v->stringValue());
}
}
}
void Row::setColumnValue(int col_index, int value) {
m_columns[col_index] = std::make_unique<ColIntegerValue>(value);
}
void Row::setColumnValue(int col_index, double value) {
m_columns[col_index] = std::make_unique<ColFloatValue>(value);
}
void Row::setColumnValue(int col_index, std::string value) {
m_columns[col_index] = std::make_unique<ColStringValue>(value);
};
void Row::print() {
for(int i=0; i<m_columns.size(); i++) {
m_columns[i].get()->print();
}
}

119
row.h Normal file
View File

@ -0,0 +1,119 @@
#pragma once
#include "exception.h"
#include "parser.h"
#include <vector>
class ColumnValue {
private:
ColumnType m_type;
union {
int int_value;
double float_value;
};
};
struct ColValue {
virtual bool isNull() { return false; };
virtual bool isInteger() { return false; };
virtual bool isFloat() { return false; };
virtual bool isString() { return false; };
virtual int integerValue() { throw Exception("Not supported"); };
virtual double floatValue() { throw Exception("Not supported"); };
virtual std::string stringValue() { throw Exception("Not supported"); };
virtual void print() {std::cout << "ColValue:" << std::endl; };
};
struct ColNullValue : ColValue {
virtual bool isNull() { return true; };
virtual void print() {std::cout << "ColNullValue:" << std::endl; };
};
struct ColIntegerValue : ColValue {
ColIntegerValue(int value) : m_integer(value) {};
ColIntegerValue(const ColIntegerValue &other) : m_integer(other.m_integer) {}
virtual bool isInteger() { return true; };
virtual int integerValue() { return m_integer; };
virtual double floatValue() { return (double) m_integer; };
virtual std::string stringValue() { return std::to_string(m_integer); };
virtual void print() {std::cout << "ColIntegerValue: " << m_integer <<std::endl; };
int m_integer;
};
struct ColFloatValue : ColValue {
ColFloatValue(double value) : m_float(value) {};
ColFloatValue(const ColFloatValue &other) : m_float(other.m_float) {}
virtual bool isFloat() { return true; }
virtual int integerValue() { return (int) m_float; };
virtual double floatValue() { return m_float; };
virtual std::string stringValue() { return std::to_string(m_float); };
virtual void print() {std::cout << "ColFloatValue: " << m_float <<std::endl; };
double m_float;
};
struct ColStringValue : ColValue {
ColStringValue(const std::string value) : m_string(value) {};
ColStringValue(const ColStringValue &other) : m_string(other.m_string) {};
virtual bool isString() { return true; }
virtual int integerValue() { return std::stoi(m_string); };
virtual double floatValue() { return std::stod(m_string); };
virtual std::string stringValue() { return m_string; };
virtual void print() {std::cout << "ColStringValue: " << m_string <<std::endl; };
std::string m_string;
};
class Row {
public:
Row(int cols_count);
Row(const Row &other);
void setColumnValue(int col_index, int value);
void setColumnValue(int col_index, double value);
void setColumnValue(int col_index, std::string value);
ColValue& operator[](int i) {
return *m_columns[i];
}
ColValue* ithColum(int i) {
return m_columns[i].get();
}
void print();
private:
std::vector<std::unique_ptr<ColValue>> m_columns;
};

View File

@ -7,22 +7,40 @@ Table::Table(const std::string name, const std::vector<ColDefNode> columns) {
m_rows.clear(); m_rows.clear();
} }
ColDefNode Table::get_column_def(const std::string col_name) { ColDefNode Table::get_column_def(const std::string& col_name) {
auto name_cmp = [col_name](ColDefNode cd){ return cd.name == col_name; }; auto name_cmp = [col_name](ColDefNode cd){ return cd.name == col_name; };
auto col_def = std::find_if(begin(m_col_defs), end(m_col_defs), name_cmp ); auto col_def = std::find_if(begin(m_col_defs), end(m_col_defs), name_cmp );
if (col_def != std::end(m_col_defs)) { if (col_def != std::end(m_col_defs)) {
return *col_def; return *col_def;
} else { } else {
// TODO throw exception throw Exception("column not exists (" + col_name + ")");
} }
} }
Row Table::createEmptyRow() {
return Row(columns_count());
}
void Table::print() { void Table::print() {
std::cout << "** " << m_name << " **" << std::endl; std::cout << "** " << m_name << " **" << std::endl;
for(auto row : m_rows) { for(auto row : m_rows) {
for( auto col : row) { for(int ci = 0; ci < columns_count(); ci++) {
std::cout << col << ","; auto v = row[ci].stringValue();
std::cout << v << ",";
} }
std::cout << std::endl; std::cout << std::endl;
} }
} }
Table::Table(const Table& other) {
m_name = other.m_name;
m_col_defs = other.m_col_defs;
m_rows.clear(); // row not copied now
}
void Table::addRow(const Row &row) {
m_rows.push_back(row);
}

16
table.h
View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "parser.h" #include "parser.h"
#include "row.h"
#include <vector> #include <vector>
@ -8,14 +9,21 @@
struct Table { struct Table {
// public: // public:
Table(const Table& other);
Table(const std::string name, const std::vector<ColDefNode> columns); Table(const std::string name, const std::vector<ColDefNode> columns);
ColDefNode get_column_def(const std::string col_name); ColDefNode get_column_def(const std::string& col_name);
int columns_count() { return m_col_defs.size(); }; int columns_count() { return m_col_defs.size(); };
Row createEmptyRow(); // TODO this means unnecessary copying
void addRow(const Row &row);
void print(); void print();
// private: // private:
std::string m_name; std::string m_name;
std::vector<ColDefNode> m_col_defs; std::vector<ColDefNode> m_col_defs;
std::vector<std::vector<std::string>> m_rows; std::vector<Row> m_rows;
}; };