From c9d3a359d6ceb94f32700bd7bd046813e2cf4249 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Tue, 28 Oct 2025 10:15:02 -0700 Subject: [PATCH 1/2] added a new package for all dependencies --- .../src/main/javacc/ClickHouseSqlParser.jj | 1283 ----------------- packages/clickhouse-jdbc-all/pom.xml | 55 + pom.xml | 1 + 3 files changed, 56 insertions(+), 1283 deletions(-) delete mode 100644 jdbc-v2/src/main/javacc/ClickHouseSqlParser.jj create mode 100644 packages/clickhouse-jdbc-all/pom.xml diff --git a/jdbc-v2/src/main/javacc/ClickHouseSqlParser.jj b/jdbc-v2/src/main/javacc/ClickHouseSqlParser.jj deleted file mode 100644 index e3eadced5..000000000 --- a/jdbc-v2/src/main/javacc/ClickHouseSqlParser.jj +++ /dev/null @@ -1,1283 +0,0 @@ -/** - * This ugly grammar defines a loose parser for ClickHouse. It cannot be used to validate SQL - * on behalf of server, but only for the following purposes: - * 1) split given SQL into multiple statements - * 2) recognize type of each statement(DDL/DML/DCL/TCL, query or mutation etc.) - * 3) extract cluster, database, table, format, file, compression, macros and parameters from a statement - * 4) check if specific keywords like "WITH TOTALS" or so exist in the statement or not - * - * The ANTLR4 grammar at https://github.com/ClickHouse/ClickHouse/blob/master/src/Parsers/New is incomplete. - * Also using it will introduce 300KB runtime and we'll have to deal with many parsing errors, - * which is too much for a JDBC driver. On the other hand, if we write a parser from scratch, - * we'll end up with one like Druid, which is more complex than the JDBC driver itself. - * - * JavaCC is something in the middle that fits our need - no runtime and easy to maintain/extend. - */ -options { - // DEBUG_LOOKAHEAD = true; - // DEBUG_PARSER = true; - // DEBUG_TOKEN_MANAGER = true; - - ERROR_REPORTING = false; - UNICODE_INPUT = true; - COMMON_TOKEN_ACTION = true; -} - -PARSER_BEGIN(ClickHouseSqlParser) - -package com.clickhouse.jdbc.parser; - -import java.io.StringReader; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.HashSet; -import java.util.Collection; - -import com.clickhouse.client.ClickHouseConfig; -import com.clickhouse.logging.Logger; -import com.clickhouse.logging.LoggerFactory; - -public class ClickHouseSqlParser { - private static final boolean DEBUG = false; - - private static final Logger log = LoggerFactory.getLogger(ClickHouseSqlParser.class); - - private final List statements = new ArrayList<>(); - - private ClickHouseConfig config; - private ParseHandler handler; - private int anyArgsListStart = -1; - - private boolean tokenIn(int tokenIndex, int... tokens) { - boolean matched = false; - - int t = getToken(tokenIndex).kind; - if (tokens != null) { - for (int i : tokens) { - if (t == i) { - matched = true; - break; - } - } - } - - return matched; - } - - // FIXME ugly workaround but performs better than adding another lexical state for ... - private boolean noAndWithinBetween() { - return !(getToken(1).kind == AND && token_source.parentToken == BETWEEN); - } - - public static ClickHouseSqlStatement[] parse(String sql, ClickHouseConfig config) { - return parse(sql, config, null); - } - - public static ClickHouseSqlStatement[] parse(String sql, ClickHouseConfig config, ParseHandler handler) { - if (config == null) { - config = new ClickHouseConfig(); - } - - ClickHouseSqlStatement[] stmts = new ClickHouseSqlStatement[] { - new ClickHouseSqlStatement(sql, StatementType.UNKNOWN) }; - - if (sql == null || sql.isEmpty()) { - return stmts; - } - - ClickHouseSqlParser p = new ClickHouseSqlParser(sql, config, handler); - try { - stmts = p.sql(); - } catch (Exception e) { - if (DEBUG) { - throw new IllegalArgumentException(e); - } else { - log.warn("%s. If you believe the SQL is valid, please feel free to open an issue on Github with this warning and the following SQL attached.\n%s", e.getMessage(), sql); - } - } - - return stmts; - } - - public ClickHouseSqlParser(String sql, ClickHouseConfig config, ParseHandler handler) { - this(new StringReader(sql)); - - this.config = config; - this.handler = handler; - } - - public void addStatement() { - if (token_source.isValid()) { - ClickHouseSqlStatement sqlStmt = token_source.build(handler); - // FIXME remove the restriction once we can hanlde insertion with format well - if (statements.isEmpty() || sqlStmt.isRecognized()) { - statements.add(sqlStmt); - } - } else { - token_source.reset(); - } - } - - - private void rememberSetStmtArgsStart() { - if (token.next != null && "ROLE".equalsIgnoreCase(token.next.image)) { - anyArgsListStart = token_source.input_stream.tokenBegin; - } - } - - private void rememberRolesIfSetStmt() { - if (anyArgsListStart > 0) { - HashSet roles = new HashSet<>(); - token_source.attachedAttributes.put("_ROLES", roles); - int stmtLength = token_source.builder.length(); - - StringBuilder roleBuff = new StringBuilder(); - boolean isQuoted = false; - for (int i = anyArgsListStart; i < stmtLength; i++) { - char ch = token_source.builder.charAt(i); - if (ch == '"' && isQuoted ) { - isQuoted = false; - } else if (ch == '"') { - isQuoted = true; - } else if (ch == ',' && !isQuoted && roleBuff.length() > 0) { - roles.add(roleBuff.toString()); - roleBuff.setLength(0); - } else if (!Character.isWhitespace(ch)) { - roleBuff.append(ch); - } - } - if (roleBuff.length() > 0) { - roles.add(roleBuff.toString()); - } - } - anyArgsListStart = -1; - } -} - -PARSER_END(ClickHouseSqlParser) - -TOKEN_MGR_DECLS: { - // whitespaces and comments are invalid - private int validTokens = 0; - // see http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm#tth_sEc3.17 - private int commentNestingDepth = 0; - - final java.util.Deque stack = new java.util.LinkedList<>(); - int parentToken = -1; - - final StringBuilder builder = new StringBuilder(512); - - StatementType stmtType = StatementType.UNKNOWN; - String cluster = null; - String database = null; - String table = null; - String input = null; - String compressAlgorithm = null; - String compressLevel = null; - String format = null; - String file = null; - - final List parameters = new ArrayList<>(); - final Map positions = new HashMap<>(); - final Map settings = new LinkedHashMap<>(); - final Set tempTables = new LinkedHashSet<>(); - final Map attachedAttributes = new HashMap<>(); - - public void CommonTokenAction(Token t) { - if (t.kind != ClickHouseSqlParserConstants.SEMICOLON) { - builder.append(t.image); - - if (t.kind != ClickHouseSqlParserConstants.EOF) { - validTokens++; - } - } - } - - void enterToken(int tokenKind) { - if (tokenKind < 0) { - return; - } - - stack.push(parentToken = tokenKind); - } - - void leaveToken(int tokenKind) { - if (parentToken == tokenKind) { - stack.pop(); - } - - parentToken = stack.isEmpty() ? -1 : stack.getLast(); - } - - void processMacro(String name, List params, ParseHandler handler) { - StringBuilder m = new StringBuilder(); - m.append('#').append(name); - - int startPos = builder.lastIndexOf(m.toString()); - int endPos = !params.isEmpty() ? builder.indexOf(")", startPos) + 1 : startPos + m.length(); - - builder.delete(startPos, endPos); - if (handler != null) { - String replacement = handler.handleMacro(name, params); - if (replacement != null && !replacement.isEmpty()) { - builder.insert(startPos, replacement); - } - } - } - - void processParameter(String str, ParseHandler handler) { - int pos = builder.lastIndexOf(str); - parameters.add(pos); - - if (handler != null) { - String replacement = handler.handleParameter(cluster, database, table, parameters.size()); - if (replacement != null && !replacement.isEmpty()) { - builder.deleteCharAt(pos); - builder.insert(pos, replacement); - } - } - } - - void append(StringBuilder str) { - builder.append(str.toString()); - } - - void reset() { - stack.clear(); - parentToken = -1; - - builder.setLength(validTokens = 0); - - stmtType = StatementType.UNKNOWN; - cluster = null; - database = null; - table = null; - input = null; - compressAlgorithm = null; - compressLevel = null; - format = null; - file = null; - parameters.clear(); - positions.clear(); - settings.clear(); - tempTables.clear(); - } - - ClickHouseSqlStatement build(ParseHandler handler) { - String sqlStmt = builder.toString(); - ClickHouseSqlStatement s = null; - if (attachedAttributes.get("_ROLES") != null && attachedAttributes.get("_ROLES") instanceof Collection){ - Collection roles = (Collection) attachedAttributes.get("_ROLES"); - settings.put("_ROLES_COUNT", String.valueOf(roles.size())); - int i = 0; - for (String role : roles) { - settings.put("_ROLE_" + i, role); - i++; - } - } - - if (handler != null) { - s = handler.handleStatement( - sqlStmt, stmtType, cluster, database, table, input, compressAlgorithm, compressLevel, format, file, parameters, positions, settings, tempTables); - } - - if (s == null) { - s = new ClickHouseSqlStatement( - sqlStmt, stmtType, cluster, database, table, input, compressAlgorithm, compressLevel, format, file, parameters, positions, settings, tempTables); - } - - // reset variables - reset(); - - return s; - } - - boolean isValid() { - return validTokens > 0; - } - - void addPosition(Token t) { - String keyword = null; - if (t == null || (keyword = t.image) == null || keyword.isEmpty()) { - return; - } - - this.positions.put(keyword.toUpperCase(Locale.ROOT), builder.lastIndexOf(keyword)); - } - - void addCustomKeywordPosition(String keyword, Token t) { - String search = t != null ? t.image : null; - if (keyword == null || keyword.isEmpty() || search == null || search.isEmpty()) { - return; - } - - this.positions.put(keyword, builder.lastIndexOf(search)); - } - - void removePosition(String keyword) { - this.positions.remove(keyword); - } - - void addSetting(String key, String value) { - if (key == null || key.isEmpty()) { - return; - } - - this.settings.put(key.toLowerCase(Locale.ROOT), value); - } -} - -SKIP: { - - { append(image); } - | { - int startIndex = image.indexOf("\'"); - int endIndex = image.lastIndexOf("\'"); - if (startIndex < 0 || endIndex < 0 || endIndex <= startIndex) { - // skip invalid content - } else if (image.charAt(1) == 'd') { // date - builder.append("date") - .append(image.substring(startIndex, endIndex + 1)); - } else { - char ch = image.charAt(2); - if (ch == 's') { // timestamp - int scale = image.lastIndexOf("."); - if (scale > 0) { - scale = endIndex - scale - 1; - } else { - scale = 0; - } - - if (scale > 0) { - // or downgrade to DateTime32 for better compatibility? - builder.append("toDateTime64(") - .append(image.substring(startIndex, endIndex + 1)).append(',').append(scale).append(')'); - } else { - builder.append("timestamp") - .append(image.substring(startIndex, endIndex + 1)); - } - } else if (ch == 't') { // temp table, either session-level temporary table or external table - String tableName = ClickHouseSqlUtils.unescape(image.substring(startIndex, endIndex + 1)); - builder.append('`').append(tableName).append('`'); - tempTables.add(tableName); - } else { - builder.append("timestamp'1970-01-01 ") - .append(image.substring(startIndex + 1, endIndex + 1)); - } - } - } - | { append(image); } - | "/*" { commentNestingDepth = 1; append(image); }: MULTI_LINE_COMMENT -} - - SKIP: { - "/*" { commentNestingDepth += 1; append(image); } - | "*/" { SwitchTo(--commentNestingDepth == 0 ? DEFAULT : MULTI_LINE_COMMENT); append(image); } - | < ~[] > { append(image); } -} - -/* - SKIP: { - { SwitchTo(DEFAULT); append(image); } - | < ~[] > { append(image); } -} -*/ - -// top-level statements -ClickHouseSqlStatement[] sql(): {} { - stmts() - { addStatement(); } - ( - (LOOKAHEAD(2) )+ - (stmts())? - { addStatement(); } - )* - - { return statements.toArray(new ClickHouseSqlStatement[statements.size()]); } -} - -void stmts(): {} { - LOOKAHEAD(2) stmt() - | LOOKAHEAD(2) anyExprList() // in case there's anything new -} - -void stmt(): {} { - alterStmt() { if (token_source.stmtType == StatementType.UNKNOWN) token_source.stmtType = StatementType.ALTER; } - | attachStmt() { token_source.stmtType = StatementType.ATTACH; } - | checkStmt() { token_source.stmtType = StatementType.CHECK; } - | createStmt() { token_source.stmtType = StatementType.CREATE; } - | deleteStmt() { token_source.stmtType = StatementType.DELETE; } - | describeStmt() { token_source.stmtType = StatementType.DESCRIBE; } - | detachStmt() { token_source.stmtType = StatementType.DETACH; } - | dropStmt() { token_source.stmtType = StatementType.DROP; } - | existsStmt() { token_source.stmtType = StatementType.EXISTS; } - | explainStmt() { token_source.stmtType = StatementType.EXPLAIN; } - | insertStmt() { token_source.stmtType = StatementType.INSERT; } - | grantStmt() { token_source.stmtType = StatementType.GRANT; } - | killStmt() { token_source.stmtType = StatementType.KILL; } - | optimizeStmt() { token_source.stmtType = StatementType.OPTIMIZE; } - | renameStmt() { token_source.stmtType = StatementType.RENAME; } - | revokeStmt() { token_source.stmtType = StatementType.REVOKE; } - | selectStmt() { token_source.stmtType = StatementType.SELECT; } - | setStmt() { token_source.stmtType = StatementType.SET; } - | showStmt() { token_source.stmtType = StatementType.SHOW; } - | systemStmt() { token_source.stmtType = StatementType.SYSTEM; } - | truncateStmt() { token_source.stmtType = StatementType.TRUNCATE; } - | updateStmt() { token_source.stmtType = StatementType.UPDATE; } - | useStmt() { token_source.stmtType = StatementType.USE; } - | watchStmt() { token_source.stmtType = StatementType.WATCH; } - | txStmt() { token_source.stmtType = StatementType.TRANSACTION; } -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/alter/ -void alterStmt(): {} { - - ( - LOOKAHEAD(2) - tableIdentifier(true) (LOOKAHEAD(2) clusterClause())? ( - LOOKAHEAD({ !tokenIn(1, UPDATE, DELETE) }) anyIdentifier() - | { token_source.stmtType = StatementType.ALTER_UPDATE; } - | { token_source.stmtType = StatementType.ALTER_DELETE; } - ) - )? (anyExprList())? -} - -void clusterClause(): { Token t; } { - (LOOKAHEAD(2) t = anyIdentifier() | t = ) - { token_source.cluster = ClickHouseSqlUtils.unescape(t.image); } -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/attach/ -void attachStmt(): { Token t; } { - ( - LOOKAHEAD(2) - ( - { token_source.addPosition(token); } - | - | ( { token_source.addPosition(token); }) ( - ()?
| ( | )? - ) - ) - ( - LOOKAHEAD(2) - { token_source.addPosition(token); } - )? - )? - anyExprList() // not interested -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/check-table/ -void checkStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/create/ -void createStmt(): {} { - ( - LOOKAHEAD(2) - ( - { token_source.addPosition(token); } - | ( { token_source.addPosition(token); })? ( - ()?
| ( | )? - ) - | | | | ()? | | ()? - ) - ( - LOOKAHEAD(2) - { token_source.addPosition(token); } - )? - )? - anyExprList() // not interested -} - -// upcoming lightweight mutation - see https://github.com/ClickHouse/ClickHouse/issues/19627 -void deleteStmt(): {} { - { token_source.addPosition(token); } { token_source.addPosition(token); } tableIdentifier(true) - (LOOKAHEAD({ getToken(1).kind == WHERE }) { token_source.addPosition(token); })? (anyExprList())? -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/describe-table/ -void describeStmt(): {} { - ( | ) { token_source.table = "columns"; } - (LOOKAHEAD({ getToken(1).kind == TABLE })
)? tableIdentifier(true) (anyExprList())? -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/detach/ -void detachStmt(): {} { - ( - LOOKAHEAD(2) - ( - { token_source.addPosition(token); } - | ()?
| | - ) - ( - LOOKAHEAD(2) - { token_source.addPosition(token); } - )? - )? - anyExprList() // not interested -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/drop/ -void dropStmt(): {} { - ( - LOOKAHEAD(2) - ( - { token_source.addPosition(token); } - | ()?
| | | | - | ()? | | ()? - ) - ( - LOOKAHEAD(2) - { token_source.addPosition(token); } - )? - )? - anyExprList() // not interested -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/exists/ -void existsStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/explain/ -void explainStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/grant/ -void grantStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/insert-into/ -void insertStmt(): {} { - - ( - LOOKAHEAD({ getToken(1).kind == FUNCTION }) functionExpr() - | (LOOKAHEAD(2)
)? tableIdentifier(true) - ) - ( - LOOKAHEAD(2) infilePart() - | ( - ( settingsPart() )? dataClause() - ) - ) -} - -void dataClause(): {} { - try { - LOOKAHEAD(2) { token_source.addPosition(token); } - { token_source.addCustomKeywordPosition(ClickHouseSqlStatement.KEYWORD_VALUES_START, token); } - columnExprList() - { token_source.addCustomKeywordPosition(ClickHouseSqlStatement.KEYWORD_VALUES_END, token); } - ( - LOOKAHEAD(2) - ()? - { token_source.removePosition(ClickHouseSqlStatement.KEYWORD_VALUES_START); } - columnExprList() - { token_source.removePosition(ClickHouseSqlStatement.KEYWORD_VALUES_END); } - )* - | (LOOKAHEAD(2) ((withClause())? { token_source.input = ClickHouseSqlUtils.unescape(token.image); } )? - { token_source.format = token.image; } )? (anyExprList())? - } catch (ParseException e) { - // FIXME introduce a lexical state in next release with consideration of delimiter from the context - Token nextToken; - do { - nextToken = getNextToken(); - } while(nextToken.kind != SEMICOLON && nextToken.kind != EOF); - } -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/kill/ -void killStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/optimize/ -void optimizeStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/rename/ -void renameStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/revoke/ -void revokeStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/select/ -void selectStmt(): {} { - // FIXME with (select 1), (select 2), 3 select * - (withClause())? -
)? tableIdentifier(true)) - ) - ) - { token_source.database = "system"; } - (LOOKAHEAD(2) anyExprList())? -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/system/ -void systemStmt(): {} { // not interested - anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/truncate/ -void truncateStmt(): {} { - (LOOKAHEAD(2) )? (LOOKAHEAD(2)
)? (LOOKAHEAD(2) )? - tableIdentifier(true) (clusterClause())? -} - -// upcoming lightweight mutation - see https://github.com/ClickHouse/ClickHouse/issues/19627 -void updateStmt(): {} { - { token_source.addPosition(token); } tableIdentifier(true) - { token_source.addPosition(token); } anyExprList() -} - -// https://clickhouse.tech/docs/en/sql-reference/statements/use/ -void useStmt(): {} { - databaseIdentifier(true) -} - -// Experimental LIVE VIEW feature -void watchStmt(): {} { // not interested - anyExprList() -} - -// TCL -void txStmt(): {} { // not interested - { token_source.addPosition(token); } - | { token_source.addPosition(token); } - | ( { token_source.addPosition(token); } ) -} - -// columns -void columnExprList(): {} { - columnsExpr() ( columnsExpr())* -} - -void withExpr(): {} { - nestedExpr() - ( - ( - LOOKAHEAD({ getToken(1).kind == FLOATING_LITERAL }) - | - )+ - | (LOOKAHEAD(2) anyExprList() )+ - | LOOKAHEAD(2) ()? - | LOOKAHEAD(2) ()? betweenExpr() - | LOOKAHEAD(2) ()? ( | ) nestedExpr() - | LOOKAHEAD(2, { noAndWithinBetween() }) (LOOKAHEAD(2, { noAndWithinBetween() }) calcExpr())+ - | LOOKAHEAD(2) ()? nestedExpr() - | LOOKAHEAD(2) nestedExpr() nestedExpr() - | LOOKAHEAD(2) columnExpr() - )? -} - -void columnsExpr(): {} { - LOOKAHEAD(allColumnsExpr()) allColumnsExpr() - ( - LOOKAHEAD(2) ( | | ) anyExprList() - )* - | nestedExpr() - ( - ( - LOOKAHEAD({ getToken(1).kind == FLOATING_LITERAL }) - | - )+ - | (LOOKAHEAD(2) anyExprList() )+ - | LOOKAHEAD(2) ()? - | LOOKAHEAD(2) ()? betweenExpr() - | LOOKAHEAD(2) ()? ( | ) nestedExpr() - | LOOKAHEAD(2, { noAndWithinBetween() }) (LOOKAHEAD(2, { noAndWithinBetween() }) calcExpr())+ - | LOOKAHEAD(2) ()? nestedExpr() - | LOOKAHEAD(2) nestedExpr() nestedExpr() - | LOOKAHEAD(2) aliasExpr() - )? -} - -void allColumnsExpr(): {} { - | anyIdentifier() (LOOKAHEAD(2) anyIdentifier() )? -} - -void nestedExpr(): {} { - LOOKAHEAD(2) ( | ) nestedExpr() - | LOOKAHEAD(2) (LOOKAHEAD({ getToken(1).kind != WHEN }) nestedExpr())? - ( nestedExpr() nestedExpr())+ ( nestedExpr())? - | LOOKAHEAD(2) (LOOKAHEAD(2) | nestedExpr() interval()) - | columnExpr() - ( - ( - | - )+ - | (LOOKAHEAD(2) anyExprList() )+ - | LOOKAHEAD(2) ()? - | LOOKAHEAD(2) ()? betweenExpr() - | LOOKAHEAD(2) ()? ( | ) nestedExpr() - | LOOKAHEAD(2, { noAndWithinBetween() }) (LOOKAHEAD(2, { noAndWithinBetween() }) calcExpr())+ - | LOOKAHEAD(2) ()? nestedExpr() - | LOOKAHEAD(2) nestedExpr() nestedExpr() - )? -} - -void calcExpr(): {} { - ( | | operator()) nestedExpr() -} - -void betweenExpr(): {} { - { token_source.enterToken(BETWEEN); } - nestedExpr() - { token_source.leaveToken(BETWEEN); } - nestedExpr() -} - -void functionExpr(): {} { - anyIdentifier() (anyExprList())? - // https://clickhouse.tech/docs/en/sql-reference/aggregate-functions/parametric-functions/ - (LOOKAHEAD(2) (anyExprList())? )? -} - -void columnExpr(): { Token t; } { - t = { token_source.processParameter(t.image, handler); } - | (LOOKAHEAD(2) anyExprList())? - | (LOOKAHEAD(2) anyExprList())? - | anyExprList() - | (LOOKAHEAD(2) macro())+ - | LOOKAHEAD(2, { !(tokenIn(1, INF, NAN, NULL) && tokenIn(2, DOT)) }) literal() - | LOOKAHEAD(2, { getToken(2).kind == LPAREN }) functionExpr() - | anyIdentifier() (LOOKAHEAD(2) anyIdentifier())* -} - -// interested parts -void compressionPart(): {} { - (LOOKAHEAD(2) ( | | ) { token_source.compressAlgorithm = token.image; })? - (LOOKAHEAD(2) ( | | ) { token_source.compressLevel = token.image; })? -} - -void formatPart(): {} { - { token_source.addPosition(token); } - (LOOKAHEAD(2) { token_source.format = token.image; })? -} - -void infilePart(): {} { - { token_source.addPosition(token); } - (LOOKAHEAD(2) ( | | ) { token_source.file = token.image; })? - ( compressionPart() )? - ( settingsPart() )? - ( formatPart() )? -} - -void outfilePart(): {} { - { token_source.addPosition(token); } - (LOOKAHEAD(2) ( | | ) { token_source.file = token.image; })? - (LOOKAHEAD(2) { token_source.addPosition(token); })? - ( compressionPart() )? -} - -void settingsPart(): {} { - { token_source.addPosition(token); } settingExprList() -} - -void withTotalPart(): {} { - (LOOKAHEAD(2) { token_source.addPosition(token); })? -} - -// expressions -void anyExprList(): {} { - anyExpr() (LOOKAHEAD(2) | anyExpr())* -} - -void anyExpr(): {} { - anyNestedExpr() ( - LOOKAHEAD(2) - ( - // TODO needs to extract parameters(and exclude ternary operator) here - | | | | | operator() - )? anyNestedExpr() - )* -} - -void anyNestedExpr(): {} { - LOOKAHEAD(2) formatPart() - | LOOKAHEAD(2) settingsPart() - | LOOKAHEAD(2) withTotalPart() - | LOOKAHEAD(2) outfilePart() - | (LOOKAHEAD(2) )? anyColumnExpr() ( - LOOKAHEAD({ getToken(1).kind == FLOATING_LITERAL }) - | - )* -} - -void anyColumnExpr(): {} { - // - { token_source.processParameter(token.image, handler); } - | (LOOKAHEAD(2) anyExprList())? - | (LOOKAHEAD(2) anyExprList())? - | (LOOKAHEAD(2) anyExprList())? - | (LOOKAHEAD(2) macro())+ - | LOOKAHEAD(2, { !(tokenIn(1, INF, NAN, NULL) && tokenIn(2, DOT)) }) literal() - // | (LOOKAHEAD(2, { !(tokenIn(1, INF, NAN, NULL)) }) | literal()) - | nestedIdentifier() -} - -Token aliasExpr(): { Token t = null; } { - ( - LOOKAHEAD(2) t = anyIdentifier() - | LOOKAHEAD(2) formatPart() - | LOOKAHEAD(2) settingsPart() - | LOOKAHEAD(2) outfilePart() - | t = identifier() - ) - { return t; } -} - -void nestedIdentifier(): {} { - ( | anyIdentifier()) (LOOKAHEAD(2) ( | anyIdentifier()))* -} - -void tableIdentifier(boolean record): { Token t; } { - ( - (LOOKAHEAD(2) databaseIdentifier(record) )? t = anyIdentifier() - (LOOKAHEAD(2) - { token_source.addCustomKeywordPosition(ClickHouseSqlStatement.KEYWORD_TABLE_COLUMNS_START, token); } - anyExprList() - { token_source.addCustomKeywordPosition(ClickHouseSqlStatement.KEYWORD_TABLE_COLUMNS_END, token); } - )? - ) - { - if (record && t != null && token_source.table == null) { - token_source.table = ClickHouseSqlUtils.unescape(t.image); - } - } -} - -void databaseIdentifier(boolean record): { Token t; } { - t = anyIdentifier() { if (record) token_source.database = ClickHouseSqlUtils.unescape(t.image); } -} - -void settingExprList(): {} { - settingExpr() (LOOKAHEAD(2) settingExpr())* -} - -void settingExpr(): { String key; } { - identifier() { key = token.image; } literal() { token_source.addSetting(key, token.image); } -} - -// basics -Token anyIdentifier(): { Token t; } { - ( - t = - | t = - | t = variable() - | t = - | t = anyKeyword() - ) - { return t; } -} - -Token identifier(): { Token t; } { - ( - t = - | t = - | t = variable() - | t = - | t = keyword() - ) - { return t; } -} - -void interval(): {} { - | | | | | | | -} - -Token literal(): { Token t = null; } { - ( - t = dateLiteral() - | t = numberLiteral() - | t = - | t = - ) - { return t; } -} - -Token dateLiteral(): { Token t; StringBuilder sb = new StringBuilder(); } { - (t = | t = ) { sb.append(t.image).append(' '); } - t = - { return Token.newToken(0, sb.append(t.image).toString()); } -} - -Token numberLiteral(): { Token t = null; StringBuilder sb = new StringBuilder(); } { - ( - (t = | t = )? { if (t != null) sb.append(t.image); } - ( - LOOKAHEAD(2) - t = | t = | t = | t = | t = - ) { sb.append(t.image); } - ) - { return Token.newToken(0, sb.toString()); } -} - -void operator(): {} { - ( | | | | | | - | | | | | | | | ) -} - -void macro(): { - Token t; - String name; - List params = new ArrayList<>(); -} { - ( - - (t = anyKeyword() | t = ) { name = t.image; } - ( - LOOKAHEAD(2) - t = { params.add(ClickHouseSqlUtils.unescape(t.image)); } - ( t = { params.add(ClickHouseSqlUtils.unescape(t.image)); })* - - )? - ) - { token_source.processMacro(name, params, handler); } -} - -Token variable(): { Token t; } { - ( (t = anyKeyword() | t = )) - { - return Token.newToken(0, "@@" + t.image); - } -} - -Token anyKeyword(): { Token t; } { - ( - // leading keywords(except with) - t = | t = | t = | t = | t = | t = | t = - | t = | t = | t = | t = | t = | t = | t = - | t = | t = | t = | t = | t = | t = | t = | t = | t = | t = | t = | t = | t = - | t = | t = | t = | t = | t = | t = | t = | t = - | t = | t = | t = | t = | t = | t = | t = | t = - | t = | t = | t = | t =
| t = | t = | t = | t = - | t = | t = | t = | t = | t = | t = | t = - | t = | t = | t = - // interval - | t = | t = | t = | t = | t = | t = | t = | t = - // values - | t = | t = | t = - ) - { return t; } -} - -Token keyword(): { Token t; } { - ( - // leading keywords(except with) - t = | t = | t = | t = | t = | t = | t = - | t = | t = | t = | t = | t = | t = | t = - | t = | t = | t = | t =
| t = | t = | t = | t = | t = | t = - | t = | t = | t = | t = - // interval - | t = | t = | t = | t = | t = | t = | t = | t = - // values - | t = | t = | t = - ) - { return t; } -} - -// keywords -TOKEN: { - > - | > - | > - | > - | > - | > - | > - | > - |

> - | > - |

> - | > - | > - | > - |

> - | > - | > - |

> - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - |

> - | > - | > - | > - |

> - | > - | > - |

> - |

> - | > - | > - | > - |

> - |

> - | > - | > - | > - | > - | > - | > - | > - | > - | > - | > - - | > - | > - | > - | > - | > - | > - | > - | > - - | > - | > - | > -} - -// letters -TOKEN: { - <#A: ["a", "A"]> - | <#B: ["b", "B"]> - | <#C: ["c", "C"]> - | <#D: ["d", "D"]> - | <#E: ["e", "E"]> - | <#F: ["f", "F"]> - | <#G: ["g", "G"]> - | <#H: ["h", "H"]> - | <#I: ["i", "I"]> - | <#J: ["j", "J"]> - | <#K: ["k", "K"]> - | <#L: ["l", "L"]> - | <#M: ["m", "M"]> - | <#N: ["n", "N"]> - | <#O: ["o", "O"]> - | <#P: ["p", "P"]> - | <#Q: ["q", "Q"]> - | <#R: ["r", "R"]> - | <#S: ["s", "S"]> - | <#T: ["t", "T"]> - | <#U: ["u", "U"]> - | <#V: ["v", "V"]> - | <#W: ["w", "W"]> - | <#X: ["x", "X"]> - | <#Y: ["y", "Y"]> - | <#Z: ["z", "Z"]> - - | <#LETTER: ["a"-"z", "A"-"Z"]> -} - -// numbers -TOKEN: { - <#ZERO: "0"> - | <#DEC_DIGIT: ["0"-"9"]> // including octal digit - | <#HEX_DIGIT: ["0"-"9", "a"-"f", "A"-"F"]> -} - -// symbols -TOKEN: { - "> - | - | - | - | - | - | - | - | - | - | - | - | - | ="> - | "> - | - | - | - | - | - | "> - | - | - | - | - | - | - | - | - | - | - | <#UNDERSCORE: "_"> -} - -// string literal -TOKEN: { - ( ~[] | ~["'", "\\"] | "''")* > -} - -TOKEN: { - | | | ) ( | | | )* - | ()+ ( - ( | )* - | ( - | | | | | | | | | | | | - | |

| | | | | | | | | | - | - ) ( | | )* - )> - | ( ~[] | ~["`", "\\"] | "``")* > - | ( ~[] | ~["\"", "\\"] | "\"\"")* > -} - -TOKEN: { - ()? (

| ) ( | )? - | (

| ) ( | )? - | ()? ( ( | )? )? - | ( ( | )? )? - | ( | )? > -} -TOKEN: { )+> } -TOKEN: { ()+> } diff --git a/packages/clickhouse-jdbc-all/pom.xml b/packages/clickhouse-jdbc-all/pom.xml new file mode 100644 index 000000000..56e52fd9d --- /dev/null +++ b/packages/clickhouse-jdbc-all/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + + + com.clickhouse + clickhouse-java + ${revision} + ../../pom.xml + + + clickhouse-jdbc-all + ${revision} + jar + + (Package) ClickHouse JDBC All Dependencies + JDBC driver for ClickHouse + https://github.com/ClickHouse/clickhouse-java/tree/main/clickhouse-jdbc-all + + + + com.clickhouse + clickhouse-jdbc + ${project.version} + all + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + 3.2.4 + + + package + + shade + + + true + true + true + true + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1625e9821..31729af8b 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,7 @@ clickhouse-jdbc jdbc-v2 clickhouse-r2dbc + packages/clickhouse-jdbc-all From e6cfb8b78ebd6d82dcde483fbaa3a6f2e665047b Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Wed, 29 Oct 2025 10:47:27 -0700 Subject: [PATCH 2/2] Made shaded jar as main --- packages/clickhouse-jdbc-all/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clickhouse-jdbc-all/pom.xml b/packages/clickhouse-jdbc-all/pom.xml index 56e52fd9d..dd99284fd 100644 --- a/packages/clickhouse-jdbc-all/pom.xml +++ b/packages/clickhouse-jdbc-all/pom.xml @@ -41,7 +41,7 @@ shade - true + false true true true