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 <uval> import_file_type opt_join_type column_type
|
||||||
%type <table> from_clause table_ref table_ref_atomic table_ref_name
|
%type <table> from_clause table_ref table_ref_atomic table_ref_name
|
||||||
%type <table> join_clause join_table table_ref_name_no_alias
|
%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> column_name literal int_literal num_literal string_literal
|
||||||
%type <expr> comp_expr opt_where join_condition opt_having
|
%type <expr> comp_expr opt_where join_condition opt_having
|
||||||
%type <limit> opt_limit opt_top
|
%type <limit> opt_limit opt_top
|
||||||
|
@ -601,6 +601,12 @@ expr_alias:
|
||||||
;
|
;
|
||||||
|
|
||||||
expr:
|
expr:
|
||||||
|
operand
|
||||||
|
| between_expr
|
||||||
|
| logic_expr
|
||||||
|
;
|
||||||
|
|
||||||
|
operand:
|
||||||
'(' expr ')' { $$ = $2; }
|
'(' expr ')' { $$ = $2; }
|
||||||
| scalar_expr
|
| scalar_expr
|
||||||
| unary_expr
|
| unary_expr
|
||||||
|
@ -615,38 +621,44 @@ scalar_expr:
|
||||||
;
|
;
|
||||||
|
|
||||||
unary_expr:
|
unary_expr:
|
||||||
'-' expr { $$ = Expr::makeOpUnary(Expr::UMINUS, $2); }
|
'-' operand { $$ = Expr::makeOpUnary(Expr::UMINUS, $2); }
|
||||||
| NOT expr { $$ = Expr::makeOpUnary(Expr::NOT, $2); }
|
| NOT operand { $$ = Expr::makeOpUnary(Expr::NOT, $2); }
|
||||||
;
|
;
|
||||||
|
|
||||||
binary_expr:
|
binary_expr:
|
||||||
comp_expr
|
comp_expr
|
||||||
| expr '-' expr { $$ = Expr::makeOpBinary($1, '-', $3); }
|
| operand '-' operand { $$ = Expr::makeOpBinary($1, '-', $3); }
|
||||||
| expr '+' expr { $$ = Expr::makeOpBinary($1, '+', $3); }
|
| operand '+' operand { $$ = Expr::makeOpBinary($1, '+', $3); }
|
||||||
| expr '/' expr { $$ = Expr::makeOpBinary($1, '/', $3); }
|
| operand '/' operand { $$ = Expr::makeOpBinary($1, '/', $3); }
|
||||||
| expr '*' expr { $$ = Expr::makeOpBinary($1, '*', $3); }
|
| operand '*' operand { $$ = Expr::makeOpBinary($1, '*', $3); }
|
||||||
| expr '%' expr { $$ = Expr::makeOpBinary($1, '%', $3); }
|
| operand '%' operand { $$ = Expr::makeOpBinary($1, '%', $3); }
|
||||||
| expr '^' expr { $$ = Expr::makeOpBinary($1, '^', $3); }
|
| operand '^' operand { $$ = Expr::makeOpBinary($1, '^', $3); }
|
||||||
| expr AND expr { $$ = Expr::makeOpBinary($1, Expr::AND, $3); }
|
| operand LIKE operand { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); }
|
||||||
| expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); }
|
| operand NOT LIKE operand { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); }
|
||||||
| expr LIKE expr { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); }
|
|
||||||
| expr NOT LIKE expr { $$ = 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:
|
comp_expr:
|
||||||
expr '=' expr { $$ = Expr::makeOpBinary($1, '=', $3); }
|
operand '=' operand { $$ = Expr::makeOpBinary($1, '=', $3); }
|
||||||
| expr NOTEQUALS expr { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); }
|
| operand NOTEQUALS operand { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); }
|
||||||
| expr '<' expr { $$ = Expr::makeOpBinary($1, '<', $3); }
|
| operand '<' operand { $$ = Expr::makeOpBinary($1, '<', $3); }
|
||||||
| expr '>' expr { $$ = Expr::makeOpBinary($1, '>', $3); }
|
| operand '>' operand { $$ = Expr::makeOpBinary($1, '>', $3); }
|
||||||
| expr LESSEQ expr { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); }
|
| operand LESSEQ operand { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); }
|
||||||
| expr GREATEREQ expr { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); }
|
| operand GREATEREQ operand { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
function_expr:
|
function_expr:
|
||||||
IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); }
|
IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
between_expr:
|
||||||
|
operand BETWEEN operand AND operand { $$ = Expr::makeBetween($1, $3, $5); }
|
||||||
|
;
|
||||||
|
|
||||||
column_name:
|
column_name:
|
||||||
IDENTIFIER { $$ = Expr::makeColumnRef($1); }
|
IDENTIFIER { $$ = Expr::makeColumnRef($1); }
|
||||||
| IDENTIFIER '.' IDENTIFIER { $$ = Expr::makeColumnRef($1, $3); }
|
| IDENTIFIER '.' IDENTIFIER { $$ = Expr::makeColumnRef($1, $3); }
|
||||||
|
|
|
@ -47,6 +47,15 @@ namespace hsql {
|
||||||
return e;
|
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* Expr::makeLiteral(int64_t val) {
|
||||||
Expr* e = new Expr(kExprLiteralInt);
|
Expr* e = new Expr(kExprLiteralInt);
|
||||||
e->ival = val;
|
e->ival = val;
|
||||||
|
|
|
@ -32,9 +32,11 @@ namespace hsql {
|
||||||
// + - * / < > = %
|
// + - * / < > = %
|
||||||
// Non-trivial are: <> <= >= LIKE ISNULL NOT
|
// Non-trivial are: <> <= >= LIKE ISNULL NOT
|
||||||
enum OperatorType {
|
enum OperatorType {
|
||||||
SIMPLE_OP,
|
// Ternary operators
|
||||||
|
BETWEEN,
|
||||||
|
|
||||||
// Binary operators.
|
// Binary operators.
|
||||||
|
SIMPLE_OP,
|
||||||
NOT_EQUALS,
|
NOT_EQUALS,
|
||||||
LESS_EQ,
|
LESS_EQ,
|
||||||
GREATER_EQ,
|
GREATER_EQ,
|
||||||
|
@ -60,6 +62,7 @@ namespace hsql {
|
||||||
|
|
||||||
ExprType type;
|
ExprType type;
|
||||||
|
|
||||||
|
// TODO: Replace expressions by list.
|
||||||
Expr* expr;
|
Expr* expr;
|
||||||
Expr* expr2;
|
Expr* expr2;
|
||||||
std::vector<Expr*>* exprList;
|
std::vector<Expr*>* exprList;
|
||||||
|
@ -99,6 +102,8 @@ namespace hsql {
|
||||||
|
|
||||||
static Expr* makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2);
|
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(int64_t val);
|
||||||
|
|
||||||
static Expr* makeLiteral(double val);
|
static Expr* makeLiteral(double val);
|
||||||
|
|
|
@ -111,7 +111,6 @@ TEST(SelectGroupDistinctTest) {
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(OrderByTest) {
|
TEST(OrderByTest) {
|
||||||
TEST_PARSE_SINGLE_SQL(
|
TEST_PARSE_SINGLE_SQL(
|
||||||
"SELECT grade, city FROM students ORDER BY grade, city DESC;",
|
"SELECT grade, city FROM students ORDER BY grade, city DESC;",
|
||||||
|
@ -132,3 +131,29 @@ TEST(OrderByTest) {
|
||||||
|
|
||||||
delete result;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ SELECT * FROM (SELECT * FROM t1);
|
||||||
SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1;
|
SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1;
|
||||||
SELECT TOP 10 * FROM t1 ORDER BY col1, col2;
|
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 a, MAX(b), MAX(c, d), CUSTOM(q, UP(r)) AS f FROM t1;
|
||||||
|
SELECT * FROM t WHERE a BETWEEN 1 and c;
|
||||||
# JOIN
|
# 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 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;
|
SELECT * FROM t1 JOIN t2 ON c1 = c2;
|
||||||
|
|
Loading…
Reference in New Issue