create table as
This commit is contained in:
parent
3e913263fc
commit
9afbe6435e
12
Radme.md
12
Radme.md
|
|
@ -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
|
||||
11
Readme.md
11
Readme.md
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
1
lexer.h
1
lexer.h
|
|
@ -20,6 +20,7 @@ namespace usql {
|
|||
greater_equal,
|
||||
lesser,
|
||||
lesser_equal,
|
||||
keyword_as,
|
||||
keyword_create,
|
||||
keyword_table,
|
||||
keyword_where,
|
||||
|
|
|
|||
31
main.cpp
31
main.cpp
|
|
@ -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"
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
11
parser.cpp
11
parser.cpp
|
|
@ -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() {
|
||||
|
|
|
|||
19
parser.h
19
parser.h
|
|
@ -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;
|
||||
|
|
|
|||
4
row.cpp
4
row.cpp
|
|
@ -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
8
row.h
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
50
table.cpp
50
table.cpp
|
|
@ -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
|
||||
1
table.h
1
table.h
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
29
usql.cpp
29
usql.cpp
|
|
@ -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
1
usql.h
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue