Skip to content

Commit

Permalink
feat: Capture expression name part delimiters (#2001)
Browse files Browse the repository at this point in the history
* feat: Capture expression name part delimiters

* feat: Checkstyle

* feat: Test for empty name parts

* feat: Move ObjectNames class to parser. Tidy imports.

* feat: Spotless
  • Loading branch information
mountaincrab committed May 3, 2024
1 parent b815601 commit 0368b9e
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 39 deletions.
28 changes: 26 additions & 2 deletions src/main/java/net/sf/jsqlparser/schema/Column.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package net.sf.jsqlparser.schema;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.sf.jsqlparser.expression.ArrayConstructor;
import net.sf.jsqlparser.expression.Expression;
Expand All @@ -24,6 +26,7 @@ public class Column extends ASTNodeAccessImpl implements Expression, MultiPartNa
private String columnName;
private String commentText;
private ArrayConstructor arrayConstructor;
private String tableDelimiter = ".";

public Column() {}

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

public Column(List<String> nameParts) {
this(nameParts.size() > 1 ? new Table(nameParts.subList(0, nameParts.size() - 1)) : null,
this(nameParts, nameParts.size() > 1 ? Collections.nCopies(nameParts.size() - 1, ".")
: new ArrayList<>());
}

public Column(List<String> nameParts, List<String> delimiters) {
this(
nameParts.size() > 1 ? new Table(nameParts.subList(0, nameParts.size() - 1),
delimiters.subList(0, delimiters.size() - 1)) : null,
nameParts.get(nameParts.size() - 1));
setTableDelimiter(delimiters.isEmpty() ? "." : delimiters.get(delimiters.size() - 1));
}

public Column(String columnName) {
Expand Down Expand Up @@ -92,6 +103,14 @@ public void setColumnName(String string) {
columnName = string;
}

public String getTableDelimiter() {
return tableDelimiter;
}

public void setTableDelimiter(String tableDelimiter) {
this.tableDelimiter = tableDelimiter;
}

@Override
public String getFullyQualifiedName() {
return getFullyQualifiedName(false);
Expand All @@ -108,7 +127,7 @@ public String getFullyQualifiedName(boolean aliases) {
}
}
if (fqn.length() > 0) {
fqn.append('.');
fqn.append(tableDelimiter);
}
if (columnName != null) {
fqn.append(columnName);
Expand Down Expand Up @@ -157,6 +176,11 @@ public Column withCommentText(String commentText) {
return this;
}

public Column withTableDelimiter(String delimiter) {
this.setTableDelimiter(delimiter);
return this;
}

public void setCommentText(String commentText) {
this.commentText = commentText;
}
Expand Down
19 changes: 18 additions & 1 deletion src/main/java/net/sf/jsqlparser/schema/Table.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public class Table extends ASTNodeAccessImpl implements FromItem, MultiPartName

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

private List<String> partDelimiters = new ArrayList<>();

private Alias alias;

private SampleClause sampleClause;
Expand Down Expand Up @@ -75,6 +77,17 @@ public Table(List<String> partItems) {
Collections.reverse(this.partItems);
}

public Table(List<String> partItems, List<String> partDelimiters) {
if (partDelimiters.size() != partItems.size() - 1) {
throw new IllegalArgumentException(
"the length of the delimiters list must be 1 less than nameParts");
}
this.partItems = new ArrayList<>(partItems);
this.partDelimiters = new ArrayList<>(partDelimiters);
Collections.reverse(this.partItems);
Collections.reverse(this.partDelimiters);
}

public Database getDatabase() {
return new Database(getIndex(DATABASE_IDX));
}
Expand Down Expand Up @@ -177,7 +190,7 @@ public String getFullyQualifiedName() {
}
fqn.append(part);
if (i != 0) {
fqn.append(".");
fqn.append(partDelimiters.isEmpty() ? "." : partDelimiters.get(i - 1));
}
}

Expand Down Expand Up @@ -299,4 +312,8 @@ public Table withSqlServerHints(SQLServerHints sqlServerHints) {
public List<String> getNameParts() {
return partItems;
}

public List<String> getNamePartDelimiters() {
return partDelimiters;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ public void visit(Column tableColumn) {
}
}
if (tableName != null && !tableName.isEmpty()) {
buffer.append(tableName).append(".");
buffer.append(tableName).append(tableColumn.getTableDelimiter());
}

buffer.append(tableColumn.getColumnName());
Expand Down
92 changes: 58 additions & 34 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,25 @@ public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
public Node getASTRoot() {
return jjtree.rootNode();
}

private static class ObjectNames {

private final List<String> names;
private final List<String> delimiters;

public ObjectNames(List<String> names, List<String> delimiters) {
this.names = names;
this.delimiters = delimiters;
}

public List<String> getNames() {
return names;
}

public List<String> getDelimiters() {
return delimiters;
}
}
}

PARSER_END(CCJSqlParser)
Expand Down Expand Up @@ -1886,33 +1905,38 @@ MergeOperation MergeWhenNotMatched() : {
{ return mi; }
}

List<String> RelObjectNameList() : {
ObjectNames RelObjectNames() : {
String token = null;
Token delimiter = null;
List<String> data = new ArrayList<String>();
List<String> delimiters = new ArrayList<String>();
} {
token = RelObjectNameExt() { data.add(token); }
( LOOKAHEAD (2) ("." | ":") ("." { data.add(null); })* token = RelObjectNameExt2() { data.add(token); } ) *
(
LOOKAHEAD (2) ( delimiter = "." | delimiter = ":" ) { delimiters.add(delimiter.image); } (( delimiter = "." | delimiter = ":" ) { data.add(null); delimiters.add(delimiter.image); })*
token = RelObjectNameExt2() { data.add(token); }
) *

{ return data; }
{ return new ObjectNames(data, delimiters); }
}

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

Column Column() #Column :
{
List<String> data = new ArrayList<String>();
ObjectNames data = null;
ArrayConstructor arrayConstructor = null;
Token tk = null;
}
{
data = RelObjectNameList()
data = RelObjectNames()
[ LOOKAHEAD(2) <K_COMMENT> tk=<S_CHAR_LITERAL> ]
// @todo: we better should return a SEQUENCE instead of a COLUMN
[ "." <K_NEXTVAL> { data.add("nextval"); } ]
[ "." <K_NEXTVAL> { data.getNames().add("nextval"); } ]

[ LOOKAHEAD(2) arrayConstructor = ArrayConstructor(false) ]
{
Column col = new Column(data);
Column col = new Column(data.getNames(), data.getDelimiters());
if (tk != null) { col.withCommentText(tk.image); }
if (arrayConstructor!=null) {
col.setArrayConstructor(arrayConstructor);
Expand Down Expand Up @@ -2004,13 +2028,13 @@ String RelObjectNameExt2():
Table Table() #TableName :
{
//String serverName = null, databaseName = null, schemaName = null, tableName = null;
List<String> data = new ArrayList<String>();
ObjectNames data = null;
}
{
data = RelObjectNameList()
data = RelObjectNames()

{
Table table = new Table(data);
Table table = new Table(data.getNames());
linkAST(table,jjtThis);
return table;
}
Expand Down Expand Up @@ -4545,13 +4569,13 @@ ConnectByRootOperator ConnectByRootOperator() #ConnectByRootOperator: {
}

NextValExpression NextValExpression() : {
List<String> data = new ArrayList<String>();
ObjectNames data = null;
Token token;
}
{
token=<K_NEXTVAL> data = RelObjectNameList()
token=<K_NEXTVAL> data = RelObjectNames()
{
return new NextValExpression(data, token.image);
return new NextValExpression(data.getNames(), token.image);
}
}

Expand Down Expand Up @@ -5350,7 +5374,7 @@ EqualsTo VariableExpression(): {

Execute Execute(): {
Token token;
List<String> funcName;
ObjectNames funcName;
ExpressionList expressionList = null;
Execute execute = new Execute();
List<Expression> namedExprList;
Expand All @@ -5361,7 +5385,7 @@ Execute Execute(): {
| <K_EXECUTE> { execute.setExecType(Execute.ExecType.EXECUTE); }
| <K_CALL> { execute.setExecType(Execute.ExecType.CALL); } )

funcName=RelObjectNameList() { execute.setName(funcName); }
funcName=RelObjectNames() { execute.setName(funcName.getNames()); }

(
LOOKAHEAD(2) expressionList=ExpressionList() { execute.setExprList(expressionList); }
Expand Down Expand Up @@ -5483,13 +5507,13 @@ Function SpecialStringFunctionWithNamedParameters() :
Function SimpleFunction():
{
Function function = new Function();
List<String> name;
ObjectNames name;
Expression expr=null;
Expression attributeExpression = null;
Column attributeColumn = null;
}
{
name = RelObjectNameList()
name = RelObjectNames()
"("
[
(
Expand All @@ -5508,7 +5532,7 @@ Function SimpleFunction():
]
")"
{
function.setName(name);
function.setName(name.getNames());
if (expr!=null) {
function.setParameters(expr);
}
Expand All @@ -5533,7 +5557,7 @@ Function InternalFunction(boolean escaped):
{
Token prefixToken = null;
Function retval = new Function();
List<String> funcName;
ObjectNames funcName;
ExpressionList expressionList = null;
KeepExpression keep = null;
Expression expr = null;
Expand All @@ -5544,7 +5568,7 @@ Function InternalFunction(boolean escaped):
}
{
[ LOOKAHEAD(2) prefixToken = <K_APPROXIMATE> ]
funcName = RelObjectNameList() { if (prefixToken!=null) funcName.add(0, prefixToken.image ); }
funcName = RelObjectNames() { if (prefixToken!=null) funcName.getNames().add(0, prefixToken.image ); }

"("
[
Expand Down Expand Up @@ -5601,7 +5625,7 @@ Function InternalFunction(boolean escaped):
{
retval.setEscaped(escaped);
retval.setParameters(expressionList);
retval.setName(funcName);
retval.setName(funcName.getNames());
retval.setKeep(keep);
return retval;
}
Expand Down Expand Up @@ -5698,10 +5722,10 @@ List<Index.ColumnParams> ColumnNamesWithParamsList() : {
}

Index Index(): {
List<String> name;
ObjectNames name;
}
{
name= RelObjectNameList() { return new Index().withName(name).withType(""); }
name= RelObjectNames() { return new Index().withName(name.getNames()).withType(""); }
}

CreateIndex CreateIndex():
Expand Down Expand Up @@ -7311,7 +7335,7 @@ Grant Grant():
ArrayList<String> privileges = new ArrayList<String>();
List<String> users;
Token tk = null;
List<String> objName;
ObjectNames objName;
}
{
<K_GRANT>
Expand All @@ -7320,7 +7344,7 @@ Grant Grant():
[readGrantTypes(privileges) (<K_COMMA> readGrantTypes(privileges))*]
<K_ON>
(
objName=RelObjectNameList() { grant.setObjectName(objName); }
objName=RelObjectNames() { grant.setObjectName(objName.getNames()); }
)
)
|
Expand Down Expand Up @@ -7365,13 +7389,13 @@ void readGrantTypes(ArrayList<String> privileges):

Sequence Sequence() #Sequence :
{
List<String> data = new ArrayList<String>();
ObjectNames data = null;
String serverName = null, databaseName = null, schemaName = null, sequenceName = null;
}
{
data = RelObjectNameList()
data = RelObjectNames()
{
Sequence sequence = new Sequence(data);
Sequence sequence = new Sequence(data.getNames());
linkAST(sequence,jjtThis);
return sequence;
}
Expand Down Expand Up @@ -7575,29 +7599,29 @@ CreateSynonym CreateSynonym(boolean isUsingOrReplace):
CreateSynonym createSynonym = new CreateSynonym();
Synonym synonym;
boolean publicSynonym = false;
List<String> data = new ArrayList<String>();
ObjectNames data = null;
}
{
[<K_PUBLIC> { publicSynonym = true; } ]
<K_SYNONYM> synonym=Synonym() { createSynonym.setSynonym(synonym); }
<K_FOR> data = RelObjectNameList()
<K_FOR> data = RelObjectNames()
{
createSynonym.setOrReplace(isUsingOrReplace);
createSynonym.setPublicSynonym(publicSynonym);
createSynonym.setForList(data);
createSynonym.setForList(data.getNames());
return createSynonym;
}
}

Synonym Synonym() #Synonym :
{
List<String> data = new ArrayList<String>();
ObjectNames data = null;
String serverName = null, databaseName = null, schemaName = null, sequenceName = null;
}
{
data = RelObjectNameList()
data = RelObjectNames()
{
Synonym synonym = new Synonym(data);
Synonym synonym = new Synonym(data.getNames());
linkAST(synonym,jjtThis);
return synonym;
}
Expand Down

0 comments on commit 0368b9e

Please sign in to comment.