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
| binary_expr
| function_expr
| '(' select_no_paren ')' { $$ = Expr::makeSelect($2); }
;
scalar_expr:

View File

@ -102,6 +102,12 @@ namespace hsql {
return e;
}
Expr* Expr::makeSelect(SelectStatement* select) {
Expr* e = new Expr(kExprSelect);
e->select = select;
return e;
}
bool Expr::isType(ExprType e_type) {
return e_type == type;
}

View File

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

View File

@ -157,3 +157,30 @@ TEST(SelectBetweenTest) {
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;
}