Implement BETWEEN operator
This commit is contained in:
parent
9ecfa8e8f6
commit
35b8b569eb
|
@ -195,7 +195,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch
|
|||
%type <uval> import_file_type opt_join_type column_type
|
||||
%type <table> from_clause table_ref table_ref_atomic table_ref_name
|
||||
%type <table> join_clause join_table table_ref_name_no_alias
|
||||
%type <expr> expr scalar_expr unary_expr binary_expr function_expr star_expr expr_alias placeholder_expr
|
||||
%type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr function_expr between_expr star_expr expr_alias placeholder_expr
|
||||
%type <expr> column_name literal int_literal num_literal string_literal
|
||||
%type <expr> comp_expr opt_where join_condition opt_having
|
||||
%type <limit> opt_limit opt_top
|
||||
|
@ -601,6 +601,12 @@ expr_alias:
|
|||
;
|
||||
|
||||
expr:
|
||||
operand
|
||||
| between_expr
|
||||
| logic_expr
|
||||
;
|
||||
|
||||
operand:
|
||||
'(' expr ')' { $$ = $2; }
|
||||
| scalar_expr
|
||||
| unary_expr
|
||||
|
@ -615,38 +621,44 @@ scalar_expr:
|
|||
;
|
||||
|
||||
unary_expr:
|
||||
'-' expr { $$ = Expr::makeOpUnary(Expr::UMINUS, $2); }
|
||||
| NOT expr { $$ = Expr::makeOpUnary(Expr::NOT, $2); }
|
||||
'-' operand { $$ = Expr::makeOpUnary(Expr::UMINUS, $2); }
|
||||
| NOT operand { $$ = Expr::makeOpUnary(Expr::NOT, $2); }
|
||||
;
|
||||
|
||||
binary_expr:
|
||||
comp_expr
|
||||
| expr '-' expr { $$ = Expr::makeOpBinary($1, '-', $3); }
|
||||
| expr '+' expr { $$ = Expr::makeOpBinary($1, '+', $3); }
|
||||
| expr '/' expr { $$ = Expr::makeOpBinary($1, '/', $3); }
|
||||
| expr '*' expr { $$ = Expr::makeOpBinary($1, '*', $3); }
|
||||
| expr '%' expr { $$ = Expr::makeOpBinary($1, '%', $3); }
|
||||
| expr '^' expr { $$ = Expr::makeOpBinary($1, '^', $3); }
|
||||
| expr AND expr { $$ = Expr::makeOpBinary($1, Expr::AND, $3); }
|
||||
| expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); }
|
||||
| expr LIKE expr { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); }
|
||||
| expr NOT LIKE expr { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); }
|
||||
| operand '-' operand { $$ = Expr::makeOpBinary($1, '-', $3); }
|
||||
| operand '+' operand { $$ = Expr::makeOpBinary($1, '+', $3); }
|
||||
| operand '/' operand { $$ = Expr::makeOpBinary($1, '/', $3); }
|
||||
| operand '*' operand { $$ = Expr::makeOpBinary($1, '*', $3); }
|
||||
| operand '%' operand { $$ = Expr::makeOpBinary($1, '%', $3); }
|
||||
| operand '^' operand { $$ = Expr::makeOpBinary($1, '^', $3); }
|
||||
| operand LIKE operand { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); }
|
||||
| operand NOT LIKE operand { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); }
|
||||
;
|
||||
|
||||
logic_expr:
|
||||
expr AND expr { $$ = Expr::makeOpBinary($1, Expr::AND, $3); }
|
||||
| expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); }
|
||||
;
|
||||
|
||||
comp_expr:
|
||||
expr '=' expr { $$ = Expr::makeOpBinary($1, '=', $3); }
|
||||
| expr NOTEQUALS expr { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); }
|
||||
| expr '<' expr { $$ = Expr::makeOpBinary($1, '<', $3); }
|
||||
| expr '>' expr { $$ = Expr::makeOpBinary($1, '>', $3); }
|
||||
| expr LESSEQ expr { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); }
|
||||
| expr GREATEREQ expr { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); }
|
||||
operand '=' operand { $$ = Expr::makeOpBinary($1, '=', $3); }
|
||||
| operand NOTEQUALS operand { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); }
|
||||
| operand '<' operand { $$ = Expr::makeOpBinary($1, '<', $3); }
|
||||
| operand '>' operand { $$ = Expr::makeOpBinary($1, '>', $3); }
|
||||
| operand LESSEQ operand { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); }
|
||||
| operand GREATEREQ operand { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); }
|
||||
;
|
||||
|
||||
function_expr:
|
||||
IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); }
|
||||
;
|
||||
|
||||
between_expr:
|
||||
operand BETWEEN operand AND operand { $$ = Expr::makeBetween($1, $3, $5); }
|
||||
;
|
||||
|
||||
column_name:
|
||||
IDENTIFIER { $$ = Expr::makeColumnRef($1); }
|
||||
| IDENTIFIER '.' IDENTIFIER { $$ = Expr::makeColumnRef($1, $3); }
|
||||
|
|
|
@ -47,6 +47,15 @@ namespace hsql {
|
|||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeBetween(Expr* expr, Expr* left, Expr* right) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->expr = expr;
|
||||
e->exprList = new std::vector<Expr*>();
|
||||
e->exprList->push_back(left);
|
||||
e->exprList->push_back(right);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeLiteral(int64_t val) {
|
||||
Expr* e = new Expr(kExprLiteralInt);
|
||||
e->ival = val;
|
||||
|
|
|
@ -32,9 +32,11 @@ namespace hsql {
|
|||
// + - * / < > = %
|
||||
// Non-trivial are: <> <= >= LIKE ISNULL NOT
|
||||
enum OperatorType {
|
||||
SIMPLE_OP,
|
||||
// Ternary operators
|
||||
BETWEEN,
|
||||
|
||||
// Binary operators.
|
||||
SIMPLE_OP,
|
||||
NOT_EQUALS,
|
||||
LESS_EQ,
|
||||
GREATER_EQ,
|
||||
|
@ -60,6 +62,7 @@ namespace hsql {
|
|||
|
||||
ExprType type;
|
||||
|
||||
// TODO: Replace expressions by list.
|
||||
Expr* expr;
|
||||
Expr* expr2;
|
||||
std::vector<Expr*>* exprList;
|
||||
|
@ -99,6 +102,8 @@ namespace hsql {
|
|||
|
||||
static Expr* makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2);
|
||||
|
||||
static Expr* makeBetween(Expr* expr, Expr* left, Expr* right);
|
||||
|
||||
static Expr* makeLiteral(int64_t val);
|
||||
|
||||
static Expr* makeLiteral(double val);
|
||||
|
|
|
@ -111,7 +111,6 @@ TEST(SelectGroupDistinctTest) {
|
|||
delete result;
|
||||
}
|
||||
|
||||
|
||||
TEST(OrderByTest) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT grade, city FROM students ORDER BY grade, city DESC;",
|
||||
|
@ -132,3 +131,29 @@ TEST(OrderByTest) {
|
|||
|
||||
delete result;
|
||||
}
|
||||
|
||||
TEST(SelectBetweenTest) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT grade, city FROM students WHERE grade BETWEEN 1 and c;",
|
||||
kStmtSelect,
|
||||
SelectStatement,
|
||||
result,
|
||||
stmt);
|
||||
|
||||
|
||||
Expr* where = stmt->whereClause;
|
||||
ASSERT_NOTNULL(where);
|
||||
ASSERT(where->isType(kExprOperator));
|
||||
ASSERT_EQ(where->opType, Expr::BETWEEN);
|
||||
|
||||
ASSERT_STREQ(where->expr->getName(), "grade");
|
||||
ASSERT(where->expr->isType(kExprColumnRef));
|
||||
|
||||
ASSERT_EQ(where->exprList->size(), 2);
|
||||
ASSERT(where->exprList->at(0)->isType(kExprLiteralInt));
|
||||
ASSERT_EQ(where->exprList->at(0)->ival, 1);
|
||||
ASSERT(where->exprList->at(1)->isType(kExprColumnRef));
|
||||
ASSERT_STREQ(where->exprList->at(1)->getName(), "c");
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ TEST(TPCHQueryTests) {
|
|||
for (const std::string& file_path : files) {
|
||||
std::ifstream t(file_path.c_str());
|
||||
std::string query((std::istreambuf_iterator<char>(t)),
|
||||
std::istreambuf_iterator<char>());
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
SQLParserResult* result = SQLParser::parseSQLString(query.c_str());
|
||||
if (!result->isValid()) {
|
||||
|
|
|
@ -10,6 +10,7 @@ SELECT * FROM (SELECT * FROM t1);
|
|||
SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1;
|
||||
SELECT TOP 10 * FROM t1 ORDER BY col1, col2;
|
||||
SELECT a, MAX(b), MAX(c, d), CUSTOM(q, UP(r)) AS f FROM t1;
|
||||
SELECT * FROM t WHERE a BETWEEN 1 and c;
|
||||
# JOIN
|
||||
SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5
|
||||
SELECT * FROM t1 JOIN t2 ON c1 = c2;
|
||||
|
|
Loading…
Reference in New Issue