Skip to content

Commit 1427b65

Browse files
Separate MySQL Special String Functions accepting Named Argument Separation as this could collide with ComplexExpressionList when InExpression is involved
Fixes #1284
1 parent f85b4b6 commit 1427b65

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
@@ -378,6 +378,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
378378
| <K_SQL_NO_CACHE: "SQL_NO_CACHE">
379379
| <K_USING:"USING">
380380
| <K_SIGNED:"SIGNED">
381+
| <K_STRING_FUNCTION_NAME: ("SUBSTR" | "SUBSTRING" | "TRIM" | "POSITION" | "OVERLAY")>
381382
| <K_UNSIGNED:"UNSIGNED">
382383
| <K_VALIDATE : "VALIDATE">
383384
| <K_VALUE:"VALUE">
@@ -1439,6 +1440,7 @@ String RelObjectNameWithoutValue() :
14391440
/*| tk=<K_PLACING> | tk=<K_BOTH> | tk=<K_LEADING> | tk=<K_TRAILING> */
14401441
| tk=<K_FORMAT> | tk=<K_DIV> | tk=<K_UNSIGNED> | tk=<K_CASE> | tk=<K_LOCAL>
14411442
| tk=<K_ARRAY_LITERAL>
1443+
| tk=<K_STRING_FUNCTION_NAME>
14421444

14431445
/* Keywords for ALTER SESSION */
14441446
/* | tk=<K_NAME> */ | tk=<K_TIMEOUT> | tk=<K_PARALLEL>
@@ -1455,7 +1457,7 @@ String RelObjectName() :
14551457
{
14561458
(result = RelObjectNameWithoutValue()
14571459
| tk=<K_GROUP> | tk=<K_INTERVAL> | tk=<K_ON> | tk=<K_ORDER> | tk=<K_START> | tk=<K_TOP> | tk=<K_VALUE>
1458-
| tk=<K_VALUES> | tk=<K_CREATE> | tk=<K_TABLES> )
1460+
| tk=<K_VALUES> | tk=<K_CREATE> | tk=<K_TABLES> )
14591461

14601462
{
14611463
if (tk!=null) result=tk.image;
@@ -1485,7 +1487,7 @@ String RelObjectNameExt():
14851487
{
14861488
( result=RelObjectName() | tk=<K_ALL> | tk=<K_ANY> | tk=<K_SOME> | tk=<K_LEFT> | tk=<K_RIGHT> | tk=<K_SET>
14871489
| tk=<K_DOUBLE> | tk=<K_IF> | tk=<K_IIF> | tk=<K_OPTIMIZE> | tk=<K_LIMIT>
1488-
| tk=<K_OFFSET> | tk=<K_PROCEDURE> | tk=<K_PUBLIC>
1490+
| tk=<K_OFFSET> | tk=<K_PROCEDURE> | tk=<K_PUBLIC>
14891491
| tk=<K_CASEWHEN> | tk=<K_IN> )
14901492
{
14911493
if (tk!=null) result=tk.image;
@@ -4201,6 +4203,7 @@ Function Function() #Function:
42014203
{
42024204
(
42034205
"{" <K_FN> { retval.setEscaped(true); } InternalFunction(retval) "}"
4206+
| LOOKAHEAD(3) retval = SpecialStringFunctionWithNamedParameters()
42044207
| InternalFunction(retval)
42054208
)
42064209
{
@@ -4209,6 +4212,33 @@ Function Function() #Function:
42094212
}
42104213
}
42114214

4215+
Function SpecialStringFunctionWithNamedParameters() :
4216+
{
4217+
Token funcName;
4218+
NamedExpressionList namedExpressionList = null;
4219+
ExpressionList expressionList = null;
4220+
List<OrderByElement> orderByList;
4221+
}
4222+
{
4223+
funcName = <K_STRING_FUNCTION_NAME>
4224+
4225+
"("
4226+
(
4227+
LOOKAHEAD(NamedExpressionList1()) namedExpressionList=NamedExpressionList1()
4228+
|
4229+
LOOKAHEAD(NamedExpressionListExprFirst(), { getAsBoolean(Feature.allowComplexParsing) }) namedExpressionList = NamedExpressionListExprFirst()
4230+
|
4231+
LOOKAHEAD(3, { getAsBoolean(Feature.allowComplexParsing) }) expressionList=ComplexExpressionList() {expressionList.setUsingBrackets(false);}
4232+
|
4233+
LOOKAHEAD(3) expressionList=SimpleExpressionList(false)
4234+
)
4235+
")"
4236+
4237+
{
4238+
return new Function().withName(funcName.image).withNamedParameters(namedExpressionList).withParameters(expressionList);
4239+
}
4240+
}
4241+
42124242
Function InternalFunction(Function retval) :
42134243
{
42144244
List<String> funcName;
@@ -4231,10 +4261,6 @@ Function InternalFunction(Function retval) :
42314261
( LOOKAHEAD(4)
42324262
"*" { retval.setAllColumns(true); }
42334263
|
4234-
LOOKAHEAD(NamedExpressionList1()) namedExpressionList=NamedExpressionList1()
4235-
|
4236-
LOOKAHEAD(NamedExpressionListExprFirst(), { getAsBoolean(Feature.allowComplexParsing) }) namedExpressionList = NamedExpressionListExprFirst()
4237-
|
42384264
LOOKAHEAD(3, { getAsBoolean(Feature.allowComplexParsing) }) (expressionList=ComplexExpressionList() {expressionList.setUsingBrackets(false);} [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ])
42394265
|
42404266
LOOKAHEAD(3) (expressionList=SimpleExpressionList(false) [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ])
@@ -4243,7 +4269,7 @@ Function InternalFunction(Function retval) :
42434269

42444270
)]
42454271
[ <K_IGNORE> <K_NULLS> {retval.setIgnoreNulls(true); }]
4246-
")"
4272+
")"
42474273

42484274
[ "." (
42494275
LOOKAHEAD(2) expr1=Function() { retval.setAttribute(expr1); }
@@ -4255,7 +4281,6 @@ Function InternalFunction(Function retval) :
42554281

42564282
{
42574283
retval.setParameters(expressionList);
4258-
retval.setNamedParameters(namedExpressionList);
42594284
retval.setName(funcName);
42604285
retval.setKeep(keep);
42614286
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)