diff --git a/Readme.md b/Readme.md index 6e9dabb..6c48cd2 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,6 @@ ### TODO +- better support for values in update and insert - date functions - now, add_date... - string functions rtrim, ltrim, rpad, lpad - add pipe | concatenation diff --git a/main.cpp b/main.cpp index d6f420f..1a7d333 100644 --- a/main.cpp +++ b/main.cpp @@ -139,7 +139,8 @@ int main(int argc, char *argv[]) { // "select ticker, dimension, calendar_date, eps, dps from sf1 where (ticker = 'AIG' or ticker = 'WFC') and dimension = 'MRY' order by 3 desc", "create table a (i integer not null, s varchar(64), f float null, d date null, b boolean)", "insert into a (i, s, b) values(1, upper('one'), 'Y')", - "select i+2, s, b from a where i >=1 order by 1 desc offset 0 limit 1", + "select i, s from a where i < to_date('20.12.1973', '%d.%m.%Y')", +// xxxxxxxx "select i+2, s, b from a where i >=1 order by 1 desc offset 0 limit 1", // "update table a set s = 'null string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'", "update table a set i = null", "insert into a (i, s) values(2, 'two')", diff --git a/parser.cpp b/parser.cpp index 6c226ae..c0d37c3 100644 --- a/parser.cpp +++ b/parser.cpp @@ -444,8 +444,9 @@ namespace usql { std::unique_ptr Parser::parse_operand_node() { auto token_type = m_lexer.tokenType(); + // parenthised expression if (token_type == TokenType::open_paren) { - m_lexer.skipToken(TokenType::open_paren); + // open paren already consumed auto left = parse_expression(); do { left = parse_expression(std::move(left)); @@ -455,21 +456,39 @@ namespace usql { return left; } - std::string tokenString = m_lexer.consumeCurrentToken().token_string; - switch (token_type) { - case TokenType::int_number: - return std::make_unique(std::stoi(tokenString)); - case TokenType::double_number: - return std::make_unique(std::stod(tokenString)); - case TokenType::string_literal: - return std::make_unique(tokenString); - case TokenType::identifier: - return std::make_unique(tokenString); - case TokenType::keyword_null: - return std::make_unique(); - default: - throw Exception("Unknown operand node " + tokenString); + // function call + if (token_type == TokenType::identifier && m_lexer.nextTokenType() == TokenType::open_paren) { + std::string function_name = m_lexer.consumeCurrentToken().token_string; + std::vector> pars; + + m_lexer.skipToken(TokenType::open_paren); + while (m_lexer.tokenType() != TokenType::close_paren) { // TODO handle errors + pars.push_back(parse_operand_node()); + m_lexer.skipTokenOptional(TokenType::comma); + } + m_lexer.skipToken(TokenType::close_paren); + return std::make_unique(function_name, std::move(pars)); } + + // numbers and strings + std::string tokenString = m_lexer.consumeCurrentToken().token_string; + + if (token_type == TokenType::int_number) + return std::make_unique(std::stoi(tokenString)); + if (token_type == TokenType::double_number) + return std::make_unique(std::stod(tokenString)); + if (token_type == TokenType::string_literal) + return std::make_unique(tokenString); + + // db column + if (token_type == TokenType::identifier) + return std::make_unique(tokenString); + + // null + if (token_type == TokenType::keyword_null) + return std::make_unique(); + + throw Exception("Unknown operand node " + tokenString); } RelationalOperatorType Parser::parse_relational_operator() {