Skip to content

Commit c074a21

Browse files
Separate MySQL Special String Functions accepting Named Argument Separation as this could collide with ComplexExpressionList when InExpression is involved (#1285)
Fixes #1284 Co-authored-by: Tobias <t.warneke@gmx.net>
1 parent f7f7bcd commit c074a21

File tree

4 files changed

+55
-9
lines changed

4 files changed

+55
-9
lines changed

src/main/java/net/sf/jsqlparser/expression/Function.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public void setName(String string) {
5252
nameparts = Arrays.asList(string);
5353
}
5454

55+
public Function withName(String name) {
56+
this.setName(name);
57+
return this;
58+
}
59+
5560
public void setName(List<String> string) {
5661
nameparts = string;
5762
}

src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public static Expression parseExpression(String expression, boolean allowPartial
120120
consumer.accept(parser);
121121
}
122122
try {
123-
Expression expr = parser.SimpleExpression();
123+
Expression expr = parser.Expression();
124124
if (!allowPartialParse && parser.getNextToken().kind != CCJSqlParserTokenManager.EOF) {
125125
throw new JSQLParserException("could only parse partial expression " + expr.toString());
126126
}

src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
382382
| <K_SQL_NO_CACHE: "SQL_NO_CACHE">
383383
| <K_USING:"USING">
384384
| <K_SIGNED:"SIGNED">
385+
| <K_STRING_FUNCTION_NAME: ("SUBSTR" | "SUBSTRING" | "TRIM" | "POSITION" | "OVERLAY")>
385386
| <K_UNSIGNED:"UNSIGNED">
386387
| <K_VALIDATE : "VALIDATE">
387388
| <K_VALUE:"VALUE">
@@ -1519,6 +1520,7 @@ String RelObjectNameWithoutValue() :
15191520
/*| tk=<K_PLACING> | tk=<K_BOTH> | tk=<K_LEADING> | tk=<K_TRAILING> */
15201521
| tk=<K_FORMAT> | tk=<K_DIV> | tk=<K_UNSIGNED> | tk=<K_CASE> | tk=<K_LOCAL>
15211522
| tk=<K_ARRAY_LITERAL>
1523+
| tk=<K_STRING_FUNCTION_NAME>
15221524
| tk=<K_USER>
15231525

15241526
/* Keywords for ALTER SESSION */
@@ -1536,7 +1538,7 @@ String RelObjectName() :
15361538
{
15371539
(result = RelObjectNameWithoutValue()
15381540
| tk=<K_GROUP> | tk=<K_INTERVAL> | tk=<K_ON> | tk=<K_ORDER> | tk=<K_START> | tk=<K_TOP> | tk=<K_VALUE>
1539-
| tk=<K_VALUES> | tk=<K_CREATE> | tk=<K_TABLES> )
1541+
| tk=<K_VALUES> | tk=<K_CREATE> | tk=<K_TABLES> )
15401542

15411543
{
15421544
if (tk!=null) result=tk.image;
@@ -1566,7 +1568,7 @@ String RelObjectNameExt():
15661568
{
15671569
( result=RelObjectName() | tk=<K_ALL> | tk=<K_ANY> | tk=<K_SOME> | tk=<K_LEFT> | tk=<K_RIGHT> | tk=<K_SET>
15681570
| tk=<K_DOUBLE> | tk=<K_IF> | tk=<K_IIF> | tk=<K_OPTIMIZE> | tk=<K_LIMIT>
1569-
| tk=<K_OFFSET> | tk=<K_PROCEDURE> | tk=<K_PUBLIC>
1571+
| tk=<K_OFFSET> | tk=<K_PROCEDURE> | tk=<K_PUBLIC>
15701572
| tk=<K_CASEWHEN> | tk=<K_IN> )
15711573
{
15721574
if (tk!=null) result=tk.image;
@@ -4282,6 +4284,7 @@ Function Function() #Function:
42824284
{
42834285
(
42844286
"{" <K_FN> { retval.setEscaped(true); } InternalFunction(retval) "}"
4287+
| LOOKAHEAD(3) retval = SpecialStringFunctionWithNamedParameters()
42854288
| InternalFunction(retval)
42864289
)
42874290
{
@@ -4290,6 +4293,33 @@ Function Function() #Function:
42904293
}
42914294
}
42924295

4296+
Function SpecialStringFunctionWithNamedParameters() :
4297+
{
4298+
Token funcName;
4299+
NamedExpressionList namedExpressionList = null;
4300+
ExpressionList expressionList = null;
4301+
List<OrderByElement> orderByList;
4302+
}
4303+
{
4304+
funcName = <K_STRING_FUNCTION_NAME>
4305+
4306+
"("
4307+
(
4308+
LOOKAHEAD(NamedExpressionList1()) namedExpressionList=NamedExpressionList1()
4309+
|
4310+
LOOKAHEAD(NamedExpressionListExprFirst(), { getAsBoolean(Feature.allowComplexParsing) }) namedExpressionList = NamedExpressionListExprFirst()
4311+
|
4312+
LOOKAHEAD(3, { getAsBoolean(Feature.allowComplexParsing) }) expressionList=ComplexExpressionList() {expressionList.setUsingBrackets(false);}
4313+
|
4314+
LOOKAHEAD(3) expressionList=SimpleExpressionList(false)
4315+
)
4316+
")"
4317+
4318+
{
4319+
return new Function().withName(funcName.image).withNamedParameters(namedExpressionList).withParameters(expressionList);
4320+
}
4321+
}
4322+
42934323
Function InternalFunction(Function retval) :
42944324
{
42954325
List<String> funcName;
@@ -4312,10 +4342,6 @@ Function InternalFunction(Function retval) :
43124342
( LOOKAHEAD(4)
43134343
"*" { retval.setAllColumns(true); }
43144344
|
4315-
LOOKAHEAD(NamedExpressionList1()) namedExpressionList=NamedExpressionList1()
4316-
|
4317-
LOOKAHEAD(NamedExpressionListExprFirst(), { getAsBoolean(Feature.allowComplexParsing) }) namedExpressionList = NamedExpressionListExprFirst()
4318-
|
43194345
LOOKAHEAD(3, { getAsBoolean(Feature.allowComplexParsing) }) (expressionList=ComplexExpressionList() {expressionList.setUsingBrackets(false);} [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ])
43204346
|
43214347
LOOKAHEAD(3) (expressionList=SimpleExpressionList(false) [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ])
@@ -4324,7 +4350,7 @@ Function InternalFunction(Function retval) :
43244350

43254351
)]
43264352
[ <K_IGNORE> <K_NULLS> {retval.setIgnoreNulls(true); }]
4327-
")"
4353+
")"
43284354

43294355
[ "." (
43304356
LOOKAHEAD(2) expr1=Function() { retval.setAttribute(expr1); }
@@ -4336,7 +4362,6 @@ Function InternalFunction(Function retval) :
43364362

43374363
{
43384364
retval.setParameters(expressionList);
4339-
retval.setNamedParameters(namedExpressionList);
43404365
retval.setName(funcName);
43414366
retval.setKeep(keep);
43424367
return retval;

src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4664,4 +4664,20 @@ public void testDB2SpecialRegisterDateTimeIssue1249() throws JSQLParserException
46644664
public void testKeywordFilterIssue1255() throws JSQLParserException {
46654665
assertSqlCanBeParsedAndDeparsed("SELECT col1 AS filter FROM table");
46664666
}
4667+
4668+
@Test
4669+
public void testCollisionWithSpecialStringFunctionsIssue1284() throws JSQLParserException {
4670+
assertSqlCanBeParsedAndDeparsed(
4671+
"SELECT test( a in (1) AND 2=2) ", true);
4672+
4673+
assertSqlCanBeParsedAndDeparsed(
4674+
"select\n" +
4675+
"sum(if(column1 in('value1', 'value2'), 1, 0)) as tcp_logs,\n" +
4676+
"sum(if(column1 in ('value1', 'value2') and column2 = 'value3', 1, 0)) as base_tcp_logs\n" +
4677+
"from\n" +
4678+
"table1\n" +
4679+
"where\n" +
4680+
"recv_time >= toDateTime('2021-07-20 00:00:00')\n" +
4681+
"and recv_time < toDateTime('2021-07-21 00:00:00')", true);
4682+
}
46674683
}

0 commit comments

Comments
 (0)