implement CASE WHEN expressions
This commit is contained in:
parent
5605dbab7e
commit
b7828e698e
|
@ -169,12 +169,11 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch
|
|||
%token INSERT ISNULL OFFSET RENAME SCHEMA SELECT SORTED
|
||||
%token TABLES UNIQUE UNLOAD UPDATE VALUES AFTER ALTER CROSS
|
||||
%token DELTA GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER
|
||||
%token OUTER RIGHT TABLE UNION USING WHERE CALL DATE DESC
|
||||
%token DROP FILE FROM FULL HASH HINT INTO JOIN LEFT LIKE
|
||||
%token LOAD NULL PART PLAN SHOW TEXT TIME VIEW WITH ADD ALL
|
||||
%token AND ASC CSV FOR INT KEY NOT OFF SET TBL TOP AS BY IF
|
||||
%token IN IS OF ON OR TO
|
||||
|
||||
%token OUTER RIGHT TABLE UNION USING WHERE CALL CASE DATE
|
||||
%token DESC DROP ELSE FILE FROM FULL HASH HINT INTO JOIN
|
||||
%token LEFT LIKE LOAD NULL PART PLAN SHOW TEXT THEN TIME
|
||||
%token VIEW WHEN WITH ADD ALL AND ASC CSV END FOR INT KEY
|
||||
%token NOT OFF SET TBL TOP AS BY IF IN IS OF ON OR TO
|
||||
|
||||
/*********************************
|
||||
** Non-Terminal types (http://www.gnu.org/software/bison/manual/html_node/Type-Decl.html)
|
||||
|
@ -198,7 +197,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch
|
|||
%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> comp_expr opt_where join_condition opt_having
|
||||
%type <expr> comp_expr opt_where join_condition opt_having case_expr
|
||||
%type <limit> opt_limit opt_top
|
||||
%type <order> order_desc
|
||||
%type <order_type> opt_order_type
|
||||
|
@ -606,6 +605,7 @@ expr:
|
|||
| between_expr
|
||||
| logic_expr
|
||||
| exists_expr
|
||||
| case_expr
|
||||
;
|
||||
|
||||
operand:
|
||||
|
@ -645,6 +645,11 @@ logic_expr:
|
|||
| expr OR expr { $$ = Expr::makeOpBinary($1, Expr::OR, $3); }
|
||||
;
|
||||
|
||||
// TODO: allow no else specified
|
||||
case_expr:
|
||||
CASE WHEN operand THEN operand ELSE operand END { $$ = Expr::makeCase($3, $5, $7); }
|
||||
;
|
||||
|
||||
exists_expr:
|
||||
EXISTS '(' select_no_paren ')' { $$ = Expr::makeExists($3); }
|
||||
;
|
||||
|
|
|
@ -54,11 +54,8 @@
|
|||
<COMMENT>[^\n]* /* skipping comment content until a end of line is read */;
|
||||
<COMMENT>\n BEGIN(INITIAL);
|
||||
|
||||
|
||||
[ \t\n]+ /* skip whitespace */;
|
||||
|
||||
|
||||
|
||||
DEALLOCATE TOKEN(DEALLOCATE)
|
||||
PARAMETERS TOKEN(PARAMETERS)
|
||||
INTERSECT TOKEN(INTERSECT)
|
||||
|
@ -127,9 +124,11 @@ UNION TOKEN(UNION)
|
|||
USING TOKEN(USING)
|
||||
WHERE TOKEN(WHERE)
|
||||
CALL TOKEN(CALL)
|
||||
CASE TOKEN(CASE)
|
||||
DATE TOKEN(DATE)
|
||||
DESC TOKEN(DESC)
|
||||
DROP TOKEN(DROP)
|
||||
ELSE TOKEN(ELSE)
|
||||
FILE TOKEN(FILE)
|
||||
FROM TOKEN(FROM)
|
||||
FULL TOKEN(FULL)
|
||||
|
@ -145,14 +144,17 @@ PART TOKEN(PART)
|
|||
PLAN TOKEN(PLAN)
|
||||
SHOW TOKEN(SHOW)
|
||||
TEXT TOKEN(TEXT)
|
||||
THEN TOKEN(THEN)
|
||||
TIME TOKEN(TIME)
|
||||
VIEW TOKEN(VIEW)
|
||||
WHEN TOKEN(WHEN)
|
||||
WITH TOKEN(WITH)
|
||||
ADD TOKEN(ADD)
|
||||
ALL TOKEN(ALL)
|
||||
AND TOKEN(AND)
|
||||
ASC TOKEN(ASC)
|
||||
CSV TOKEN(CSV)
|
||||
END TOKEN(END)
|
||||
FOR TOKEN(FOR)
|
||||
INT TOKEN(INT)
|
||||
KEY TOKEN(KEY)
|
||||
|
@ -171,15 +173,12 @@ ON TOKEN(ON)
|
|||
OR TOKEN(OR)
|
||||
TO TOKEN(TO)
|
||||
|
||||
|
||||
"<>" TOKEN(NOTEQUALS)
|
||||
"<=" TOKEN(LESSEQ)
|
||||
">=" TOKEN(GREATEREQ)
|
||||
|
||||
|
||||
[-+*/(){},.;<>=^%:?] { return yytext[0]; }
|
||||
|
||||
|
||||
[0-9]+"."[0-9]* |
|
||||
"."[0-9]* {
|
||||
yylval->fval = atof(yytext);
|
||||
|
@ -202,7 +201,6 @@ TO TOKEN(TO)
|
|||
return SQL_IDENTIFIER;
|
||||
}
|
||||
|
||||
|
||||
'[^'\n]*' {
|
||||
// Crop the leading and trailing quote char
|
||||
yylval->sval = hsql::substr(yytext, 1, strlen(yytext)-1);
|
||||
|
|
|
@ -140,6 +140,11 @@ IS
|
|||
ISNULL
|
||||
BETWEEN
|
||||
ESCAPE
|
||||
CASE
|
||||
WHEN
|
||||
THEN
|
||||
ELSE
|
||||
END
|
||||
|
||||
// With
|
||||
WITH
|
||||
|
|
|
@ -57,6 +57,16 @@ namespace hsql {
|
|||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeCase(Expr* expr, Expr* then, Expr* other) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->expr = expr;
|
||||
e->opType = CASE;
|
||||
e->exprList = new std::vector<Expr*>();
|
||||
e->exprList->push_back(then);
|
||||
e->exprList->push_back(other);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeLiteral(int64_t val) {
|
||||
Expr* e = new Expr(kExprLiteralInt);
|
||||
e->ival = val;
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace hsql {
|
|||
|
||||
// Ternary operators
|
||||
BETWEEN,
|
||||
CASE,
|
||||
|
||||
// Binary operators.
|
||||
SIMPLE_OP,
|
||||
|
@ -111,6 +112,8 @@ namespace hsql {
|
|||
|
||||
static Expr* makeBetween(Expr* expr, Expr* left, Expr* right);
|
||||
|
||||
static Expr* makeCase(Expr* expr, Expr* then, Expr* other);
|
||||
|
||||
static Expr* makeLiteral(int64_t val);
|
||||
|
||||
static Expr* makeLiteral(double val);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||
SELECT O_YEAR, SUM(CASE WHEN NATION = 'BRAZIL' THEN VOLUME ELSE 0 END)/SUM(VOLUME) AS MKT_SHARE
|
||||
FROM (SELECT datepart(yy,O_ORDERDATE) AS O_YEAR, L_EXTENDEDPRICE*(1-L_DISCOUNT) AS VOLUME, N2.N_NAME AS NATION
|
||||
FROM PART, SUPPLIER, LINEITEM, ORDERS, CUSTOMER, NATION N1, NATION N2, REGION
|
||||
FROM "PART", SUPPLIER, LINEITEM, ORDERS, CUSTOMER, NATION N1, NATION N2, REGION
|
||||
WHERE P_PARTKEY = L_PARTKEY AND S_SUPPKEY = L_SUPPKEY AND L_ORDERKEY = O_ORDERKEY
|
||||
AND O_CUSTKEY = C_CUSTKEY AND C_NATIONKEY = N1.N_NATIONKEY AND
|
||||
N1.N_REGIONKEY = R_REGIONKEY AND R_NAME = 'AMERICA' AND S_NATIONKEY = N2.N_NATIONKEY
|
||||
|
|
|
@ -184,7 +184,7 @@ TEST(SelectConditionalSelectTest) {
|
|||
|
||||
SelectStatement* select2 = cond1->expr2->select;
|
||||
ASSERT_NOTNULL(select2);
|
||||
ASSERT_STREQ(select2->fromTable->getName(), "tt")
|
||||
ASSERT_STREQ(select2->fromTable->getName(), "tt");
|
||||
|
||||
|
||||
// EXISTS (SELECT ...)
|
||||
|
@ -193,7 +193,33 @@ TEST(SelectConditionalSelectTest) {
|
|||
ASSERT_NOTNULL(cond2->select);
|
||||
|
||||
SelectStatement* ex_select = cond2->select;
|
||||
ASSERT_STREQ(ex_select->fromTable->getName(), "test")
|
||||
ASSERT_STREQ(ex_select->fromTable->getName(), "test");
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
||||
TEST(SelectCaseWhen) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT MAX(CASE WHEN a = 'foo' THEN x ELSE 0 END) FROM test;",
|
||||
kStmtSelect,
|
||||
SelectStatement,
|
||||
result,
|
||||
stmt);
|
||||
|
||||
ASSERT_EQ(stmt->selectList->size(), 1);
|
||||
Expr* func = stmt->selectList->at(0);
|
||||
|
||||
ASSERT_NOTNULL(func);
|
||||
ASSERT(func->isType(kExprFunctionRef));
|
||||
ASSERT_EQ(func->exprList->size(), 1);
|
||||
|
||||
Expr* caseExpr = func->exprList->at(0);
|
||||
ASSERT_NOTNULL(caseExpr);
|
||||
ASSERT(caseExpr->isType(kExprOperator));
|
||||
ASSERT_EQ(caseExpr->opType, Expr::CASE);
|
||||
ASSERT(caseExpr->expr->isType(kExprOperator));
|
||||
ASSERT(caseExpr->expr->isSimpleOp('='));
|
||||
ASSERT_EQ(caseExpr->exprList->size(), 2);
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue