support for functions in where clause

This commit is contained in:
VaclavT 2021-08-13 15:54:14 +02:00
parent e53d062ff5
commit ee0cbf64ff
3 changed files with 37 additions and 16 deletions

View File

@ -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

View File

@ -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')",

View File

@ -444,8 +444,9 @@ namespace usql {
std::unique_ptr<Node> 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<IntValueNode>(std::stoi(tokenString));
case TokenType::double_number:
return std::make_unique<DoubleValueNode>(std::stod(tokenString));
case TokenType::string_literal:
return std::make_unique<StringValueNode>(tokenString);
case TokenType::identifier:
return std::make_unique<DatabaseValueNode>(tokenString);
case TokenType::keyword_null:
return std::make_unique<NullValueNode>();
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<std::unique_ptr<Node>> 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<FunctionNode>(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<IntValueNode>(std::stoi(tokenString));
if (token_type == TokenType::double_number)
return std::make_unique<DoubleValueNode>(std::stod(tokenString));
if (token_type == TokenType::string_literal)
return std::make_unique<StringValueNode>(tokenString);
// db column
if (token_type == TokenType::identifier)
return std::make_unique<DatabaseValueNode>(tokenString);
// null
if (token_type == TokenType::keyword_null)
return std::make_unique<NullValueNode>();
throw Exception("Unknown operand node " + tokenString);
}
RelationalOperatorType Parser::parse_relational_operator() {