create table as

This commit is contained in:
VaclavT 2021-07-18 21:49:13 +02:00
parent 3e913263fc
commit 9afbe6435e
13 changed files with 203 additions and 137 deletions

View File

@ -1,12 +0,0 @@
### TODO
- unify using of float and double keywords to double
- use long data type for int
- stoi -> stol, stof -> stod
- add exceptions
- class members should have prefix m_
- add pipe | token
- add to_date a to_number functions
- add min and max functions
- add logging
- add const wherever should be

View File

@ -1,10 +1,13 @@
### TODO
- rename Exception to UException, Table to UTable, Row to URow etc
- remove newlines from lexed string tokens
- unify using of float and double keywords
- add constructors
- save table command
- unify using of float and double keywords to double
- use long data type for int
- stoi -> stol, stof -> stod
- add exceptions
- class members should have prefix m_
- add pipe | token
- add to_date a to_number functions
- add min and max functions, eg aggregate functions
- add logging
- add const wherever should be

View File

@ -156,6 +156,9 @@ namespace usql {
if (token == "<=")
return TokenType::lesser_equal;
if (token == "as")
return TokenType::keyword_as;
if (token == "create")
return TokenType::keyword_create;
@ -326,6 +329,9 @@ namespace usql {
case TokenType::lesser_equal:
txt = "<=";
break;
case TokenType::keyword_as:
txt = "as";
break;
case TokenType::keyword_create:
txt = "create";
break;

View File

@ -20,6 +20,7 @@ namespace usql {
greater_equal,
lesser,
lesser_equal,
keyword_as,
keyword_create,
keyword_table,
keyword_where,

View File

@ -15,20 +15,23 @@ int main(int argc, char *argv[]) {
"insert into a (i, s) values(3, 'two')",
"insert into a (i, s) values(4, lower('FOUR'))",
"insert into a (i, s) values(5, 'five')",
"select i, s from a where i > 2",
"select i, s from a where i = 1",
"select i, s from a where s = 'two'",
"select i, s from a where i <= 3 and s = 'one'",
"select i, s from a where i > 0",
"delete from a where i = 4",
"select i, s from a where i > 0",
"update a set f = 9.99 where i = 3",
"select i, s, f from a where i = 3",
"update a set s = 'three', f = f + 0.01 where i = 3",
"select i, s, f from a where i = 3",
"create table data (ticker varchar(8), price float null)",
"load data from '/Users/vaclavt/Library/Mobile Documents/com~apple~CloudDocs/Development/usql/data.csv')",
"select ticker, price from data"
// "select i, s from a where i > 2",
// "select i, s from a where i = 1",
// "select i, s from a where s = 'two'",
// "select i, s from a where i <= 3 and s = 'one'",
// "select i, s from a where i > 0",
// "delete from a where i = 4",
// "select i, s from a where i > 0",
// "update a set f = 9.99 where i = 3",
// "select i, s, f from a where i = 3",
// "update a set s = 'three', f = f + 0.01 where i = 3",
// "select i, s, f from a where i = 3",
// "create table data (ticker varchar(8), price float null)",
// "load data from '/Users/vaclavt/Library/Mobile Documents/com~apple~CloudDocs/Development/usql/data.csv')",
// "select ticker, price from data",
"select i, s, f from a where i < 300",
"create table x as select i, s, f from a where i < 300",
"select i, s, f from x where i < 300"
};

View File

@ -45,6 +45,14 @@ namespace usql {
if (lexer.tokenType() != TokenType::identifier) { /* TODO handle error */ }
std::string table_name = lexer.consumeCurrentToken().token_string;
// create as select
if (lexer.tokenType() == TokenType::keyword_as) {
lexer.skipToken(TokenType::keyword_as);
std::unique_ptr<Node> select = parse_select_from_table();
return std::make_unique<CreateTableAsSelectNode>(table_name, std::move(select));
} else {
lexer.skipToken(TokenType::open_paren);
int column_order = 0;
do {
@ -87,12 +95,11 @@ namespace usql {
lexer.skipTokenOptional(TokenType::comma);
// TODO in future constraints
} while (lexer.tokenType() != TokenType::close_paren);
return std::make_unique<CreateTableNode>(table_name, cols_def);
}
}
std::unique_ptr<Node> Parser::parse_insert_into_table() {

View File

@ -25,6 +25,7 @@ namespace usql {
relational_operator,
arithmetical_operator,
create_table,
create_table_as_select,
insert_into,
select_from,
delete_from,
@ -63,13 +64,6 @@ namespace usql {
null(nullable) {}
};
struct ColValueNode : Node {
std::string value;
ColValueNode(const std::string col_value) :
Node(NodeType::column_value), value(col_value) {}
};
struct FunctionNode : Node {
std::string function;
std::vector<std::unique_ptr<Node>> params;
@ -198,6 +192,7 @@ namespace usql {
Node(NodeType::create_table), table_name(name), cols_defs(defs) {}
};
struct InsertIntoTableNode : Node {
std::string table_name;
std::vector<ColNameNode> cols_names;
@ -216,6 +211,16 @@ namespace usql {
Node(NodeType::select_from), table_name(name), cols_names(names), where(std::move(where_clause)) {}
};
struct CreateTableAsSelectNode : Node {
std::string table_name;
std::unique_ptr<Node> select_table;
CreateTableAsSelectNode(const std::string name, std::unique_ptr<Node> table) :
Node(NodeType::create_table_as_select), table_name(name), select_table(std::move(table)) {}
};
struct UpdateTableNode : Node {
std::string table_name;
std::vector<ColNameNode> cols_names;

View File

@ -35,6 +35,10 @@ namespace usql {
return *this;
}
void Row::setColumnNull(int col_index) {
m_columns[col_index] = std::make_unique<ColNullValue>();
}
void Row::setColumnValue(int col_index, int value) {
m_columns[col_index] = std::make_unique<ColIntegerValue>(value);
}

8
row.h
View File

@ -10,7 +10,7 @@ namespace usql {
struct ColValue {
virtual bool isNull() { return false; };;;;
virtual bool isNull() { return false; };
virtual int integerValue() { throw Exception("Not supported"); };
@ -80,22 +80,20 @@ namespace usql {
public:
Row(int cols_count);
Row(const Row &other);
Row &operator=(Row other);
void setColumnNull(int col_index);
void setColumnValue(int col_index, int value);
void setColumnValue(int col_index, double value);
void setColumnValue(int col_index, const std::string &value);
ColValue &operator[](int i) {
return *m_columns[i];
}
ColValue *ithColumn(int i) {
ColValue * ithColumn(int i) const {
return m_columns[i].get();
}

View File

@ -3,13 +3,13 @@
namespace usql {
Table::Table(const std::string name, const std::vector<ColDefNode> columns) {
Table::Table(const std::string name, const std::vector<ColDefNode> columns) {
m_name = name;
m_col_defs = columns;
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 col_def = std::find_if(begin(m_col_defs), end(m_col_defs), name_cmp);
if (col_def != std::end(m_col_defs)) {
@ -17,31 +17,55 @@ namespace usql {
} else {
throw Exception("column not exists (" + col_name + ")");
}
}
}
Row Table::createEmptyRow() {
Row Table::createEmptyRow() {
return Row(columns_count());
}
}
void Table::print() {
void Table::print() {
std::cout << "** " << m_name << " **" << std::endl;
for (auto row : m_rows) {
row.print();
}
}
}
Table::Table(const Table &other) {
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) {
void Table::addRow(const Row &row) {
// TODO validate for not null values
// todo validate for length etc
m_rows.push_back(row);
}
}
void Table::addCopyOfRow(const Row &row) {
// TODO validate for not null values
// todo validate for length etc
Row new_row = createEmptyRow();
for(int i = 0; i < m_col_defs.size(); i++) {
ColValue *ct = row.ithColumn(i);
if (ct->isNull()) {
new_row.setColumnNull(i);
} else {
if (m_col_defs[i].type == ColumnType::integer_type) {
new_row.setColumnValue(i, row.ithColumn(i)->integerValue());
} else if (m_col_defs[i].type == ColumnType::float_type) {
new_row.setColumnValue(i, row.ithColumn(i)->floatValue());
} else if (m_col_defs[i].type == ColumnType::varchar_type) {
new_row.setColumnValue(i, row.ithColumn(i)->stringValue());
}
}
}
m_rows.push_back(row);
}
} // namespace

View File

@ -19,6 +19,7 @@ namespace usql {
Row createEmptyRow(); // TODO this means unnecessary copying
void addRow(const Row &row);
void addCopyOfRow(const Row &row);
void print();

View File

@ -18,6 +18,8 @@ std::unique_ptr<Table> USql::execute(Node &node) {
switch (node.node_type) {
case NodeType::create_table:
return execute_create_table(static_cast<CreateTableNode &>(node));
case NodeType::create_table_as_select:
return execute_create_table_as_table(static_cast<CreateTableAsSelectNode &>(node));
case NodeType::insert_into:
return execute_insert_into_table(static_cast<InsertIntoTableNode &>(node));
case NodeType::select_from:
@ -43,6 +45,28 @@ std::unique_ptr<Table> USql::execute_create_table(CreateTableNode &node) {
}
std::unique_ptr<Table> USql::execute_create_table_as_table(CreateTableAsSelectNode &node) {
// TODO check table does not exists
auto select = execute_select((SelectFromTableNode &) *node.select_table.get());
// create table
Table new_table{node.table_name, select.get()->m_col_defs};
m_tables.push_back(new_table);
// copy rows
// must be here, if rows are put into new_table, they are lost during m_tables.push_table
Table *table = find_table(node.table_name);
for( Row& orig_row : select.get()->m_rows) {
table->addCopyOfRow(orig_row);
}
select.release(); // is it correct? hoping not to release select table here and then when releasing CreateTableAsSelectNode
return create_stmt_result_table(0, "table created");
}
std::unique_ptr<Table> USql::execute_insert_into_table(InsertIntoTableNode &node) {
// TODO check column names.size = values.size
@ -107,14 +131,15 @@ std::unique_ptr<Table> USql::execute_select(SelectFromTableNode &node) {
for (auto idx = 0; idx < result->columns_count(); idx++) {
auto row_col_index = source_table_col_index[idx];
ColValue *col_value = row->ithColumn(row_col_index);
if (!col_value->isNull()) {
if (result_tbl_col_defs[idx].type == ColumnType::integer_type)
new_row.setColumnValue(idx,
((ColIntegerValue *) col_value)->integerValue());
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);

1
usql.h
View File

@ -18,6 +18,7 @@ private:
std::unique_ptr<Table> execute(Node &node);
std::unique_ptr<Table> execute_create_table(CreateTableNode &node);
std::unique_ptr<Table> execute_create_table_as_table(CreateTableAsSelectNode &node);
std::unique_ptr<Table> execute_insert_into_table(InsertIntoTableNode &node);
std::unique_ptr<Table> execute_select(SelectFromTableNode &node);
std::unique_ptr<Table> execute_delete(DeleteFromTableNode &node);