implement EXISTS conditional

This commit is contained in:
Pedro 2017-03-07 14:37:05 +01:00
parent cf1c84d46d
commit 5605dbab7e
4 changed files with 42 additions and 10 deletions

View File

@ -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); }

View File

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

View File

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

View File

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