From 165438cdf3f8536fb09e4527cc0357d24d601cd9 Mon Sep 17 00:00:00 2001 From: vaclavt Date: Sun, 3 Apr 2022 16:54:44 +0200 Subject: [PATCH] usql function to_string renamed to to_char --- tests/test.lsp | 2 +- usql/parser.cpp | 50 +++++++++++++++++++++--------------------- usql/parser.h | 14 ++++++++---- usql/usql.cpp | 4 +++- usql/usql.h | 4 +++- usql/usql_dml.cpp | 22 +++++++++++++++---- usql/usql_function.cpp | 22 ++++++++++++++----- 7 files changed, 77 insertions(+), 41 deletions(-) diff --git a/tests/test.lsp b/tests/test.lsp index 689697b..82f93ea 100644 --- a/tests/test.lsp +++ b/tests/test.lsp @@ -1,6 +1,6 @@ (include "/usr/local/var/mlisp/ut.lsp") -(def local_time_offset 3600) +(def local_time_offset 7200) ;; prepare some code to be used in tests (defn fact (n) diff --git a/usql/parser.cpp b/usql/parser.cpp index b5682d7..678f6b0 100644 --- a/usql/parser.cpp +++ b/usql/parser.cpp @@ -3,7 +3,7 @@ namespace usql { -// TOOD handle premature eof + // TOOD handle premature eof std::string column_type_name(const ColumnType type) { if (type == ColumnType::integer_type) return "integer_type"; @@ -64,11 +64,11 @@ namespace usql { // create as select if (m_lexer.tokenType() == TokenType::keyword_as) { - m_lexer.skipToken(TokenType::keyword_as); + m_lexer.skipToken(TokenType::keyword_as); - std::unique_ptr select = parse_select_from_table(); + std::unique_ptr select = parse_select_from_table(); - return std::make_unique(table_name, std::move(select)); + return std::make_unique(table_name, std::move(select)); } else { m_lexer.skipToken(TokenType::open_paren); int column_order = 0; @@ -80,30 +80,30 @@ namespace usql { // column name if (m_lexer.tokenType() != TokenType::identifier) { - throw Exception("syntax error, expected identifier"); + throw Exception("syntax error, expected identifier"); } - database_value = m_lexer.consumeToken().token_string; + database_value = m_lexer.consumeToken().token_string; - // column type and optionally len - if (m_lexer.tokenType() == TokenType::keyword_integer) { - column_type = ColumnType::integer_type; - m_lexer.nextToken(); - } else if (m_lexer.tokenType() == TokenType::keyword_float) { - column_type = ColumnType::float_type; - m_lexer.nextToken(); - } else if (m_lexer.tokenType() == TokenType::keyword_varchar) { - column_type = ColumnType::varchar_type; - m_lexer.nextToken(); - m_lexer.skipToken(TokenType::open_paren); - column_len = std::stoi(m_lexer.consumeToken(TokenType::int_number).token_string); - m_lexer.skipToken(TokenType::close_paren); + // column type and optionally len + if (m_lexer.tokenType() == TokenType::keyword_integer) { + column_type = ColumnType::integer_type; + m_lexer.nextToken(); + } else if (m_lexer.tokenType() == TokenType::keyword_float) { + column_type = ColumnType::float_type; + m_lexer.nextToken(); + } else if (m_lexer.tokenType() == TokenType::keyword_varchar) { + column_type = ColumnType::varchar_type; + m_lexer.nextToken(); + m_lexer.skipToken(TokenType::open_paren); + column_len = std::stoi(m_lexer.consumeToken(TokenType::int_number).token_string); + m_lexer.skipToken(TokenType::close_paren); } else if (m_lexer.tokenType() == TokenType::keyword_date) { column_type = ColumnType::date_type; m_lexer.nextToken(); - } else if (m_lexer.tokenType() == TokenType::keyword_bool) { - column_type = ColumnType::bool_type; - m_lexer.nextToken(); - } else { + } else if (m_lexer.tokenType() == TokenType::keyword_bool) { + column_type = ColumnType::bool_type; + m_lexer.nextToken(); + } else { throw Exception("syntax error, column type expected, found " + m_lexer.currentToken().token_string); } @@ -120,7 +120,7 @@ namespace usql { m_lexer.skipTokenOptional(TokenType::comma); //constraints - //defaults + //defaults } while (m_lexer.tokenType() != TokenType::close_paren); return std::make_unique(table_name, cols_def); @@ -502,7 +502,7 @@ namespace usql { return RelationalOperatorType::lesser_equal; case TokenType::is: if (m_lexer.tokenType() == TokenType::keyword_not) { - m_lexer.skipToken(TokenType::keyword_not); + m_lexer.skipToken(TokenType::keyword_not); return RelationalOperatorType::is_not; } return RelationalOperatorType::is; diff --git a/usql/parser.h b/usql/parser.h index ee09e75..2392d36 100644 --- a/usql/parser.h +++ b/usql/parser.h @@ -126,8 +126,10 @@ struct ColDefNode : Node { struct FunctionNode : Node { enum class Type { - to_string, + to_char, to_date, + to_int, + to_float, date_add, pp, lower, @@ -139,8 +141,10 @@ struct FunctionNode : Node { }; static Type get_function(const std::string &str) { - if (str=="to_string") return Type::to_string; + 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; @@ -154,8 +158,10 @@ struct FunctionNode : Node { }; static std::string function_name(const Type type) { - if (type == Type::to_string) return "to_string"; + 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"; @@ -169,7 +175,7 @@ struct FunctionNode : Node { }; - Type function; + Type function; std::vector> params; FunctionNode(std::string func_name, std::vector> pars) : diff --git a/usql/usql.cpp b/usql/usql.cpp index e827c4b..4cb568f 100644 --- a/usql/usql.cpp +++ b/usql/usql.cpp @@ -182,7 +182,9 @@ std::unique_ptr USql::eval_function_value_node(Table *table, Row &row if (fnc->function == FunctionNode::Type::lower) return lower_function(evaluatedPars); if (fnc->function == FunctionNode::Type::upper) return upper_function(evaluatedPars); if (fnc->function == FunctionNode::Type::to_date) return to_date_function(evaluatedPars); - if (fnc->function == FunctionNode::Type::to_string) return to_string_function(evaluatedPars); + if (fnc->function == FunctionNode::Type::to_char) return to_char_function(evaluatedPars); + if (fnc->function == FunctionNode::Type::to_int) return to_int_function(evaluatedPars); + if (fnc->function == FunctionNode::Type::to_float) return to_float_function(evaluatedPars); if (fnc->function == FunctionNode::Type::date_add) return date_add_function(evaluatedPars); if (fnc->function == FunctionNode::Type::pp) return pp_function(evaluatedPars); if (fnc->function == FunctionNode::Type::count) return count_function(agg_func_value, evaluatedPars); diff --git a/usql/usql.h b/usql/usql.h index d8f9383..5cd8dc8 100644 --- a/usql/usql.h +++ b/usql/usql.h @@ -75,7 +75,9 @@ private: static std::unique_ptr upper_function(const std::vector> &evaluatedPars); static std::unique_ptr coalesce_function(const std::vector> &evaluatedPars); static std::unique_ptr to_date_function(const std::vector> &evaluatedPars); - static std::unique_ptr to_string_function(const std::vector> &evaluatedPars); + static std::unique_ptr to_char_function(const std::vector> &evaluatedPars); + static std::unique_ptr to_int_function(const std::vector> &evaluatedPars); + static std::unique_ptr to_float_function(const std::vector> &evaluatedPars); static std::unique_ptr date_add_function(const std::vector> &evaluatedPars); static std::unique_ptr pp_function(const std::vector> &evaluatedPars); diff --git a/usql/usql_dml.cpp b/usql/usql_dml.cpp index f259687..eeca189 100644 --- a/usql/usql_dml.cpp +++ b/usql/usql_dml.cpp @@ -217,7 +217,7 @@ ColDefNode USql::get_db_column_definition(Table *table, Node *node) { throw Exception("Undefined table node - get_db_column_definition"); } -std::tuple USql::get_node_definition(Table *table, Node * node, const std::string & col_name, int col_order ) { +std::tuple USql::get_node_definition(Table *table, Node * node, const std::string &col_name, int col_order ) { if (node->node_type == NodeType::database_value) { ColDefNode src_col_def = get_db_column_definition(table, node); ColDefNode col_def = ColDefNode{col_name, src_col_def.type, col_order, src_col_def.length, src_col_def.null}; @@ -226,9 +226,15 @@ std::tuple USql::get_node_definition(Table *table, Node * node, } else if (node->node_type == NodeType::function) { auto func_node = static_cast(node); - if (func_node->function == FunctionNode::Type::to_string) { + if (func_node->function == FunctionNode::Type::to_char) { ColDefNode col_def = ColDefNode{col_name, ColumnType::varchar_type, col_order, 32, true}; return std::make_tuple(FUNCTION_CALL, col_def); + } else if (func_node->function == FunctionNode::Type::to_int) { + ColDefNode col_def = ColDefNode{col_name, ColumnType::integer_type, col_order, 1, true}; + return std::make_tuple(FUNCTION_CALL, col_def); + } else if (func_node->function == FunctionNode::Type::to_float) { + ColDefNode col_def = ColDefNode{col_name, ColumnType::float_type, col_order, 1, true}; + return std::make_tuple(FUNCTION_CALL, col_def); } else if (func_node->function == FunctionNode::Type::to_date) { ColDefNode col_def = ColDefNode{col_name, ColumnType::integer_type, col_order, 1, true}; return std::make_tuple(FUNCTION_CALL, col_def); @@ -243,18 +249,26 @@ std::tuple USql::get_node_definition(Table *table, Node * node, // TODO handle cases here if (func_node->params.empty()) throw Exception("Coalesce without parameters"); if (func_node->params[0]->node_type != NodeType::database_value) throw Exception("Coalesce first parameter must be database column"); + ColDefNode tbl_col_def = get_db_column_definition(table, func_node->params[0].get()); ColDefNode col_def = ColDefNode{col_name, tbl_col_def.type, col_order, tbl_col_def.length, true}; return std::make_tuple(FUNCTION_CALL, col_def); } else if (func_node->function == FunctionNode::Type::min || func_node->function == FunctionNode::Type::max) { - auto col_type= ColumnType::float_type; + auto col_type = ColumnType::float_type; size_t col_len = 1; - auto & v = func_node->params[0]; + auto &v = func_node->params[0]; + if (v->node_type == NodeType::database_value) { ColDefNode src_col_def = get_db_column_definition(table, v.get()); col_type = src_col_def.type; col_len = src_col_def.length; + + } else if (node->node_type == NodeType::function) { + std::tuple fun_type = get_node_definition(table, static_cast(& *v), "", 0); + col_type = std::get<1>(fun_type).type; + col_len = std::get<1>(fun_type).length; } + ColDefNode col_def = ColDefNode{col_name, col_type, col_order, col_len, true}; return std::make_tuple(FUNCTION_CALL, col_def); } else if (func_node->function == FunctionNode::Type::count) { diff --git a/usql/usql_function.cpp b/usql/usql_function.cpp index 11ec866..6b766aa 100644 --- a/usql/usql_function.cpp +++ b/usql/usql_function.cpp @@ -7,12 +7,24 @@ namespace usql { -std::unique_ptr USql::to_string_function(const std::vector> &evaluatedPars) { - long date = evaluatedPars[0]->getDateValue(); - std::string format = evaluatedPars[1]->getStringValue(); - std::string formatted_date = date_to_string(date, format); +std::unique_ptr USql::to_char_function(const std::vector> &evaluatedPars) { + if (evaluatedPars[0]->node_type == NodeType::int_value && evaluatedPars.size()==2) { // TODO when propper date is introduced + long date = evaluatedPars[0]->getDateValue(); + std::string format = evaluatedPars[1]->getStringValue(); + std::string formatted_date = date_to_string(date, format); - return std::make_unique(formatted_date); + return std::make_unique(formatted_date); + } else { + return std::make_unique(evaluatedPars[0]->getStringValue()); + } +} + +std::unique_ptr USql::to_int_function(const std::vector> &evaluatedPars) { + return std::make_unique(evaluatedPars[0]->getIntegerValue()); +} + +std::unique_ptr USql::to_float_function(const std::vector> &evaluatedPars) { + return std::make_unique(evaluatedPars[0]->getDoubleValue()); } std::unique_ptr USql::to_date_function(const std::vector> &evaluatedPars) {