Add select statement as possible operand in expressions

This commit is contained in:
Pedro 2017-03-07 14:21:45 +01:00
parent 35b8b569eb
commit cf1c84d46d
4 changed files with 46 additions and 6 deletions

View File

@ -612,6 +612,7 @@ operand:
| unary_expr | unary_expr
| binary_expr | binary_expr
| function_expr | function_expr
| '(' select_no_paren ')' { $$ = Expr::makeSelect($2); }
; ;
scalar_expr: scalar_expr:
@ -633,7 +634,7 @@ binary_expr:
| 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 LIKE operand { $$ = Expr::makeOpBinary($1, Expr::LIKE, $3); }
| operand NOT LIKE operand { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); } | operand NOT LIKE operand { $$ = Expr::makeOpBinary($1, Expr::NOT_LIKE, $4); }
; ;
@ -643,11 +644,11 @@ logic_expr:
; ;
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); }
| 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 LESSEQ operand { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); } | operand LESSEQ operand { $$ = Expr::makeOpBinary($1, Expr::LESS_EQ, $3); }
| operand GREATEREQ operand { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); } | operand GREATEREQ operand { $$ = Expr::makeOpBinary($1, Expr::GREATER_EQ, $3); }
; ;

View File

@ -102,6 +102,12 @@ namespace hsql {
return e; return e;
} }
Expr* Expr::makeSelect(SelectStatement* select) {
Expr* e = new Expr(kExprSelect);
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

@ -6,6 +6,7 @@
#include <vector> #include <vector>
namespace hsql { namespace hsql {
class SelectStatement;
// Helper function used by the lexer. // Helper function used by the lexer.
// TODO: move to more appropriate place. // TODO: move to more appropriate place.
@ -19,7 +20,8 @@ namespace hsql {
kExprPlaceholder, kExprPlaceholder,
kExprColumnRef, kExprColumnRef,
kExprFunctionRef, kExprFunctionRef,
kExprOperator kExprOperator,
kExprSelect
}; };
typedef struct Expr Expr; typedef struct Expr Expr;
@ -66,6 +68,7 @@ namespace hsql {
Expr* expr; Expr* expr;
Expr* expr2; Expr* expr2;
std::vector<Expr*>* exprList; std::vector<Expr*>* exprList;
SelectStatement* select;
char* name; char* name;
char* table; char* table;
char* alias; char* alias;
@ -77,6 +80,7 @@ namespace hsql {
char opChar; char opChar;
bool distinct; bool distinct;
// Convenience accessor methods. // Convenience accessor methods.
bool isType(ExprType e_type); bool isType(ExprType e_type);
@ -117,6 +121,8 @@ namespace hsql {
static Expr* makeFunctionRef(char* func_name, std::vector<Expr*>* exprList, bool distinct); static Expr* makeFunctionRef(char* func_name, std::vector<Expr*>* exprList, bool distinct);
static Expr* makePlaceholder(int id); static Expr* makePlaceholder(int id);
static Expr* makeSelect(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

@ -157,3 +157,30 @@ TEST(SelectBetweenTest) {
delete result; delete result;
} }
TEST(SelectConditionalSelectTest) {
TEST_PARSE_SINGLE_SQL(
"SELECT * FROM t WHERE a = (SELECT MIN(v) FROM tt);",
kStmtSelect,
SelectStatement,
result,
stmt);
Expr* where = stmt->whereClause;
ASSERT_NOTNULL(where);
ASSERT(where->isType(kExprOperator));
ASSERT(where->isSimpleOp('='));
ASSERT_NOTNULL(where->expr);
ASSERT_STREQ(where->expr->getName(), "a");
ASSERT(where->expr->isType(kExprColumnRef));
ASSERT_NOTNULL(where->expr2);
ASSERT(where->expr2->isType(kExprSelect));
SelectStatement* select2 = where->expr2->select;
ASSERT_NOTNULL(select2);
ASSERT_STREQ(select2->fromTable->getName(), "tt")
delete result;
}