Skip to content

Commit 0368b9e

Browse files
authored
feat: Capture expression name part delimiters (#2001)
* feat: Capture expression name part delimiters * feat: Checkstyle * feat: Test for empty name parts * feat: Move ObjectNames class to parser. Tidy imports. * feat: Spotless
1 parent b815601 commit 0368b9e

File tree

7 files changed

+180
-39
lines changed

7 files changed

+180
-39
lines changed

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

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

12+
import java.util.ArrayList;
13+
import java.util.Collections;
1214
import java.util.List;
1315
import net.sf.jsqlparser.expression.ArrayConstructor;
1416
import net.sf.jsqlparser.expression.Expression;
@@ -24,6 +26,7 @@ public class Column extends ASTNodeAccessImpl implements Expression, MultiPartNa
2426
private String columnName;
2527
private String commentText;
2628
private ArrayConstructor arrayConstructor;
29+
private String tableDelimiter = ".";
2730

2831
public Column() {}
2932

@@ -33,8 +36,16 @@ public Column(Table table, String columnName) {
3336
}
3437

3538
public Column(List<String> nameParts) {
36-
this(nameParts.size() > 1 ? new Table(nameParts.subList(0, nameParts.size() - 1)) : null,
39+
this(nameParts, nameParts.size() > 1 ? Collections.nCopies(nameParts.size() - 1, ".")
40+
: new ArrayList<>());
41+
}
42+
43+
public Column(List<String> nameParts, List<String> delimiters) {
44+
this(
45+
nameParts.size() > 1 ? new Table(nameParts.subList(0, nameParts.size() - 1),
46+
delimiters.subList(0, delimiters.size() - 1)) : null,
3747
nameParts.get(nameParts.size() - 1));
48+
setTableDelimiter(delimiters.isEmpty() ? "." : delimiters.get(delimiters.size() - 1));
3849
}
3950

4051
public Column(String columnName) {
@@ -92,6 +103,14 @@ public void setColumnName(String string) {
92103
columnName = string;
93104
}
94105

106+
public String getTableDelimiter() {
107+
return tableDelimiter;
108+
}
109+
110+
public void setTableDelimiter(String tableDelimiter) {
111+
this.tableDelimiter = tableDelimiter;
112+
}
113+
95114
@Override
96115
public String getFullyQualifiedName() {
97116
return getFullyQualifiedName(false);
@@ -108,7 +127,7 @@ public String getFullyQualifiedName(boolean aliases) {
108127
}
109128
}
110129
if (fqn.length() > 0) {
111-
fqn.append('.');
130+
fqn.append(tableDelimiter);
112131
}
113132
if (columnName != null) {
114133
fqn.append(columnName);
@@ -157,6 +176,11 @@ public Column withCommentText(String commentText) {
157176
return this;
158177
}
159178

179+
public Column withTableDelimiter(String delimiter) {
180+
this.setTableDelimiter(delimiter);
181+
return this;
182+
}
183+
160184
public void setCommentText(String commentText) {
161185
this.commentText = commentText;
162186
}

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public class Table extends ASTNodeAccessImpl implements FromItem, MultiPartName
4141

4242
private List<String> partItems = new ArrayList<>();
4343

44+
private List<String> partDelimiters = new ArrayList<>();
45+
4446
private Alias alias;
4547

4648
private SampleClause sampleClause;
@@ -75,6 +77,17 @@ public Table(List<String> partItems) {
7577
Collections.reverse(this.partItems);
7678
}
7779

80+
public Table(List<String> partItems, List<String> partDelimiters) {
81+
if (partDelimiters.size() != partItems.size() - 1) {
82+
throw new IllegalArgumentException(
83+
"the length of the delimiters list must be 1 less than nameParts");
84+
}
85+
this.partItems = new ArrayList<>(partItems);
86+
this.partDelimiters = new ArrayList<>(partDelimiters);
87+
Collections.reverse(this.partItems);
88+
Collections.reverse(this.partDelimiters);
89+
}
90+
7891
public Database getDatabase() {
7992
return new Database(getIndex(DATABASE_IDX));
8093
}
@@ -177,7 +190,7 @@ public String getFullyQualifiedName() {
177190
}
178191
fqn.append(part);
179192
if (i != 0) {
180-
fqn.append(".");
193+
fqn.append(partDelimiters.isEmpty() ? "." : partDelimiters.get(i - 1));
181194
}
182195
}
183196

@@ -299,4 +312,8 @@ public Table withSqlServerHints(SQLServerHints sqlServerHints) {
299312
public List<String> getNameParts() {
300313
return partItems;
301314
}
315+
316+
public List<String> getNamePartDelimiters() {
317+
return partDelimiters;
318+
}
302319
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ public void visit(Column tableColumn) {
571571
}
572572
}
573573
if (tableName != null && !tableName.isEmpty()) {
574-
buffer.append(tableName).append(".");
574+
buffer.append(tableName).append(tableColumn.getTableDelimiter());
575575
}
576576

577577
buffer.append(tableColumn.getColumnName());

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

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,25 @@ public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
102102
public Node getASTRoot() {
103103
return jjtree.rootNode();
104104
}
105+
106+
private static class ObjectNames {
107+
108+
private final List<String> names;
109+
private final List<String> delimiters;
110+
111+
public ObjectNames(List<String> names, List<String> delimiters) {
112+
this.names = names;
113+
this.delimiters = delimiters;
114+
}
115+
116+
public List<String> getNames() {
117+
return names;
118+
}
119+
120+
public List<String> getDelimiters() {
121+
return delimiters;
122+
}
123+
}
105124
}
106125

107126
PARSER_END(CCJSqlParser)
@@ -1886,33 +1905,38 @@ MergeOperation MergeWhenNotMatched() : {
18861905
{ return mi; }
18871906
}
18881907

1889-
List<String> RelObjectNameList() : {
1908+
ObjectNames RelObjectNames() : {
18901909
String token = null;
1910+
Token delimiter = null;
18911911
List<String> data = new ArrayList<String>();
1912+
List<String> delimiters = new ArrayList<String>();
18921913
} {
18931914
token = RelObjectNameExt() { data.add(token); }
1894-
( LOOKAHEAD (2) ("." | ":") ("." { data.add(null); })* token = RelObjectNameExt2() { data.add(token); } ) *
1915+
(
1916+
LOOKAHEAD (2) ( delimiter = "." | delimiter = ":" ) { delimiters.add(delimiter.image); } (( delimiter = "." | delimiter = ":" ) { data.add(null); delimiters.add(delimiter.image); })*
1917+
token = RelObjectNameExt2() { data.add(token); }
1918+
) *
18951919

1896-
{ return data; }
1920+
{ return new ObjectNames(data, delimiters); }
18971921
}
18981922

18991923
// See: http://technet.microsoft.com/en-us/library/ms187879%28v=sql.105%29.aspx
19001924

19011925
Column Column() #Column :
19021926
{
1903-
List<String> data = new ArrayList<String>();
1927+
ObjectNames data = null;
19041928
ArrayConstructor arrayConstructor = null;
19051929
Token tk = null;
19061930
}
19071931
{
1908-
data = RelObjectNameList()
1932+
data = RelObjectNames()
19091933
[ LOOKAHEAD(2) <K_COMMENT> tk=<S_CHAR_LITERAL> ]
19101934
// @todo: we better should return a SEQUENCE instead of a COLUMN
1911-
[ "." <K_NEXTVAL> { data.add("nextval"); } ]
1935+
[ "." <K_NEXTVAL> { data.getNames().add("nextval"); } ]
19121936

19131937
[ LOOKAHEAD(2) arrayConstructor = ArrayConstructor(false) ]
19141938
{
1915-
Column col = new Column(data);
1939+
Column col = new Column(data.getNames(), data.getDelimiters());
19161940
if (tk != null) { col.withCommentText(tk.image); }
19171941
if (arrayConstructor!=null) {
19181942
col.setArrayConstructor(arrayConstructor);
@@ -2004,13 +2028,13 @@ String RelObjectNameExt2():
20042028
Table Table() #TableName :
20052029
{
20062030
//String serverName = null, databaseName = null, schemaName = null, tableName = null;
2007-
List<String> data = new ArrayList<String>();
2031+
ObjectNames data = null;
20082032
}
20092033
{
2010-
data = RelObjectNameList()
2034+
data = RelObjectNames()
20112035

20122036
{
2013-
Table table = new Table(data);
2037+
Table table = new Table(data.getNames());
20142038
linkAST(table,jjtThis);
20152039
return table;
20162040
}
@@ -4545,13 +4569,13 @@ ConnectByRootOperator ConnectByRootOperator() #ConnectByRootOperator: {
45454569
}
45464570

45474571
NextValExpression NextValExpression() : {
4548-
List<String> data = new ArrayList<String>();
4572+
ObjectNames data = null;
45494573
Token token;
45504574
}
45514575
{
4552-
token=<K_NEXTVAL> data = RelObjectNameList()
4576+
token=<K_NEXTVAL> data = RelObjectNames()
45534577
{
4554-
return new NextValExpression(data, token.image);
4578+
return new NextValExpression(data.getNames(), token.image);
45554579
}
45564580
}
45574581

@@ -5350,7 +5374,7 @@ EqualsTo VariableExpression(): {
53505374

53515375
Execute Execute(): {
53525376
Token token;
5353-
List<String> funcName;
5377+
ObjectNames funcName;
53545378
ExpressionList expressionList = null;
53555379
Execute execute = new Execute();
53565380
List<Expression> namedExprList;
@@ -5361,7 +5385,7 @@ Execute Execute(): {
53615385
| <K_EXECUTE> { execute.setExecType(Execute.ExecType.EXECUTE); }
53625386
| <K_CALL> { execute.setExecType(Execute.ExecType.CALL); } )
53635387

5364-
funcName=RelObjectNameList() { execute.setName(funcName); }
5388+
funcName=RelObjectNames() { execute.setName(funcName.getNames()); }
53655389

53665390
(
53675391
LOOKAHEAD(2) expressionList=ExpressionList() { execute.setExprList(expressionList); }
@@ -5483,13 +5507,13 @@ Function SpecialStringFunctionWithNamedParameters() :
54835507
Function SimpleFunction():
54845508
{
54855509
Function function = new Function();
5486-
List<String> name;
5510+
ObjectNames name;
54875511
Expression expr=null;
54885512
Expression attributeExpression = null;
54895513
Column attributeColumn = null;
54905514
}
54915515
{
5492-
name = RelObjectNameList()
5516+
name = RelObjectNames()
54935517
"("
54945518
[
54955519
(
@@ -5508,7 +5532,7 @@ Function SimpleFunction():
55085532
]
55095533
")"
55105534
{
5511-
function.setName(name);
5535+
function.setName(name.getNames());
55125536
if (expr!=null) {
55135537
function.setParameters(expr);
55145538
}
@@ -5533,7 +5557,7 @@ Function InternalFunction(boolean escaped):
55335557
{
55345558
Token prefixToken = null;
55355559
Function retval = new Function();
5536-
List<String> funcName;
5560+
ObjectNames funcName;
55375561
ExpressionList expressionList = null;
55385562
KeepExpression keep = null;
55395563
Expression expr = null;
@@ -5544,7 +5568,7 @@ Function InternalFunction(boolean escaped):
55445568
}
55455569
{
55465570
[ LOOKAHEAD(2) prefixToken = <K_APPROXIMATE> ]
5547-
funcName = RelObjectNameList() { if (prefixToken!=null) funcName.add(0, prefixToken.image ); }
5571+
funcName = RelObjectNames() { if (prefixToken!=null) funcName.getNames().add(0, prefixToken.image ); }
55485572

55495573
"("
55505574
[
@@ -5601,7 +5625,7 @@ Function InternalFunction(boolean escaped):
56015625
{
56025626
retval.setEscaped(escaped);
56035627
retval.setParameters(expressionList);
5604-
retval.setName(funcName);
5628+
retval.setName(funcName.getNames());
56055629
retval.setKeep(keep);
56065630
return retval;
56075631
}
@@ -5698,10 +5722,10 @@ List<Index.ColumnParams> ColumnNamesWithParamsList() : {
56985722
}
56995723

57005724
Index Index(): {
5701-
List<String> name;
5725+
ObjectNames name;
57025726
}
57035727
{
5704-
name= RelObjectNameList() { return new Index().withName(name).withType(""); }
5728+
name= RelObjectNames() { return new Index().withName(name.getNames()).withType(""); }
57055729
}
57065730

57075731
CreateIndex CreateIndex():
@@ -7311,7 +7335,7 @@ Grant Grant():
73117335
ArrayList<String> privileges = new ArrayList<String>();
73127336
List<String> users;
73137337
Token tk = null;
7314-
List<String> objName;
7338+
ObjectNames objName;
73157339
}
73167340
{
73177341
<K_GRANT>
@@ -7320,7 +7344,7 @@ Grant Grant():
73207344
[readGrantTypes(privileges) (<K_COMMA> readGrantTypes(privileges))*]
73217345
<K_ON>
73227346
(
7323-
objName=RelObjectNameList() { grant.setObjectName(objName); }
7347+
objName=RelObjectNames() { grant.setObjectName(objName.getNames()); }
73247348
)
73257349
)
73267350
|
@@ -7365,13 +7389,13 @@ void readGrantTypes(ArrayList<String> privileges):
73657389

73667390
Sequence Sequence() #Sequence :
73677391
{
7368-
List<String> data = new ArrayList<String>();
7392+
ObjectNames data = null;
73697393
String serverName = null, databaseName = null, schemaName = null, sequenceName = null;
73707394
}
73717395
{
7372-
data = RelObjectNameList()
7396+
data = RelObjectNames()
73737397
{
7374-
Sequence sequence = new Sequence(data);
7398+
Sequence sequence = new Sequence(data.getNames());
73757399
linkAST(sequence,jjtThis);
73767400
return sequence;
73777401
}
@@ -7575,29 +7599,29 @@ CreateSynonym CreateSynonym(boolean isUsingOrReplace):
75757599
CreateSynonym createSynonym = new CreateSynonym();
75767600
Synonym synonym;
75777601
boolean publicSynonym = false;
7578-
List<String> data = new ArrayList<String>();
7602+
ObjectNames data = null;
75797603
}
75807604
{
75817605
[<K_PUBLIC> { publicSynonym = true; } ]
75827606
<K_SYNONYM> synonym=Synonym() { createSynonym.setSynonym(synonym); }
7583-
<K_FOR> data = RelObjectNameList()
7607+
<K_FOR> data = RelObjectNames()
75847608
{
75857609
createSynonym.setOrReplace(isUsingOrReplace);
75867610
createSynonym.setPublicSynonym(publicSynonym);
7587-
createSynonym.setForList(data);
7611+
createSynonym.setForList(data.getNames());
75887612
return createSynonym;
75897613
}
75907614
}
75917615

75927616
Synonym Synonym() #Synonym :
75937617
{
7594-
List<String> data = new ArrayList<String>();
7618+
ObjectNames data = null;
75957619
String serverName = null, databaseName = null, schemaName = null, sequenceName = null;
75967620
}
75977621
{
7598-
data = RelObjectNameList()
7622+
data = RelObjectNames()
75997623
{
7600-
Synonym synonym = new Synonym(data);
7624+
Synonym synonym = new Synonym(data.getNames());
76017625
linkAST(synonym,jjtThis);
76027626
return synonym;
76037627
}

0 commit comments

Comments
 (0)