Merge master
This commit is contained in:
commit
1425deb75d
File diff suppressed because it is too large
Load Diff
|
@ -197,7 +197,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
|
|||
%type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr
|
||||
%type <expr> function_expr between_expr expr_alias param_expr
|
||||
%type <expr> column_name literal int_literal num_literal string_literal
|
||||
%type <expr> comp_expr opt_where join_condition opt_having case_expr in_expr hint
|
||||
%type <expr> comp_expr opt_where join_condition opt_having case_expr case_list in_expr hint
|
||||
%type <expr> array_expr array_index null_literal
|
||||
%type <limit> opt_limit opt_top
|
||||
%type <order> order_desc
|
||||
|
@ -793,11 +793,18 @@ in_expr:
|
|||
| operand NOT IN '(' select_no_paren ')' { $$ = Expr::makeOpUnary(kOpNot, Expr::makeInOperator($1, $5)); }
|
||||
;
|
||||
|
||||
// TODO: allow no else specified
|
||||
// CASE grammar based on: flex & bison by John Levine
|
||||
// https://www.safaribooksonline.com/library/view/flex-bison/9780596805418/ch04.html#id352665
|
||||
case_expr:
|
||||
CASE WHEN expr THEN operand END { $$ = Expr::makeCase($3, $5); }
|
||||
|
|
||||
CASE WHEN expr THEN operand ELSE operand END { $$ = Expr::makeCase($3, $5, $7); }
|
||||
CASE expr case_list END { $$ = Expr::makeCase($2, $3, nullptr); }
|
||||
| CASE expr case_list ELSE expr END { $$ = Expr::makeCase($2, $3, $5); }
|
||||
| CASE case_list END { $$ = Expr::makeCase(nullptr, $2, nullptr); }
|
||||
| CASE case_list ELSE expr END { $$ = Expr::makeCase(nullptr, $2, $4); }
|
||||
;
|
||||
|
||||
case_list:
|
||||
WHEN expr THEN expr { $$ = Expr::makeCaseList(Expr::makeCaseListElement($2, $4)); }
|
||||
| case_list WHEN expr THEN expr { $$ = Expr::caseListAppend($1, Expr::makeCaseListElement($3, $5)); }
|
||||
;
|
||||
|
||||
exists_expr:
|
||||
|
|
|
@ -68,22 +68,35 @@ namespace hsql {
|
|||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeCase(Expr* expr, Expr* then) {
|
||||
Expr* Expr::makeCaseList(Expr* caseListElement) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->expr = expr;
|
||||
e->opType = kOpCase;
|
||||
e->opType = kOpCaseList;
|
||||
e->exprList = new std::vector<Expr*>();
|
||||
e->exprList->push_back(then);
|
||||
e->exprList->push_back(caseListElement);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeCase(Expr* expr, Expr* then, Expr* other) {
|
||||
Expr* Expr::makeCaseListElement(Expr* when, Expr* then) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->opType = kOpCaseListElement;
|
||||
e->expr = when;
|
||||
e->expr2 = then;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::caseListAppend(Expr* caseList, Expr* caseListElement) {
|
||||
caseList->exprList->push_back(caseListElement);
|
||||
return caseList;
|
||||
}
|
||||
|
||||
Expr* Expr::makeCase(Expr* expr, Expr* caseList, Expr* elseExpr) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->expr = expr;
|
||||
e->opType = kOpCase;
|
||||
e->exprList = new std::vector<Expr*>();
|
||||
e->exprList->push_back(then);
|
||||
e->exprList->push_back(other);
|
||||
e->expr = expr;
|
||||
e->expr2 = elseExpr;
|
||||
e->exprList = caseList->exprList;
|
||||
caseList->exprList = nullptr;
|
||||
delete caseList;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,16 +25,22 @@ namespace hsql {
|
|||
kExprSelect,
|
||||
kExprHint,
|
||||
kExprArray,
|
||||
kExprArrayIndex
|
||||
kExprArrayIndex,
|
||||
kExprCaseList,
|
||||
kExprCaseListElement
|
||||
};
|
||||
|
||||
// Operator types. These are important for expressions of type kExprOperator.
|
||||
enum OperatorType {
|
||||
kOpNone,
|
||||
|
||||
// Ternary operators
|
||||
// Ternary operator
|
||||
kOpBetween,
|
||||
|
||||
// n-nary special case
|
||||
kOpCase,
|
||||
kOpCaseList, // Contains n >= 1 kExprCaseListElement in its exprList
|
||||
kOpCaseListElement, // `WHEN expr THEN expr`
|
||||
|
||||
// Binary operators.
|
||||
kOpPlus,
|
||||
|
@ -113,9 +119,13 @@ namespace hsql {
|
|||
|
||||
static Expr* makeBetween(Expr* expr, Expr* left, Expr* right);
|
||||
|
||||
static Expr* makeCase(Expr* expr, Expr* then);
|
||||
static Expr* makeCaseList(Expr* caseListElement);
|
||||
|
||||
static Expr* makeCase(Expr* expr, Expr* then, Expr* other);
|
||||
static Expr* makeCaseListElement(Expr* when, Expr* then);
|
||||
|
||||
static Expr* caseListAppend(Expr* caseList, Expr* caseListElement);
|
||||
|
||||
static Expr* makeCase(Expr* expr, Expr* when, Expr* elseExpr);
|
||||
|
||||
static Expr* makeLiteral(int64_t val);
|
||||
|
||||
|
|
|
@ -214,9 +214,74 @@ TEST(SelectCaseWhen) {
|
|||
ASSERT_NOTNULL(caseExpr);
|
||||
ASSERT(caseExpr->isType(kExprOperator));
|
||||
ASSERT_EQ(caseExpr->opType, kOpCase);
|
||||
ASSERT(caseExpr->expr->isType(kExprOperator));
|
||||
ASSERT_EQ(caseExpr->expr->opType, kOpEquals);
|
||||
ASSERT_NULL(caseExpr->expr);
|
||||
ASSERT_NOTNULL(caseExpr->exprList);
|
||||
ASSERT_NOTNULL(caseExpr->expr2);
|
||||
ASSERT_EQ(caseExpr->exprList->size(), 1);
|
||||
ASSERT(caseExpr->expr2->isType(kExprLiteralInt));
|
||||
|
||||
Expr* whenExpr = caseExpr->exprList->at(0);
|
||||
ASSERT(whenExpr->expr->isType(kExprOperator));
|
||||
ASSERT_EQ(whenExpr->expr->opType, kOpEquals);
|
||||
ASSERT(whenExpr->expr->expr->isType(kExprColumnRef));
|
||||
ASSERT(whenExpr->expr->expr2->isType(kExprLiteralString));
|
||||
}
|
||||
|
||||
TEST(SelectCaseWhenWhen) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT CASE WHEN x = 1 THEN 1 WHEN 1.25 < x THEN 2 END FROM test;",
|
||||
kStmtSelect,
|
||||
SelectStatement,
|
||||
result,
|
||||
stmt);
|
||||
|
||||
ASSERT_EQ(stmt->selectList->size(), 1);
|
||||
Expr* caseExpr = stmt->selectList->at(0);
|
||||
ASSERT_NOTNULL(caseExpr);
|
||||
ASSERT(caseExpr->isType(kExprOperator));
|
||||
ASSERT_EQ(caseExpr->opType, kOpCase);
|
||||
// CASE [expr] [exprList] [expr2]
|
||||
// [expr] [expr]
|
||||
// [expr] [expr2] [expr] [expr2]
|
||||
// CASE (null) WHEN X = 1 THEN 1 WHEN 1.25 < x THEN 2 (null)
|
||||
ASSERT_NULL(caseExpr->expr);
|
||||
ASSERT_NOTNULL(caseExpr->exprList);
|
||||
ASSERT_NULL(caseExpr->expr2);
|
||||
ASSERT_EQ(caseExpr->exprList->size(), 2);
|
||||
|
||||
Expr* whenExpr = caseExpr->exprList->at(0);
|
||||
ASSERT_EQ(whenExpr->expr->opType, kOpEquals);
|
||||
ASSERT(whenExpr->expr->expr->isType(kExprColumnRef));
|
||||
ASSERT(whenExpr->expr->expr2->isType(kExprLiteralInt));
|
||||
|
||||
Expr* whenExpr2 = caseExpr->exprList->at(1);
|
||||
ASSERT_EQ(whenExpr2->expr->opType, kOpLess);
|
||||
ASSERT(whenExpr2->expr->expr->isType(kExprLiteralFloat));
|
||||
ASSERT(whenExpr2->expr->expr2->isType(kExprColumnRef));
|
||||
}
|
||||
|
||||
TEST(SelectCaseValueWhenWhenElse) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT CASE x WHEN 1 THEN 0 WHEN 2 THEN 3 WHEN 8 THEN 7 ELSE 4 END FROM test;",
|
||||
kStmtSelect,
|
||||
SelectStatement,
|
||||
result,
|
||||
stmt);
|
||||
|
||||
ASSERT_EQ(stmt->selectList->size(), 1);
|
||||
Expr* caseExpr = stmt->selectList->at(0);
|
||||
ASSERT_NOTNULL(caseExpr);
|
||||
ASSERT(caseExpr->isType(kExprOperator));
|
||||
ASSERT_EQ(caseExpr->opType, kOpCase);
|
||||
ASSERT_NOTNULL(caseExpr->expr);
|
||||
ASSERT_NOTNULL(caseExpr->exprList);
|
||||
ASSERT_NOTNULL(caseExpr->expr2);
|
||||
ASSERT_EQ(caseExpr->exprList->size(), 3);
|
||||
ASSERT(caseExpr->expr->isType(kExprColumnRef));
|
||||
|
||||
Expr* whenExpr = caseExpr->exprList->at(2);
|
||||
ASSERT(whenExpr->expr->isType(kExprLiteralInt));
|
||||
ASSERT_EQ(whenExpr->expr2->ival, 7);
|
||||
}
|
||||
|
||||
TEST(SelectJoin) {
|
||||
|
|
Loading…
Reference in New Issue