Skip to content

Commit c065c09

Browse files
Merge branch 'master' of github.com:JSQLParser/JSqlParser
2 parents 4ba800d + bfcb8b7 commit c065c09

File tree

9 files changed

+142
-17
lines changed

9 files changed

+142
-17
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package net.sf.jsqlparser.expression;
1111

12+
import java.util.List;
1213
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
1314
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
1415
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
@@ -68,8 +69,6 @@
6869
import net.sf.jsqlparser.statement.select.Select;
6970
import net.sf.jsqlparser.statement.update.UpdateSet;
7071

71-
import java.util.List;
72-
7372
public interface ExpressionVisitor<T> {
7473

7574
default <S> T visitExpressions(ExpressionList<? extends Expression> expressions, S context) {
@@ -790,6 +789,12 @@ default void visit(Inverse inverse) {
790789

791790
<S> T visit(DateUnitExpression dateUnitExpression, S context);
792791

792+
<S> T visit(KeyExpression keyExpression, S context);
793+
794+
default void visit(KeyExpression keyExpression) {
795+
this.visit(keyExpression, null);
796+
}
797+
793798
<S> T visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter, S context);
794799

795800
default void visit(PostgresNamedFunctionParameter postgresNamedFunctionParameter) {

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
*/
1010
package net.sf.jsqlparser.expression;
1111

12+
import java.util.ArrayList;
13+
import java.util.Arrays;
14+
import java.util.Collection;
15+
import java.util.Optional;
1216
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
1317
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
1418
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
@@ -73,11 +77,6 @@
7377
import net.sf.jsqlparser.statement.select.UnPivot;
7478
import net.sf.jsqlparser.statement.select.WithItem;
7579

76-
import java.util.ArrayList;
77-
import java.util.Arrays;
78-
import java.util.Collection;
79-
import java.util.Optional;
80-
8180
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.UncommentedEmptyMethodBody"})
8281
public class ExpressionVisitorAdapter<T>
8382
implements ExpressionVisitor<T>, PivotVisitor<T>, SelectItemVisitor<T> {
@@ -769,6 +768,11 @@ public <S> T visit(ConnectByPriorOperator connectByPriorOperator, S context) {
769768
return connectByPriorOperator.getColumn().accept(this, context);
770769
}
771770

771+
@Override
772+
public <S> T visit(KeyExpression keyExpression, S context) {
773+
return keyExpression.getExpression().accept(this, context);
774+
}
775+
772776
@Override
773777
public <S> T visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) {
774778
return oracleNamedFunctionParameter.getExpression().accept(this, context);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.expression;
11+
12+
import java.util.Objects;
13+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
14+
15+
/**
16+
* Dialect specific expression for constructs such as {@code KEY chain.entity}.
17+
*/
18+
public class KeyExpression extends ASTNodeAccessImpl implements Expression {
19+
private final Expression expression;
20+
21+
public KeyExpression(Expression expression) {
22+
this.expression = Objects.requireNonNull(expression,
23+
"The EXPRESSION of the KEY expression must not be null");
24+
}
25+
26+
public Expression getExpression() {
27+
return expression;
28+
}
29+
30+
@Override
31+
public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
32+
return expressionVisitor.visit(this, context);
33+
}
34+
35+
public StringBuilder appendTo(StringBuilder builder) {
36+
builder.append("KEY ").append(expression);
37+
return builder;
38+
}
39+
40+
@Override
41+
public String toString() {
42+
return appendTo(new StringBuilder()).toString();
43+
}
44+
}

src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,8 @@ protected void toStringPartition(StringBuilder b) {
10721072
* Handles the general case for ADD, MODIFY, CHANGE, DROP (column), COMMENT, row-level security,
10731073
* and all field-based dispatch (columns, constraints, FK, UK, PK, index).
10741074
*/
1075-
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
1075+
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity",
1076+
"PMD.ExcessiveMethodLength"})
10761077
protected void toStringGeneral(StringBuilder b) {
10771078
if (operation == AlterOperation.COMMENT_WITH_EQUAL_SIGN) {
10781079
b.append("COMMENT =").append(" ");

src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,12 @@ public <S> Void visit(ConnectByPriorOperator connectByPriorOperator, S context)
17951795
return null;
17961796
}
17971797

1798+
@Override
1799+
public <S> Void visit(KeyExpression keyExpression, S context) {
1800+
keyExpression.getExpression().accept(this, context);
1801+
return null;
1802+
}
1803+
17981804
@Override
17991805
public <S> Void visit(IfElseStatement ifElseStatement, S context) {
18001806
ifElseStatement.getIfStatement().accept(this, context);

src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
*/
1010
package net.sf.jsqlparser.util.deparser;
1111

12+
import static java.util.stream.Collectors.joining;
13+
14+
import java.util.Iterator;
15+
import java.util.List;
16+
import java.util.Map;
1217
import net.sf.jsqlparser.expression.AllValue;
1318
import net.sf.jsqlparser.expression.AnalyticExpression;
1419
import net.sf.jsqlparser.expression.AnalyticType;
@@ -20,8 +25,8 @@
2025
import net.sf.jsqlparser.expression.CaseExpression;
2126
import net.sf.jsqlparser.expression.CastExpression;
2227
import net.sf.jsqlparser.expression.CollateExpression;
23-
import net.sf.jsqlparser.expression.ConnectByRootOperator;
2428
import net.sf.jsqlparser.expression.ConnectByPriorOperator;
29+
import net.sf.jsqlparser.expression.ConnectByRootOperator;
2530
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
2631
import net.sf.jsqlparser.expression.DateUnitExpression;
2732
import net.sf.jsqlparser.expression.DateValue;
@@ -41,6 +46,7 @@
4146
import net.sf.jsqlparser.expression.JsonFunction;
4247
import net.sf.jsqlparser.expression.JsonTableFunction;
4348
import net.sf.jsqlparser.expression.KeepExpression;
49+
import net.sf.jsqlparser.expression.KeyExpression;
4450
import net.sf.jsqlparser.expression.LambdaExpression;
4551
import net.sf.jsqlparser.expression.LongValue;
4652
import net.sf.jsqlparser.expression.LowExpression;
@@ -134,12 +140,6 @@
134140
import net.sf.jsqlparser.statement.select.SelectVisitor;
135141
import net.sf.jsqlparser.statement.select.WithItem;
136142

137-
import java.util.Iterator;
138-
import java.util.List;
139-
import java.util.Map;
140-
141-
import static java.util.stream.Collectors.joining;
142-
143143
@SuppressWarnings({"PMD.CyclomaticComplexity"})
144144
public class ExpressionDeParser extends AbstractDeParser<Expression>
145145
// FIXME maybe we should implement an ItemsListDeparser too?
@@ -1549,6 +1549,10 @@ public void visit(SimilarToExpression expr) {
15491549
visit(expr, null);
15501550
}
15511551

1552+
public void visit(KeyExpression keyExpression) {
1553+
visit(keyExpression, null);
1554+
}
1555+
15521556

15531557
@Override
15541558
public <S> StringBuilder visit(ArrayExpression array, S context) {
@@ -1669,6 +1673,13 @@ public <S> StringBuilder visit(ConnectByPriorOperator connectByPriorOperator, S
16691673
return builder;
16701674
}
16711675

1676+
@Override
1677+
public <S> StringBuilder visit(KeyExpression keyExpression, S context) {
1678+
builder.append("KEY ");
1679+
keyExpression.getExpression().accept(this, context);
1680+
return builder;
1681+
}
1682+
16721683
@Override
16731684
public <S> StringBuilder visit(OracleNamedFunctionParameter oracleNamedFunctionParameter,
16741685
S context) {

src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
import net.sf.jsqlparser.expression.CaseExpression;
2020
import net.sf.jsqlparser.expression.CastExpression;
2121
import net.sf.jsqlparser.expression.CollateExpression;
22-
import net.sf.jsqlparser.expression.ConnectByRootOperator;
2322
import net.sf.jsqlparser.expression.ConnectByPriorOperator;
23+
import net.sf.jsqlparser.expression.ConnectByRootOperator;
2424
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
2525
import net.sf.jsqlparser.expression.DateUnitExpression;
2626
import net.sf.jsqlparser.expression.DateValue;
@@ -40,6 +40,7 @@
4040
import net.sf.jsqlparser.expression.JsonFunction;
4141
import net.sf.jsqlparser.expression.JsonTableFunction;
4242
import net.sf.jsqlparser.expression.KeepExpression;
43+
import net.sf.jsqlparser.expression.KeyExpression;
4344
import net.sf.jsqlparser.expression.LambdaExpression;
4445
import net.sf.jsqlparser.expression.LongValue;
4546
import net.sf.jsqlparser.expression.LowExpression;
@@ -1061,6 +1062,12 @@ public <S> Void visit(ConnectByPriorOperator connectByPriorOperator, S context)
10611062
return null;
10621063
}
10631064

1065+
@Override
1066+
public <S> Void visit(KeyExpression keyExpression, S context) {
1067+
keyExpression.getExpression().accept(this, context);
1068+
return null;
1069+
}
1070+
10641071
@Override
10651072
public <S> Void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter, S context) {
10661073
oracleNamedFunctionParameter.getExpression().accept(this, context);
@@ -1249,6 +1256,10 @@ public void visit(ConnectByRootOperator connectByRootOperator) {
12491256
visit(connectByRootOperator, null);
12501257
}
12511258

1259+
public void visit(KeyExpression keyExpression) {
1260+
visit(keyExpression, null);
1261+
}
1262+
12521263
public void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) {
12531264
visit(oracleNamedFunctionParameter, null);
12541265
}

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7471,6 +7471,8 @@ Expression PrimaryExpression() #PrimaryExpression:
74717471

74727472
| retval=ConnectByPriorOperator()
74737473

7474+
| LOOKAHEAD(2, { !interrupted && getToken(1).kind == K_KEY && getToken(2).kind != OPENING_BRACKET }) retval=KeyExpression()
7475+
74747476
| LOOKAHEAD(2, {!interrupted}) <K_ALL> { retval = new AllValue(); }
74757477

74767478
| LOOKAHEAD(2, {!interrupted}) retval=Column()
@@ -7613,7 +7615,17 @@ ConnectByPriorOperator ConnectByPriorOperator() #ConnectByPriorOperator: {
76137615
{
76147616
<K_PRIOR> expression = Expression()
76157617
{
7616-
return new ConnectByPriorOperator(expression);
7618+
return new ConnectByPriorOperator(expression);
7619+
}
7620+
}
7621+
7622+
KeyExpression KeyExpression() #KeyExpression: {
7623+
Expression expression;
7624+
}
7625+
{
7626+
<K_KEY> expression = Expression()
7627+
{
7628+
return new KeyExpression(expression);
76177629
}
76187630
}
76197631

src/test/java/net/sf/jsqlparser/expression/FunctionTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
*/
1010
package net.sf.jsqlparser.expression;
1111

12+
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
14+
1215
import net.sf.jsqlparser.JSQLParserException;
16+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
1317
import net.sf.jsqlparser.test.TestUtils;
1418
import org.junit.jupiter.api.Disabled;
1519
import org.junit.jupiter.api.Test;
@@ -126,4 +130,31 @@ void TestIntervalParameterIssue2272() throws JSQLParserException {
126130
"SELECT DATE_SUB('2025-06-19', INTERVAL QUARTER(STR_TO_DATE('20250619', '%Y%m%d')) - 1 QUARTER) from dual";
127131
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
128132
}
133+
134+
@Test
135+
void testAesDecryptWithKeyExpressionParameter() throws JSQLParserException {
136+
String expression = "aes_decrypt(from_base64(entity), KEY chain.entity)";
137+
TestUtils.assertExpressionCanBeParsedAndDeparsed(expression, true);
138+
139+
Function function = (Function) CCJSqlParserUtil.parseExpression(expression);
140+
KeyExpression keyExpression =
141+
assertInstanceOf(KeyExpression.class, function.getParameters().get(1));
142+
assertEquals("chain.entity", keyExpression.getExpression().toString());
143+
144+
function.accept(new ExpressionVisitorAdapter<>(), null);
145+
}
146+
147+
@Test
148+
void testAesDecryptWithKeyExpressionInSelect() throws JSQLParserException {
149+
String sqlStr = "SELECT t1.entity, SUM(t2.balance) AS total_balance\n"
150+
+ "FROM (\n"
151+
+ " SELECT DISTINCT address, aes_decrypt(from_base64(entity), KEY chain.entity) AS entity\n"
152+
+ " FROM bch_entity\n"
153+
+ ") t1\n"
154+
+ "JOIN bch_address_token_statis t2\n"
155+
+ "ON t1.address = t2.address\n"
156+
+ "GROUP BY t1.entity";
157+
158+
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
159+
}
129160
}

0 commit comments

Comments
 (0)