usql/parser.h

620 lines
18 KiB
C++

#pragma once
#include "lexer.h"
#include "exception.h"
#include "ml_date.h"
#include "settings.h"
#include <string>
#include <utility>
#include <vector>
static const int FUNCTION_CALL = -1;
namespace usql {
enum class ColumnType {
integer_type,
float_type,
varchar_type,
date_type,
bool_type
};
std::string column_type_name(const ColumnType type);
enum class NodeType {
true_node,
null_value,
int_value,
float_value,
string_value,
bool_value,
logical_operator,
relational_operator,
arithmetical_operator,
create_table,
create_table_as_select,
insert_into,
select_from,
delete_from,
update_table,
load_table,
save_table,
drop_table,
create_index,
set,
show,
database_value,
offset_limit,
column_order,
function,
column_def,
error
};
struct Node {
NodeType node_type;
explicit Node(const NodeType type) : node_type(type) {}
virtual ~Node() = default;
virtual void dump() const {
std::cout << "type: Node" << (int)node_type << std::endl;
}
};
struct ColOrderNode : Node {
std::string col_name;
int col_index;
bool ascending;
ColOrderNode(std::string name, bool asc) : Node(NodeType::column_order), col_name(std::move(name)), col_index(-1), ascending(asc) {}
ColOrderNode(int index, bool asc) : Node(NodeType::database_value), col_index(index), ascending(asc) {}
void dump() const override {
std::cout << "type: ColOrderNode, col_name: " << col_name << ", col_index: " << col_index << ", asc: " << ascending << std::endl;
}
};
struct OffsetLimitNode : Node {
size_t offset;
size_t limit;
OffsetLimitNode(size_t off, size_t lim) : Node(NodeType::offset_limit), offset(off), limit(lim) {}
void dump() const override {
std::cout << "type: OffsetLimitNode, offset: " << offset << ", limit: " << limit << std::endl;
}
};
struct SelectColNode : Node {
std::unique_ptr<Node> value;
std::string name;
SelectColNode(std::unique_ptr<Node> column, std::string alias) :
Node(NodeType::database_value), value(std::move(column)), name(std::move(alias)) {}
void dump() const override {
std::cout << "type: SelectColNode, name:" << name << "value:" << std::endl;
value->dump();
}
};
struct ColDefNode : Node {
std::string name;
ColumnType type;
int order;
size_t length;
bool null;
ColDefNode(std::string col_name, ColumnType col_type, int col_order, size_t col_len, bool nullable) :
Node(NodeType::column_def), name(std::move(col_name)), type(col_type), order(col_order), length(col_len),
null(nullable) {}
void dump() const override {
std::cout << "type: ColDefNode, name: " << name << ", type: " << column_type_name(type) << ", order: " << order << ", length: " << length << ", null: " << null << std::endl;
}
};
struct FunctionNode : Node {
enum class Type {
to_char,
to_date,
to_int,
to_float,
date_add,
pp,
lower,
upper,
coalesce,
min,
max,
count
};
static Type get_function(const std::string &str) {
if (str=="to_char") return Type::to_char;
if (str=="to_date") return Type::to_date;
if (str=="to_int") return Type::to_int;
if (str=="to_float") return Type::to_float;
if (str=="date_add") return Type::date_add;
if (str=="pp") return Type::pp;
if (str=="lower") return Type::lower;
if (str=="upper") return Type::upper;
if (str=="coalesce") return Type::coalesce;
if (str=="min") return Type::min;
if (str=="max") return Type::max;
if (str=="count") return Type::count;
throw Exception("invalid function: " + str);
};
static std::string function_name(const Type type) {
if (type == Type::to_char) return "to_char";
if (type == Type::to_date) return "to_date";
if (type == Type::to_int) return "to_int";
if (type == Type::to_float) return "to_float";
if (type == Type::date_add) return "date_add";
if (type == Type::pp) return "pp";
if (type == Type::lower) return "lower";
if (type == Type::upper) return "upper";
if (type == Type::coalesce) return "coalesce";
if (type == Type::min) return "min";
if (type == Type::max) return "max";
if (type == Type::count) return "count";
throw Exception("invalid function: " + std::to_string((int)type));
};
FunctionNode(std::string func_name, std::vector<std::unique_ptr<Node>> pars) :
Node(NodeType::function), function(get_function(func_name)), params(std::move(pars)) {}
bool is_agg_function() {
return (function == Type::count || function == Type::min || function == Type::max);
}
friend std::ostream &operator<<(std::ostream &output, const Type &t ) {
output << function_name(t);
return output;
}
void dump() const override {
std::cout << "type: FunctionNode, function: " << function_name(function) << "(";
for(int i = 0; i < params.size(); i++){
if (i > 0) std::cout << ",";
params[i]->dump();
}
std::cout << ")" << std::endl;
}
Type function;
std::vector<std::unique_ptr<Node>> params;
};
struct TrueNode : Node {
TrueNode() : Node(NodeType::true_node) {}
void dump() const override {
std::cout << "type: TrueNode," << std::endl;
}
};
struct ValueNode : Node {
explicit ValueNode(NodeType type) : Node(type) {}
virtual bool isNull() const { return false; }
virtual long getIntegerValue() const = 0;
virtual double getDoubleValue() const = 0;
virtual std::string getStringValue() const = 0;
virtual long getDateValue() const = 0;
virtual bool getBooleanValue() const = 0;
~ValueNode() override = default;
};
struct NullValueNode : ValueNode {
NullValueNode() : ValueNode(NodeType::null_value) {}
bool isNull() const override { return true; }
long getIntegerValue() const override { throw Exception("getIntegerValue not supported on NullValueNode"); };
double getDoubleValue() const override { throw Exception("getDoubleValue not supported on NullValueNode"); };
std::string getStringValue() const override { throw Exception("getStringValue not supported on NullValueNode"); };
long getDateValue() const override { throw Exception("getDateValue not supported on NullValueNode"); };
bool getBooleanValue() const override { throw Exception("getBooleanValue not supported on NullValueNode"); };
void dump() const override {
std::cout << "type: NullValueNode," << std::endl;
}
};
struct IntValueNode : ValueNode {
long value;
explicit IntValueNode(long value) : ValueNode(NodeType::int_value), value(value) {}
long getIntegerValue() const override { return value; };
double getDoubleValue() const override { return (double) value; };
std::string getStringValue() const override { return Settings::long_to_string(value); }
long getDateValue() const override { return value; };
bool getBooleanValue() const override { return value != 0; };
void dump() const override {
std::cout << "type: IntValueNode, value: " << value << std::endl;
}
};
struct DoubleValueNode : ValueNode {
double value;
explicit DoubleValueNode(double value) : ValueNode(NodeType::float_value), value(value) {}
long getIntegerValue() const override { return (long) value; };
double getDoubleValue() const override { return value; };
std::string getStringValue() const override { return Settings::double_to_string(value); }
long getDateValue() const override { return (long) value; };
bool getBooleanValue() const override { return value != 0.0; };
void dump() const override {
std::cout << "type: DoubleValueNode, value: " << value << std::endl;
}
};
struct StringValueNode : ValueNode {
std::string value;
explicit StringValueNode(std::string value) : ValueNode(NodeType::string_value), value(std::move(value)) {}
long getIntegerValue() const override { return Settings::string_to_long(value); };
double getDoubleValue() const override { return Settings::string_to_double(value); };
std::string getStringValue() const override { return value; };
long getDateValue() const override { return Settings::string_to_date(value); };
bool getBooleanValue() const override { return Settings::string_to_bool(value); };
void dump() const override {
std::cout << "type: StringValueNode, value: " << value << std::endl;
}
};
struct BooleanValueNode : ValueNode {
bool value;
explicit BooleanValueNode(bool value) : ValueNode(NodeType::bool_value), value(value) {}
long getIntegerValue() const override { return (long) value; };
double getDoubleValue() const override { return (double) value; };
std::string getStringValue() const override { return Settings::bool_to_string(value); }
long getDateValue() const override { return (long) value; };
bool getBooleanValue() const override { return value; };
void dump() const override {
std::cout << "type: BooleanValueNode, value: " << value << std::endl;
}
};
struct DatabaseValueNode : Node {
std::string col_name;
explicit DatabaseValueNode(std::string name) : Node(NodeType::database_value), col_name(std::move(name)) {}
void dump() const override {
std::cout << "type: DatabaseValueNode, col_name: " << col_name << std::endl;
}
};
enum class LogicalOperatorType {
and_operator,
or_operator
// not_operator
};
struct LogicalOperatorNode : Node {
LogicalOperatorType op;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
LogicalOperatorNode(LogicalOperatorType op, std::unique_ptr<Node> left, std::unique_ptr<Node> right) :
Node(NodeType::logical_operator), op(op), left(std::move(left)), right(std::move(right)) {};
void dump() const override {
std::cout << "type: LogicalOperatorNode, op: " << (int)op << std::endl;
left->dump();
right->dump();
}
};
enum class RelationalOperatorType {
equal,
greater,
greater_equal,
lesser,
lesser_equal,
not_equal,
is,
is_not
// 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)) {};
void dump() const override {
std::cout << "type: RelationalOperatorNode, op: " << (int)op << std::endl;
left->dump();
right->dump();
}
};
enum class ArithmeticalOperatorType {
copy_value, // just copy lef value and do nothing with it
plus_operator,
minus_operator,
multiply_operator,
divide_operator
};
struct ArithmeticalOperatorNode : Node {
ArithmeticalOperatorType op;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
ArithmeticalOperatorNode(ArithmeticalOperatorType op, std::unique_ptr<Node> left, std::unique_ptr<Node> right) :
Node(NodeType::arithmetical_operator), op(op), left(std::move(left)), right(std::move(right)) {};
void dump() const override {
std::cout << "type: ArithmeticalOperatorNode, op: " << (int)op << std::endl;
left->dump();
right->dump();
}
};
struct CreateTableNode : Node {
std::string table_name;
std::vector<ColDefNode> cols_defs;
CreateTableNode(std::string name, std::vector<ColDefNode> defs) :
Node(NodeType::create_table), table_name(std::move(name)), cols_defs(std::move(defs)) {}
void dump() const override {
std::cout << "type: CreateTableNode, table_name: " << table_name << "(";
for(int i = 0; i < cols_defs.size(); i++) {
if (i > 0) std::cout << ",";
cols_defs[i].dump();
}
std::cout << ")" << std::endl;
}
};
struct InsertIntoTableNode : Node {
std::string table_name;
std::vector<DatabaseValueNode> cols_names;
std::vector<std::unique_ptr<Node>> cols_values;
InsertIntoTableNode(std::string name, std::vector<DatabaseValueNode> names, std::vector<std::unique_ptr<Node>> values) :
Node(NodeType::insert_into), table_name(std::move(name)), cols_names(std::move(names)), cols_values(std::move(values)) {}
void dump() const override {
std::cout << "type: InsertIntoTableNode, table_name: " << table_name << "(";
for(int i = 0; i < cols_names.size(); i++) {
if (i > 0) std::cout << ",";
cols_names[i].dump();
}
std::cout << ") values (";
for(int i = 0; i < cols_values.size(); i++) {
if (i > 0) std::cout << ",";
cols_values[i]->dump();
}
std::cout << ")" << std::endl;
}
};
struct SelectFromTableNode : Node {
std::string table_name;
std::unique_ptr<std::vector<SelectColNode>> cols_names;
std::unique_ptr<Node> where;
std::vector<ColOrderNode> order_by;
OffsetLimitNode offset_limit;
bool distinct;
SelectFromTableNode(std::string name, std::unique_ptr<std::vector<SelectColNode>> names, std::unique_ptr<Node> where_clause, std::vector<ColOrderNode> orderby, OffsetLimitNode offlim, bool distinct_):
Node(NodeType::select_from), table_name(std::move(name)), cols_names(std::move(names)), where(std::move(where_clause)), order_by(std::move(orderby)), offset_limit(std::move(offlim)), distinct(distinct_) {}
void dump() const override {
std::cout << "type: SelectFromTableNode, table_name: " << table_name;
std::cout << "colums: ";
for(int i = 0; i < cols_names->size(); i++) {
if (i > 0) std::cout << ",";
cols_names->operator[](i).dump();
}
std::cout << "where: ";
where->dump();
std::cout << "offset,limit: ";
for(int i = 0; i < order_by.size(); i++) {
if (i > 0) std::cout << ",";
order_by[i].dump();
}
std::cout << "offset,limit: ";
offset_limit.dump();
std::cout << std::endl;
}
};
struct CreateTableAsSelectNode : Node {
std::string table_name;
std::unique_ptr<Node> select_table;
CreateTableAsSelectNode(std::string name, std::unique_ptr<Node> table) :
Node(NodeType::create_table_as_select), table_name(std::move(name)), select_table(std::move(table)) {}
void dump() const override {
std::cout << "type: CreateTableAsSelectNode, table_name: " << table_name << std::endl;
select_table->dump();
}
};
struct UpdateTableNode : Node {
std::string table_name;
std::vector<DatabaseValueNode> cols_names;
std::vector<std::unique_ptr<Node>> values;
std::unique_ptr<Node> where;
UpdateTableNode(std::string name, std::vector<DatabaseValueNode> names, std::vector<std::unique_ptr<Node>> vals,
std::unique_ptr<Node> where_clause) :
Node(NodeType::update_table), table_name(std::move(name)), cols_names(std::move(names)), values(std::move(vals)),
where(std::move(where_clause)) {}
void dump() const override {
std::cout << "type: UpdateTableNode, table_name: " << table_name << " set ";
for(int i = 0; i < cols_names.size(); i++) {
if (i > 0) std::cout << ",";
cols_names[i].dump();
std::cout << " = ";
values[i]->dump();
}
std::cout << " where: ";
where->dump();
std::cout << std::endl;
}
};
struct LoadIntoTableNode : Node {
std::string table_name;
std::string filename;
LoadIntoTableNode(std::string name, std::string file) :
Node(NodeType::load_table), table_name(std::move(name)), filename(std::move(file)) {}
void dump() const override {
std::cout << "type: LoadIntoTableNode, table_name: " << table_name << ", filename" << filename << std::endl;
}
};
struct SaveTableNode : Node {
std::string table_name;
std::string filename;
SaveTableNode(std::string name, std::string file) :
Node(NodeType::save_table), table_name(std::move(name)), filename(std::move(file)) {}
void dump() const override {
std::cout << "type: SaveTableNode, table_name: " << table_name << ", filename" << filename << std::endl;
}
};
struct DropTableNode : Node {
std::string table_name;
explicit DropTableNode(std::string name) : Node(NodeType::drop_table), table_name(std::move(name)) {}
void dump() const override {
std::cout << "type: SelectFromTableNode, table_name: " << table_name << std::endl;
}
};
struct DeleteFromTableNode : Node {
std::string table_name;
std::unique_ptr<Node> where;
DeleteFromTableNode(std::string name, std::unique_ptr<Node> where_clause) :
Node(NodeType::delete_from), table_name(std::move(name)), where(std::move(where_clause)) {}
void dump() const override {
std::cout << "type: DeleteFromTableNode, table_name: " << table_name;
std::cout << "where: ";
where->dump();
std::cout << std::endl;
}
};
struct SetNode : Node {
std::string name;
std::string value;
SetNode(std::string node_name, std::string node_value) :
Node(NodeType::set), name(std::move(node_name)), value(std::move(node_value)) {}
void dump() const override {
std::cout << "type: SetNode, name: " << name << ", value: " << value << std::endl;
}
};
struct ShowNode : Node {
std::string name;
explicit ShowNode(std::string node_name) : Node(NodeType::show), name(std::move(node_name)) {}
void dump() const override {
std::cout << "type: ShowNode, name: " << name << std::endl;
}
};
struct CreateIndexNode : Node {
std::string index_name;
std::string table_name;
std::string column_name;
CreateIndexNode(std::string idx_name, std::string tbl_name, std::string col_name) :
Node(NodeType::create_index), index_name(std::move(idx_name)), table_name(std::move(tbl_name)), column_name(std::move(col_name)) {}
void dump() const override {
std::cout << "type: CreateIndexNode, table_name: " << table_name << ", index_name: " << index_name << ", column_name: " << column_name << std::endl;
}
};
class Parser {
public:
Parser();
std::unique_ptr<Node> parse(const std::string &code);
private:
std::unique_ptr<Node> parse_create_table();
std::unique_ptr<Node> parse_drop_table();
std::unique_ptr<Node> parse_load_table();
std::unique_ptr<Node> parse_save_table();
std::unique_ptr<Node> parse_set();
std::unique_ptr<Node> parse_show();
std::unique_ptr<Node> parse_insert_into_table();
std::unique_ptr<Node> parse_select_from_table();
std::unique_ptr<Node> parse_delete_from_table();
std::unique_ptr<Node> parse_update_table();
std::unique_ptr<Node> parse_create_index();
std::vector<ColOrderNode> parse_order_by_clause();
OffsetLimitNode parse_offset_limit_clause();
std::unique_ptr<Node> parse_where_clause();
std::unique_ptr<Node> parse_expression();
std::unique_ptr<Node> parse_expression(std::unique_ptr<Node> left);
std::unique_ptr<Node> parse_value();
RelationalOperatorType parse_relational_operator();
LogicalOperatorType parse_logical_operator();
ArithmeticalOperatorType parse_arithmetical_operator();
private:
Lexer m_lexer;
};
} // namespace