Skip to content

Commit 09a70a4

Browse files
feat: access Elements of Array Columns
- Example `update utilisateur set listes[0] = 1` - fixes #1083
1 parent c07a43b commit 09a70a4

9 files changed

Lines changed: 147 additions & 12 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,6 @@ public interface ExpressionVisitor {
228228
void visit(TranscodingFunction transcodingFunction);
229229

230230
void visit(TrimFunction trimFunction);
231+
232+
void visit(RangeExpression rangeExpression);
231233
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,4 +644,10 @@ public void visit(TranscodingFunction transcodingFunction) {
644644
public void visit(TrimFunction trimFunction) {
645645

646646
}
647+
648+
@Override
649+
public void visit(RangeExpression rangeExpression) {
650+
rangeExpression.getStartExpression().accept(this);
651+
rangeExpression.getEndExpression().accept(this);
652+
}
647653
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package net.sf.jsqlparser.expression;
2+
3+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
4+
5+
public class RangeExpression extends ASTNodeAccessImpl implements Expression {
6+
private Expression startExpression;
7+
private Expression endExpression;
8+
9+
public RangeExpression(Expression startExpression, Expression endExpression) {
10+
this.startExpression = startExpression;
11+
this.endExpression = endExpression;
12+
}
13+
14+
public Expression getStartExpression() {
15+
return startExpression;
16+
}
17+
18+
public RangeExpression setStartExpression(Expression startExpression) {
19+
this.startExpression = startExpression;
20+
return this;
21+
}
22+
23+
public Expression getEndExpression() {
24+
return endExpression;
25+
}
26+
27+
public RangeExpression setEndExpression(Expression endExpression) {
28+
this.endExpression = endExpression;
29+
return this;
30+
}
31+
32+
@Override
33+
public String toString() {
34+
return startExpression + ":" + endExpression;
35+
}
36+
37+
@Override
38+
public void accept(ExpressionVisitor expressionVisitor) {
39+
expressionVisitor.visit(this);
40+
}
41+
}

src/main/java/net/sf/jsqlparser/schema/Column.java

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

12+
import net.sf.jsqlparser.expression.ArrayConstructor;
1213
import net.sf.jsqlparser.expression.Expression;
1314
import net.sf.jsqlparser.expression.ExpressionVisitor;
1415
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
@@ -22,6 +23,7 @@ public class Column extends ASTNodeAccessImpl implements Expression, MultiPartNa
2223

2324
private Table table;
2425
private String columnName;
26+
private ArrayConstructor arrayConstructor;
2527

2628
public Column() {}
2729

@@ -39,6 +41,15 @@ public Column(String columnName) {
3941
this(null, columnName);
4042
}
4143

44+
public ArrayConstructor getArrayConstructor() {
45+
return arrayConstructor;
46+
}
47+
48+
public Column setArrayConstructor(ArrayConstructor arrayConstructor) {
49+
this.arrayConstructor = arrayConstructor;
50+
return this;
51+
}
52+
4253
/**
4354
* Retrieve the information regarding the {@code Table} this {@code Column} does belong to, if
4455
* any can be inferred.
@@ -102,6 +113,11 @@ public String getName(boolean aliases) {
102113
if (columnName != null) {
103114
fqn.append(columnName);
104115
}
116+
117+
if (arrayConstructor != null) {
118+
fqn.append(arrayConstructor);
119+
}
120+
105121
return fqn.toString();
106122
}
107123

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
4747
import net.sf.jsqlparser.expression.OverlapsCondition;
4848
import net.sf.jsqlparser.expression.Parenthesis;
49+
import net.sf.jsqlparser.expression.RangeExpression;
4950
import net.sf.jsqlparser.expression.RowConstructor;
5051
import net.sf.jsqlparser.expression.RowGetExpression;
5152
import net.sf.jsqlparser.expression.SignedExpression;
@@ -212,6 +213,12 @@ public void visit(TrimFunction trimFunction) {
212213
}
213214
}
214215

216+
@Override
217+
public void visit(RangeExpression rangeExpression) {
218+
rangeExpression.getStartExpression().accept(this);
219+
rangeExpression.getEndExpression().accept(this);
220+
}
221+
215222
/**
216223
* Main entry for this Tool class. A list of found tables is returned.
217224
*/

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
4747
import net.sf.jsqlparser.expression.OverlapsCondition;
4848
import net.sf.jsqlparser.expression.Parenthesis;
49+
import net.sf.jsqlparser.expression.RangeExpression;
4950
import net.sf.jsqlparser.expression.RowConstructor;
5051
import net.sf.jsqlparser.expression.RowGetExpression;
5152
import net.sf.jsqlparser.expression.SignedExpression;
@@ -470,6 +471,13 @@ public void visit(TrimFunction trimFunction) {
470471
buffer.append(" )");
471472
}
472473

474+
@Override
475+
public void visit(RangeExpression rangeExpression) {
476+
rangeExpression.getStartExpression().accept(this);
477+
buffer.append(":");
478+
rangeExpression.getEndExpression().accept(this);
479+
}
480+
473481
@Override
474482
public void visit(Column tableColumn) {
475483
final Table table = tableColumn.getTable();
@@ -486,6 +494,10 @@ public void visit(Column tableColumn) {
486494
}
487495

488496
buffer.append(tableColumn.getColumnName());
497+
498+
if (tableColumn.getArrayConstructor() != null) {
499+
tableColumn.getArrayConstructor().accept(this);
500+
}
489501
}
490502

491503
@Override

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
4646
import net.sf.jsqlparser.expression.OverlapsCondition;
4747
import net.sf.jsqlparser.expression.Parenthesis;
48+
import net.sf.jsqlparser.expression.RangeExpression;
4849
import net.sf.jsqlparser.expression.RowConstructor;
4950
import net.sf.jsqlparser.expression.RowGetExpression;
5051
import net.sf.jsqlparser.expression.SignedExpression;
@@ -668,4 +669,10 @@ public void visit(TrimFunction trimFunction) {
668669
trimFunction.getFromExpression().accept(this);
669670
}
670671
}
672+
673+
@Override
674+
public void visit(RangeExpression rangeExpression) {
675+
rangeExpression.getStartExpression().accept(this);
676+
rangeExpression.getEndExpression().accept(this);
677+
}
671678
}

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

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ List<UpdateSet> UpdateSets():
13071307
{
13081308
(
13091309
(
1310-
tableColumn=Column() "=" valueExpression=SimpleExpression()
1310+
tableColumn=Column() "=" valueExpression=Expression()
13111311
{ updateSets.add( new UpdateSet (tableColumn, valueExpression)); }
13121312
)
13131313
|
@@ -1326,7 +1326,7 @@ List<UpdateSet> UpdateSets():
13261326
(
13271327
","
13281328
(
1329-
tableColumn=Column() "=" valueExpression=SimpleExpression()
1329+
tableColumn=Column() "=" valueExpression=Expression()
13301330
{ updateSets.add( new UpdateSet (tableColumn, valueExpression)); }
13311331
)
13321332
|
@@ -1684,12 +1684,16 @@ List<String> RelObjectNameList() : {
16841684
Column Column() #Column :
16851685
{
16861686
List<String> data = new ArrayList<String>();
1687+
ArrayConstructor arrayConstructor = null;
16871688
}
16881689
{
16891690
data = RelObjectNameList()
1690-
1691+
[ LOOKAHEAD(2) arrayConstructor = ArrayConstructor(false) ]
16911692
{
16921693
Column col = new Column(data);
1694+
if (arrayConstructor!=null) {
1695+
col.setArrayConstructor(arrayConstructor);
1696+
}
16931697
linkAST(col,jjtThis);
16941698
return col;
16951699
}
@@ -3974,17 +3978,39 @@ DateTimeLiteralExpression DateTimeLiteralExpression() : {
39743978
t=<S_CHAR_LITERAL> { expr.setValue(t.image); return expr; }
39753979
}
39763980

3981+
RangeExpression RangeExpression(Expression startExpression):
3982+
{
3983+
Expression endExpression;
3984+
}
3985+
{
3986+
":" endExpression = Expression()
3987+
{
3988+
return new RangeExpression(startExpression, endExpression);
3989+
}
3990+
}
3991+
39773992
ArrayConstructor ArrayConstructor(boolean arrayKeyword) : {
39783993
ExpressionList expList = new ExpressionList();
39793994
ArrayConstructor array = new ArrayConstructor(expList, arrayKeyword);
39803995
Expression exp;
39813996
} {
39823997
"["
3983-
[ (LOOKAHEAD(3) exp = SimpleExpression() | exp = ArrayConstructor(false))
3984-
{ expList.add(exp); }
3985-
("," (exp = SimpleExpression() | exp = ArrayConstructor(false))
3986-
{ expList.add(exp); })*
3987-
]
3998+
[
3999+
(
4000+
LOOKAHEAD(3) exp = Expression() [ exp=RangeExpression(exp) ]
4001+
|
4002+
exp = ArrayConstructor(false)
4003+
) { expList.add(exp); }
4004+
4005+
(
4006+
","
4007+
(
4008+
LOOKAHEAD(3) exp = Expression() [ exp=RangeExpression(exp) ]
4009+
|
4010+
exp = ArrayConstructor(false)
4011+
){ expList.add(exp); }
4012+
)*
4013+
]
39884014
"]"
39894015
{ return array; }
39904016
}

src/test/java/net/sf/jsqlparser/statement/update/UpdateTest.java

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

12-
import java.io.StringReader;
1312
import net.sf.jsqlparser.JSQLParserException;
1413
import net.sf.jsqlparser.expression.DoubleValue;
1514
import net.sf.jsqlparser.expression.JdbcParameter;
@@ -19,14 +18,18 @@
1918
import net.sf.jsqlparser.parser.CCJSqlParserManager;
2019
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
2120
import net.sf.jsqlparser.schema.Column;
22-
import static net.sf.jsqlparser.test.TestUtils.*;
21+
import net.sf.jsqlparser.statement.Statement;
22+
import org.junit.jupiter.api.Test;
23+
24+
import java.io.StringReader;
25+
26+
import static net.sf.jsqlparser.test.TestUtils.assertOracleHintExists;
27+
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
2328
import static org.junit.jupiter.api.Assertions.assertEquals;
2429
import static org.junit.jupiter.api.Assertions.assertFalse;
2530
import static org.junit.jupiter.api.Assertions.assertThrows;
2631
import static org.junit.jupiter.api.Assertions.assertTrue;
2732

28-
import org.junit.jupiter.api.Test;
29-
3033
public class UpdateTest {
3134

3235
private static final CCJSqlParserManager PARSER_MANAGER = new CCJSqlParserManager();
@@ -337,4 +340,19 @@ public void testUpdateSetsIssue1590() throws JSQLParserException {
337340

338341
assertEquals("UPDATE mytable SET (a, y) = (5, 6) WHERE b = 2", update.toString());
339342
}
343+
344+
@Test
345+
void testIssue() throws JSQLParserException {
346+
String sqlStr = "SELECT listes[(SELECT cardinality(listes))]";
347+
Statement select = assertSqlCanBeParsedAndDeparsed(sqlStr, true);
348+
349+
sqlStr = "update utilisateur set listes[0] = 1";
350+
assertSqlCanBeParsedAndDeparsed(sqlStr, true);
351+
352+
sqlStr = "update utilisateur set listes[(select cardinality(listes))] = 1";
353+
assertSqlCanBeParsedAndDeparsed(sqlStr, true);
354+
355+
sqlStr = "update utilisateur set listes[0:3] = (1,2,3,4)";
356+
assertSqlCanBeParsedAndDeparsed(sqlStr, true);
357+
}
340358
}

0 commit comments

Comments
 (0)