Skip to content

fix: mysql case when #317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/grammar/mysql/MySqlParser.g4
Original file line number Diff line number Diff line change
@@ -2779,8 +2779,8 @@ specificFunction
| KW_CONVERT '(' expression KW_USING charsetName ')' # dataTypeFunctionCall
| KW_CAST '(' expression KW_AS convertedDataType ')' # dataTypeFunctionCall
| KW_VALUES '(' columnName ')' # valuesFunctionCall
| KW_CASE expression caseFuncAlternative+ (KW_ELSE elseArg=functionArg)? KW_END # caseExpressionFunctionCall
| KW_CASE caseFuncAlternative+ (KW_ELSE elseArg=functionArg)? KW_END # caseFunctionCall
| KW_CASE expression caseFuncAlternative+ (KW_ELSE elseArg=functionArg)? KW_END # caseExpressionFunctionCall
| KW_CHAR '(' functionArgs (KW_USING charsetName)? ')' # charFunctionCall
| KW_POSITION '(' (positionString=stringLiteral | positionExpression=expression) KW_IN (
inString=stringLiteral
2 changes: 1 addition & 1 deletion src/lib/mysql/MySqlParser.interp

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions src/lib/mysql/MySqlParser.ts
Original file line number Diff line number Diff line change
@@ -43810,49 +43810,49 @@ export class MySqlParser extends SQLParserBase {
}
break;
case 7:
localContext = new CaseExpressionFunctionCallContext(localContext);
localContext = new CaseFunctionCallContext(localContext);
this.enterOuterAlt(localContext, 7);
{
this.state = 7424;
this.match(MySqlParser.KW_CASE);
this.state = 7425;
this.expression(0);
this.state = 7427;
this.state = 7426;
this.errorHandler.sync(this);
_la = this.tokenStream.LA(1);
do {
{
{
this.state = 7426;
this.state = 7425;
this.caseFuncAlternative();
}
}
this.state = 7429;
this.state = 7428;
this.errorHandler.sync(this);
_la = this.tokenStream.LA(1);
} while (_la === 191);
this.state = 7433;
this.state = 7432;
this.errorHandler.sync(this);
_la = this.tokenStream.LA(1);
if (_la === 53) {
{
this.state = 7431;
this.state = 7430;
this.match(MySqlParser.KW_ELSE);
this.state = 7432;
(localContext as CaseExpressionFunctionCallContext)._elseArg = this.functionArg();
this.state = 7431;
(localContext as CaseFunctionCallContext)._elseArg = this.functionArg();
}
}

this.state = 7435;
this.state = 7434;
this.match(MySqlParser.KW_END);
}
break;
case 8:
localContext = new CaseFunctionCallContext(localContext);
localContext = new CaseExpressionFunctionCallContext(localContext);
this.enterOuterAlt(localContext, 8);
{
this.state = 7437;
this.state = 7436;
this.match(MySqlParser.KW_CASE);
this.state = 7437;
this.expression(0);
this.state = 7439;
this.errorHandler.sync(this);
_la = this.tokenStream.LA(1);
@@ -43875,7 +43875,7 @@ export class MySqlParser extends SQLParserBase {
this.state = 7443;
this.match(MySqlParser.KW_ELSE);
this.state = 7444;
(localContext as CaseFunctionCallContext)._elseArg = this.functionArg();
(localContext as CaseExpressionFunctionCallContext)._elseArg = this.functionArg();
}
}

@@ -48262,8 +48262,8 @@ export class MySqlParser extends SQLParserBase {
7388,8,380,1,380,3,380,7391,8,380,1,381,1,381,1,381,3,381,7396,8,
381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,
1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,
1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,4,381,7428,
8,381,11,381,12,381,7429,1,381,1,381,3,381,7434,8,381,1,381,1,381,
1,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,4,381,7427,8,381,
11,381,12,381,7428,1,381,1,381,3,381,7433,8,381,1,381,1,381,1,381,
1,381,1,381,4,381,7440,8,381,11,381,12,381,7441,1,381,1,381,3,381,
7446,8,381,1,381,1,381,1,381,1,381,1,381,1,381,1,381,3,381,7455,
8,381,1,381,1,381,1,381,1,381,1,381,1,381,3,381,7463,8,381,1,381,
@@ -50909,11 +50909,11 @@ export class MySqlParser extends SQLParserBase {
7414,5,866,0,0,7414,7415,3,800,400,0,7415,7416,5,13,0,0,7416,7417,
3,726,363,0,7417,7418,5,867,0,0,7418,7572,1,0,0,0,7419,7420,5,189,
0,0,7420,7421,5,866,0,0,7421,7422,3,658,329,0,7422,7423,5,867,0,
0,7423,7572,1,0,0,0,7424,7425,5,23,0,0,7425,7427,3,800,400,0,7426,
7428,3,764,382,0,7427,7426,1,0,0,0,7428,7429,1,0,0,0,7429,7427,1,
0,0,0,7429,7430,1,0,0,0,7430,7433,1,0,0,0,7431,7432,5,53,0,0,7432,
7434,3,798,399,0,7433,7431,1,0,0,0,7433,7434,1,0,0,0,7434,7435,1,
0,0,0,7435,7436,5,378,0,0,7436,7572,1,0,0,0,7437,7439,5,23,0,0,7438,
0,7423,7572,1,0,0,0,7424,7426,5,23,0,0,7425,7427,3,764,382,0,7426,
7425,1,0,0,0,7427,7428,1,0,0,0,7428,7426,1,0,0,0,7428,7429,1,0,0,
0,7429,7432,1,0,0,0,7430,7431,5,53,0,0,7431,7433,3,798,399,0,7432,
7430,1,0,0,0,7432,7433,1,0,0,0,7433,7434,1,0,0,0,7434,7435,5,378,
0,0,7435,7572,1,0,0,0,7436,7437,5,23,0,0,7437,7439,3,800,400,0,7438,
7440,3,764,382,0,7439,7438,1,0,0,0,7440,7441,1,0,0,0,7441,7439,1,
0,0,0,7441,7442,1,0,0,0,7442,7445,1,0,0,0,7443,7444,5,53,0,0,7444,
7446,3,798,399,0,7445,7443,1,0,0,0,7445,7446,1,0,0,0,7446,7447,1,
@@ -50961,7 +50961,7 @@ export class MySqlParser extends SQLParserBase {
7568,3,288,144,0,7567,7566,1,0,0,0,7567,7568,1,0,0,0,7568,7569,1,
0,0,0,7569,7570,5,867,0,0,7570,7572,1,0,0,0,7571,7392,1,0,0,0,7571,
7397,1,0,0,0,7571,7398,1,0,0,0,7571,7405,1,0,0,0,7571,7412,1,0,0,
0,7571,7419,1,0,0,0,7571,7424,1,0,0,0,7571,7437,1,0,0,0,7571,7449,
0,7571,7419,1,0,0,0,7571,7424,1,0,0,0,7571,7436,1,0,0,0,7571,7449,
1,0,0,0,7571,7458,1,0,0,0,7571,7471,1,0,0,0,7571,7491,1,0,0,0,7571,
7505,1,0,0,0,7571,7518,1,0,0,0,7571,7537,1,0,0,0,7571,7547,1,0,0,
0,7571,7554,1,0,0,0,7572,763,1,0,0,0,7573,7574,5,191,0,0,7574,7575,
@@ -51211,7 +51211,7 @@ export class MySqlParser extends SQLParserBase {
7095,7098,7103,7106,7110,7115,7120,7125,7130,7133,7138,7143,7148,
7154,7159,7164,7169,7173,7176,7181,7185,7189,7197,7204,7208,7213,
7218,7222,7224,7227,7243,7253,7263,7272,7281,7288,7295,7303,7311,
7323,7330,7340,7345,7348,7353,7356,7378,7387,7390,7395,7429,7433,
7323,7330,7340,7345,7348,7353,7356,7378,7387,7390,7395,7428,7432,
7441,7445,7454,7462,7467,7475,7480,7485,7487,7496,7501,7509,7514,
7522,7530,7533,7543,7561,7564,7567,7571,7584,7592,7596,7601,7606,
7612,7617,7621,7626,7631,7636,7646,7649,7653,7657,7664,7668,7697,
18 changes: 9 additions & 9 deletions src/lib/mysql/MySqlParserListener.ts
Original file line number Diff line number Diff line change
@@ -605,8 +605,8 @@ import { SimpleFunctionCallContext } from "./MySqlParser.js";
import { CurrentUserContext } from "./MySqlParser.js";
import { DataTypeFunctionCallContext } from "./MySqlParser.js";
import { ValuesFunctionCallContext } from "./MySqlParser.js";
import { CaseExpressionFunctionCallContext } from "./MySqlParser.js";
import { CaseFunctionCallContext } from "./MySqlParser.js";
import { CaseExpressionFunctionCallContext } from "./MySqlParser.js";
import { CharFunctionCallContext } from "./MySqlParser.js";
import { PositionFunctionCallContext } from "./MySqlParser.js";
import { SubstrFunctionCallContext } from "./MySqlParser.js";
@@ -7159,29 +7159,29 @@ export class MySqlParserListener implements ParseTreeListener {
*/
exitValuesFunctionCall?: (ctx: ValuesFunctionCallContext) => void;
/**
* Enter a parse tree produced by the `caseExpressionFunctionCall`
* Enter a parse tree produced by the `caseFunctionCall`
* labeled alternative in `MySqlParser.specificFunction`.
* @param ctx the parse tree
*/
enterCaseExpressionFunctionCall?: (ctx: CaseExpressionFunctionCallContext) => void;
enterCaseFunctionCall?: (ctx: CaseFunctionCallContext) => void;
/**
* Exit a parse tree produced by the `caseExpressionFunctionCall`
* Exit a parse tree produced by the `caseFunctionCall`
* labeled alternative in `MySqlParser.specificFunction`.
* @param ctx the parse tree
*/
exitCaseExpressionFunctionCall?: (ctx: CaseExpressionFunctionCallContext) => void;
exitCaseFunctionCall?: (ctx: CaseFunctionCallContext) => void;
/**
* Enter a parse tree produced by the `caseFunctionCall`
* Enter a parse tree produced by the `caseExpressionFunctionCall`
* labeled alternative in `MySqlParser.specificFunction`.
* @param ctx the parse tree
*/
enterCaseFunctionCall?: (ctx: CaseFunctionCallContext) => void;
enterCaseExpressionFunctionCall?: (ctx: CaseExpressionFunctionCallContext) => void;
/**
* Exit a parse tree produced by the `caseFunctionCall`
* Exit a parse tree produced by the `caseExpressionFunctionCall`
* labeled alternative in `MySqlParser.specificFunction`.
* @param ctx the parse tree
*/
exitCaseFunctionCall?: (ctx: CaseFunctionCallContext) => void;
exitCaseExpressionFunctionCall?: (ctx: CaseExpressionFunctionCallContext) => void;
/**
* Enter a parse tree produced by the `charFunctionCall`
* labeled alternative in `MySqlParser.specificFunction`.
10 changes: 5 additions & 5 deletions src/lib/mysql/MySqlParserVisitor.ts
Original file line number Diff line number Diff line change
@@ -605,8 +605,8 @@ import { SimpleFunctionCallContext } from "./MySqlParser.js";
import { CurrentUserContext } from "./MySqlParser.js";
import { DataTypeFunctionCallContext } from "./MySqlParser.js";
import { ValuesFunctionCallContext } from "./MySqlParser.js";
import { CaseExpressionFunctionCallContext } from "./MySqlParser.js";
import { CaseFunctionCallContext } from "./MySqlParser.js";
import { CaseExpressionFunctionCallContext } from "./MySqlParser.js";
import { CharFunctionCallContext } from "./MySqlParser.js";
import { PositionFunctionCallContext } from "./MySqlParser.js";
import { SubstrFunctionCallContext } from "./MySqlParser.js";
@@ -4522,19 +4522,19 @@ export class MySqlParserVisitor<Result> extends AbstractParseTreeVisitor<Result>
*/
visitValuesFunctionCall?: (ctx: ValuesFunctionCallContext) => Result;
/**
* Visit a parse tree produced by the `caseExpressionFunctionCall`
* Visit a parse tree produced by the `caseFunctionCall`
* labeled alternative in `MySqlParser.specificFunction`.
* @param ctx the parse tree
* @return the visitor result
*/
visitCaseExpressionFunctionCall?: (ctx: CaseExpressionFunctionCallContext) => Result;
visitCaseFunctionCall?: (ctx: CaseFunctionCallContext) => Result;
/**
* Visit a parse tree produced by the `caseFunctionCall`
* Visit a parse tree produced by the `caseExpressionFunctionCall`
* labeled alternative in `MySqlParser.specificFunction`.
* @param ctx the parse tree
* @return the visitor result
*/
visitCaseFunctionCall?: (ctx: CaseFunctionCallContext) => Result;
visitCaseExpressionFunctionCall?: (ctx: CaseExpressionFunctionCallContext) => Result;
/**
* Visit a parse tree produced by the `charFunctionCall`
* labeled alternative in `MySqlParser.specificFunction`.
1 change: 1 addition & 0 deletions test/parser/mysql/syntax/dml.test.ts
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ const mysql = new MySQL();

const features = {
call: readSQL(__dirname, 'call.sql'),
case: readSQL(__dirname, 'case.sql'),
delete: readSQL(__dirname, 'delete.sql'),
do: readSQL(__dirname, 'do.sql'),
handler: readSQL(__dirname, 'handler.sql'),
63 changes: 63 additions & 0 deletions test/parser/mysql/syntax/fixtures/case.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
-- https://dev.mysql.com/doc/refman/5.7/en/case.html


/* CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE

or

CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list]
END CASE */


SELECT
id,
CASE
WHEN age = 18 THEN '成年'
WHEN age = 60 THEN '老年'
ELSE '未知'
END AS name
FROM people;

SELECT
id,
name,
score,
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
WHEN score >= 70 THEN 'C'
WHEN score >= 60 THEN 'D'
ELSE 'F'
END AS grade
FROM students;

SELECT
id,
name,
salary,
CASE salary
WHEN 1000 THEN 'Low'
WHEN 2000 THEN 'Medium'
WHEN 3000 THEN 'High'
ELSE 'Unknown'
END AS salary_grade
FROM employees;

SELECT
id,
name,
salary,
CASE
WHEN salary < 1000 THEN 'Low'
WHEN salary >= 1000 AND salary < 3000 THEN 'Medium'
WHEN salary >= 3000 THEN 'High'
ELSE 'Unknown'
END AS salary_grade
FROM employees;