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