Skip to content

Commit 5dd3bbb

Browse files
Refactor multi-dot notation handling to be done in parser
Address PR feedback: Handle multi-dot notation directly in the parser grammar rather than in post-processing Java code. Changes: - ANTLR: Simplified to use getText() directly from parser, removed extractTableName() method that was walking the parse tree - JavaCC: Modified tableIdentifier rule to parse all dot-separated identifiers and split database/table within the grammar action - Both parsers now handle the logic in the grammar/parser itself
1 parent 1f9c61f commit 5dd3bbb

File tree

2 files changed

+35
-39
lines changed

2 files changed

+35
-39
lines changed

jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/SqlParserFacade.java

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,25 @@ public void enterColumnExprPrecedence3(ClickHouseParser.ColumnExprPrecedence3Con
248248
super.enterColumnExprPrecedence3(ctx);
249249
}
250250

251+
private String unquoteTableIdentifier(String rawTableId) {
252+
if (rawTableId == null || rawTableId.isEmpty()) {
253+
return rawTableId;
254+
}
255+
256+
// Split by dots and unquote each part
257+
String[] parts = rawTableId.split("\\.");
258+
StringBuilder result = new StringBuilder();
259+
260+
for (int i = 0; i < parts.length; i++) {
261+
if (i > 0) {
262+
result.append('.');
263+
}
264+
result.append(SQLUtils.unquoteIdentifier(parts[i]));
265+
}
266+
267+
return result.toString();
268+
}
269+
251270
@Override
252271
public void visitErrorNode(ErrorNode node) {
253272
parsedStatement.setHasErrors(true);
@@ -265,51 +284,18 @@ public void enterAssignmentValuesList(ClickHouseParser.AssignmentValuesListConte
265284
}
266285

267286

268-
private String extractTableName(ClickHouseParser.TableIdentifierContext tableId) {
269-
if (tableId == null) {
270-
return null;
271-
}
272-
273-
StringBuilder tableName = new StringBuilder();
274-
275-
// Handle database identifier if present
276-
if (tableId.databaseIdentifier() != null) {
277-
ClickHouseParser.DatabaseIdentifierContext dbCtx = tableId.databaseIdentifier();
278-
// Database identifier can have multiple parts: identifier (DOT identifier)*
279-
List<ClickHouseParser.IdentifierContext> dbParts = dbCtx.identifier();
280-
for (int i = 0; i < dbParts.size(); i++) {
281-
if (i > 0) {
282-
tableName.append('.');
283-
}
284-
tableName.append(SQLUtils.unquoteIdentifier(dbParts.get(i).getText()));
285-
}
286-
287-
// Only append dot if table identifier exists
288-
if (tableId.identifier() != null) {
289-
tableName.append('.');
290-
}
291-
}
292-
293-
// Handle table identifier
294-
if (tableId.identifier() != null) {
295-
tableName.append(SQLUtils.unquoteIdentifier(tableId.identifier().getText()));
296-
}
297-
298-
return tableName.toString();
299-
}
300-
301287
@Override
302288
public void enterTableExprIdentifier(ClickHouseParser.TableExprIdentifierContext ctx) {
303289
if (ctx.tableIdentifier() != null) {
304-
parsedStatement.setTable(extractTableName(ctx.tableIdentifier()));
290+
parsedStatement.setTable(unquoteTableIdentifier(ctx.tableIdentifier().getText()));
305291
}
306292
}
307293

308294
@Override
309295
public void enterInsertStmt(ClickHouseParser.InsertStmtContext ctx) {
310296
ClickHouseParser.TableIdentifierContext tableId = ctx.tableIdentifier();
311297
if (tableId != null) {
312-
parsedStatement.setTable(extractTableName(tableId));
298+
parsedStatement.setTable(unquoteTableIdentifier(tableId.getText()));
313299
}
314300

315301
ClickHouseParser.ColumnsClauseContext columns = ctx.columnsClause();

jdbc-v2/src/main/javacc/ClickHouseSqlParser.jj

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -903,18 +903,28 @@ void nestedIdentifier(): {} {
903903
(<ASTERISK> | anyIdentifier()) (LOOKAHEAD(2) <DOT> (<ASTERISK> | anyIdentifier()))*
904904
}
905905

906-
void tableIdentifier(boolean record): { Token t; } {
906+
void tableIdentifier(boolean record): { Token t; StringBuilder fullName = new StringBuilder(); } {
907907
(
908-
(LOOKAHEAD(2) databaseIdentifier(record) <DOT>)? t = anyIdentifier()
908+
t = anyIdentifier() { fullName.append(ClickHouseSqlUtils.unescape(t.image)); }
909+
(
910+
LOOKAHEAD(2) <DOT> t = anyIdentifier() { fullName.append('.').append(ClickHouseSqlUtils.unescape(t.image)); }
911+
)*
909912
(LOOKAHEAD(2)
910913
<LPAREN> { token_source.addCustomKeywordPosition(ClickHouseSqlStatement.KEYWORD_TABLE_COLUMNS_START, token); }
911914
anyExprList()
912915
<RPAREN> { token_source.addCustomKeywordPosition(ClickHouseSqlStatement.KEYWORD_TABLE_COLUMNS_END, token); }
913916
)?
914917
)
915918
{
916-
if (record && t != null && token_source.table == null) {
917-
token_source.table = ClickHouseSqlUtils.unescape(t.image);
919+
if (record && token_source.table == null) {
920+
String qualifiedName = fullName.toString();
921+
int lastDot = qualifiedName.lastIndexOf('.');
922+
if (lastDot > 0) {
923+
token_source.database = qualifiedName.substring(0, lastDot);
924+
token_source.table = qualifiedName.substring(lastDot + 1);
925+
} else {
926+
token_source.table = qualifiedName;
927+
}
918928
}
919929
}
920930
}

0 commit comments

Comments
 (0)