implement EXISTS conditional
This commit is contained in:
parent
cf1c84d46d
commit
5605dbab7e
|
@ -195,7 +195,8 @@ 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 operand scalar_expr unary_expr binary_expr logic_expr function_expr between_expr star_expr expr_alias placeholder_expr
|
||||
%type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr
|
||||
%type <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
|
||||
|
@ -604,6 +605,7 @@ expr:
|
|||
operand
|
||||
| between_expr
|
||||
| logic_expr
|
||||
| exists_expr
|
||||
;
|
||||
|
||||
operand:
|
||||
|
@ -643,6 +645,10 @@ logic_expr:
|
|||
| expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); }
|
||||
;
|
||||
|
||||
exists_expr:
|
||||
EXISTS '(' select_no_paren ')' { $$ = Expr::makeExists($3); }
|
||||
;
|
||||
|
||||
comp_expr:
|
||||
operand '=' operand { $$ = Expr::makeOpBinary($1, '=', $3); }
|
||||
| operand NOTEQUALS operand { $$ = Expr::makeOpBinary($1, Expr::NOT_EQUALS, $3); }
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace hsql {
|
|||
Expr* Expr::makeBetween(Expr* expr, Expr* left, Expr* right) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->expr = expr;
|
||||
e->opType = BETWEEN;
|
||||
e->exprList = new std::vector<Expr*>();
|
||||
e->exprList->push_back(left);
|
||||
e->exprList->push_back(right);
|
||||
|
@ -108,6 +109,13 @@ namespace hsql {
|
|||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeExists(SelectStatement* select) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->opType = EXISTS;
|
||||
e->select = select;
|
||||
return e;
|
||||
}
|
||||
|
||||
bool Expr::isType(ExprType e_type) {
|
||||
return e_type == type;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace hsql {
|
|||
// + - * / < > = %
|
||||
// Non-trivial are: <> <= >= LIKE ISNULL NOT
|
||||
enum OperatorType {
|
||||
NONE,
|
||||
|
||||
// Ternary operators
|
||||
BETWEEN,
|
||||
|
||||
|
@ -50,7 +52,8 @@ namespace hsql {
|
|||
// Unary operators.
|
||||
NOT,
|
||||
UMINUS,
|
||||
ISNULL
|
||||
ISNULL,
|
||||
EXISTS
|
||||
};
|
||||
|
||||
|
||||
|
@ -123,6 +126,8 @@ namespace hsql {
|
|||
static Expr* makePlaceholder(int id);
|
||||
|
||||
static Expr* makeSelect(SelectStatement* select);
|
||||
|
||||
static Expr* makeExists(SelectStatement* select);
|
||||
};
|
||||
|
||||
// Zero initializes an Expr object and assigns it to a space in the heap
|
||||
|
|
|
@ -160,7 +160,7 @@ TEST(SelectBetweenTest) {
|
|||
|
||||
TEST(SelectConditionalSelectTest) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT * FROM t WHERE a = (SELECT MIN(v) FROM tt);",
|
||||
"SELECT * FROM t WHERE a = (SELECT MIN(v) FROM tt) AND EXISTS (SELECT * FROM test WHERE x < a);",
|
||||
kStmtSelect,
|
||||
SelectStatement,
|
||||
result,
|
||||
|
@ -169,18 +169,31 @@ TEST(SelectConditionalSelectTest) {
|
|||
Expr* where = stmt->whereClause;
|
||||
ASSERT_NOTNULL(where);
|
||||
ASSERT(where->isType(kExprOperator));
|
||||
ASSERT(where->isSimpleOp('='));
|
||||
ASSERT_EQ(where->opType, Expr::AND);
|
||||
|
||||
ASSERT_NOTNULL(where->expr);
|
||||
ASSERT_STREQ(where->expr->getName(), "a");
|
||||
ASSERT(where->expr->isType(kExprColumnRef));
|
||||
// a = (SELECT ...)
|
||||
Expr* cond1 = where->expr;
|
||||
ASSERT_NOTNULL(cond1);
|
||||
ASSERT_NOTNULL(cond1->expr);
|
||||
ASSERT(cond1->isSimpleOp('='));
|
||||
ASSERT_STREQ(cond1->expr->getName(), "a");
|
||||
ASSERT(cond1->expr->isType(kExprColumnRef));
|
||||
|
||||
ASSERT_NOTNULL(where->expr2);
|
||||
ASSERT(where->expr2->isType(kExprSelect));
|
||||
ASSERT_NOTNULL(cond1->expr2);
|
||||
ASSERT(cond1->expr2->isType(kExprSelect));
|
||||
|
||||
SelectStatement* select2 = where->expr2->select;
|
||||
SelectStatement* select2 = cond1->expr2->select;
|
||||
ASSERT_NOTNULL(select2);
|
||||
ASSERT_STREQ(select2->fromTable->getName(), "tt")
|
||||
|
||||
|
||||
// EXISTS (SELECT ...)
|
||||
Expr* cond2 = where->expr2;
|
||||
ASSERT_EQ(cond2->opType, Expr::EXISTS);
|
||||
ASSERT_NOTNULL(cond2->select);
|
||||
|
||||
SelectStatement* ex_select = cond2->select;
|
||||
ASSERT_STREQ(ex_select->fromTable->getName(), "test")
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue