Skip to content

Commit 6f7e415

Browse files
committed
Fixed statements with result set and several other
1 parent 25cca50 commit 6f7e415

File tree

6 files changed

+64
-40
lines changed

6 files changed

+64
-40
lines changed

jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/parser/ClickHouseLexer.g4

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ CASE : C A S E;
4545
CAST : C A S T;
4646
CHANGED : C H A N G E D;
4747
CHECK : C H E C K;
48+
CHANGEABLE_IN_READONLY : C H A N G E A B L E UNDERSCORE I N UNDERSCORE R E A D O N L Y;
4849
CLEANUP : C L E A N U P;
4950
CLEAR : C L E A R;
5051
CLIENT : C L I E N T ;
@@ -62,6 +63,7 @@ COMPILED : C O M P I L E D ;
6263
CONFIG : C O N F I G ;
6364
CONNECTIONS : C O N N E C T I O N S ;
6465
CONSTRAINT : C O N S T R A I N T;
66+
CONST : C O N S T;
6567
CREATE : C R E A T E;
6668
CROSS : C R O S S;
6769
CUBE : C U B E;
@@ -95,6 +97,7 @@ ENABLED : E N A B L E D;
9597
END : E N D;
9698
ENGINE : E N G I N E;
9799
ENGINES : E N G I N E S;
100+
ESTIMATE : E S T I M A T E;
98101
EVENTS : E V E N T S;
99102
EXCEPT : E X C E P T;
100103
EXISTS : E X I S T S;
@@ -142,6 +145,7 @@ INDEX : I N D E X;
142145
INDICES : I N D I C E S;
143146
INF : I N F | I N F I N I T Y;
144147
IN : I N;
148+
INHERIT : I N H E R I T;
145149
INJECTIVE : I N J E C T I V E;
146150
INNER : I N N E R;
147151
INSERT : I N S E R T;
@@ -212,11 +216,15 @@ OR : O R;
212216
OUTER : O U T E R;
213217
OUTFILE : O U T F I L E;
214218
OVER : O V E R;
219+
OVERRIDE : O V E R R I D E;
215220
PAGE : P A G E ;
216221
PARTITION : P A R T I T I O N;
217-
PARTS : P A R T S ;
222+
PART : P A R T;
223+
PARTS : P A R T S;
218224
PERMISSIVE : P E R M I S S I V E;
225+
PIPELINE : P I P E L I N E;
219226
PLAINTEXT_PASSWORD : P L A I N T E X T '_' P A S S W O R D;
227+
PLAN : P L A N;
220228
POLICIES : P O L I C I E S ;
221229
POLICY : P O L I C Y;
222230
POPULATE : P O P U L A T E;
@@ -236,8 +244,9 @@ QUOTA : Q U O T A;
236244
QUOTAS : Q U O T A S ;
237245
RABBITMQ : R A B B I T M Q;
238246
RANGE : R A N G E;
239-
READINESS : R E A D I N E S S ;
247+
READINESS : R E A D I N E S S;
240248
REALM : R E A L M;
249+
READONLY : R E A D O N L Y;
241250
REDIS : R E D I S;
242251
REDUCE : R E D U C E ;
243252
REFRESH : R E F R E S H ;
@@ -307,6 +316,7 @@ TOTALS : T O T A L S;
307316
TO : T O;
308317
TRAILING : T R A I L I N G;
309318
TRANSACTION : T R A N S A C T I O N;
319+
TREE : T R E E;
310320
TRIM : T R I M;
311321
TRUNCATE : T R U N C A T E;
312322
TTL : T T L;
@@ -338,7 +348,8 @@ WHEN : W H E N;
338348
WHERE : W H E R E;
339349
WINDOW : W I N D O W;
340350
WITH : W I T H;
341-
WORKLOAD : W O R K L O A D ;
351+
WORKLOAD : W O R K L O A D;
352+
WRITABLE : W R I T A B L E;
342353
YEAR : Y E A R | Y Y Y Y;
343354

344355
JSON_FALSE : 'false';

jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/parser/ClickHouseParser.g4

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ alterTableClause
8989
| MODIFY COLUMN (IF EXISTS)? tableColumnDfnt # AlterTableClauseModify
9090
| MODIFY ORDER BY columnExpr # AlterTableClauseModifyOrderBy
9191
| MODIFY ttlClause # AlterTableClauseModifyTTL
92+
| MODIFY COMMENT literal # AlterTableClauseModifyComment
9293
| MOVE partitionClause (
9394
TO DISK STRING_LITERAL
9495
| TO VOLUME STRING_LITERAL
@@ -130,15 +131,17 @@ attachStmt
130131
// CHECK statement
131132

132133
checkStmt
133-
: CHECK TABLE tableIdentifier partitionClause?
134+
: CHECK TABLE tableIdentifier (PARTITION identifier | PART identifier)? (FORMAT identifier)? settingsClause? # checkTableStmt
135+
| CHECK ALL TABLES (FORMAT identifier)? settingsClause? # checkAllTablesStmt
136+
| CHECK GRANT privilege columnsClause? ON grantTableIdentifier # checkGrantStmt
134137
;
135138

136139
// CREATE statement
137140

138141
createStmt
139142
: (ATTACH | CREATE) DATABASE (IF NOT EXISTS)? databaseIdentifier clusterClause? engineExpr? # CreateDatabaseStmt
140143
| (ATTACH | CREATE (OR REPLACE)? | REPLACE) DICTIONARY (IF NOT EXISTS)? tableIdentifier uuidClause? clusterClause? dictionarySchemaClause
141-
dictionaryEngineClause # CreateDictionaryStmt
144+
dictionaryEngineClause sourceClause layoutClause lifetimeClause dictionarySettingsClause? (COMMENT literal)? # CreateDictionaryStmt
142145
| (ATTACH | CREATE) LIVE VIEW (IF NOT EXISTS)? tableIdentifier uuidClause? clusterClause? (
143146
WITH TIMEOUT DECIMAL_LITERAL?
144147
)? destinationClause? tableSchemaClause? subqueryClause # CreateLiveViewStmt
@@ -147,8 +150,8 @@ createStmt
147150
| engineClause POPULATE?
148151
) subqueryClause # CreateMaterializedViewStmt
149152
| (ATTACH | CREATE (OR REPLACE)? | REPLACE) TEMPORARY? TABLE (IF NOT EXISTS)? tableIdentifier uuidClause? clusterClause? tableSchemaClause?
150-
engineClause? subqueryClause? # CreateTableStmt
151-
| (ATTACH | CREATE) (OR REPLACE)? VIEW (IF NOT EXISTS)? tableIdentifier uuidClause? clusterClause? tableSchemaClause? subqueryClause #
153+
engineClause? subqueryClause? # CreateTableStmt
154+
| (ATTACH | CREATE) (OR REPLACE)? VIEW (IF NOT EXISTS)? tableIdentifier alias? uuidClause? clusterClause? tableSchemaClause? subqueryClause #
152155
CreateViewStmt
153156
| CREATE USER ((IF NOT EXISTS) | (OR REPLACE))? userIdentifier (COMMA userIdentifier)* clusterClause?
154157
userIdentifiedClause?
@@ -162,6 +165,16 @@ createStmt
162165
| CREATE (ROW)? POLICY (IF NOT EXISTS | OR REPLACE)? identifier clusterClause? ON tableIdentifier
163166
(IN identifier)? (AS (PERMISSIVE | RESTRICTIVE))? (FOR SELECT)? USING columnExpr
164167
(TO identifier | ALL | ALL EXCEPT identifier)? # CreatePolicyStmt
168+
| CREATE SETTINGS? PROFILE ((IF NOT EXISTS) | (OR REPLACE))? identifier (COMMA identifier)* clusterClause?
169+
(IN identifier)? ((SETTINGS identifier (EQ_SINGLE literal)? (MIN EQ_SINGLE? literal)? (MAX EQ_SINGLE? literal)?
170+
(CONST|READONLY|WRITABLE|CHANGEABLE_IN_READONLY)?)
171+
| ( INHERIT identifier))? (TO identifier | ALL | ALL EXCEPT identifier)? # createProfileStmt
172+
| CREATE FUNCTION identifier clusterClause? AS LPAREN (identifier)? (COMMA identifier)? RPAREN ARROW .+? #createFunctionStmt
173+
| CREATE NAMED COLLECTION (IF NOT EXISTS)? identifier clusterClause? AS nameCollectionKey (COMMA nameCollectionKey)* #createNamedCollectionStmt
174+
;
175+
176+
nameCollectionKey
177+
: (identifier EQ_SINGLE literal (NOT? OVERRIDE)?)
165178
;
166179

167180
userIdentifier
@@ -205,23 +218,23 @@ dictionarySchemaClause
205218
;
206219

207220
dictionaryAttrDfnt
208-
: identifier columnTypeExpr
221+
: identifier columnTypeExpr ((DEFAULT | EXPRESSION) columnExpr)? (IS_OBJECT_ID|HIERARCHICAL|INJECTIVE)?
209222
;
210223

211224
dictionaryEngineClause
212225
: dictionaryPrimaryKeyClause?
213226
;
214227

215228
dictionaryPrimaryKeyClause
216-
: PRIMARY KEY columnExprList
229+
: PRIMARY KEY (identifier) (COMMA identifier)*
217230
;
218231

219232
dictionaryArgExpr
220233
: identifier (identifier (LPAREN RPAREN)? | literal)
221234
;
222235

223236
sourceClause
224-
: SOURCE LPAREN identifier LPAREN dictionaryArgExpr* RPAREN RPAREN
237+
: SOURCE LPAREN identifier LPAREN settingExprList RPAREN RPAREN
225238
;
226239

227240
lifetimeClause
@@ -298,7 +311,7 @@ tableElementExpr
298311
;
299312

300313
tableColumnDfnt
301-
: nestedIdentifier columnTypeExpr tableColumnPropertyExpr? (COMMENT STRING_LITERAL)? codecExpr? (
314+
: nestedIdentifier columnTypeExpr (NULL_SQL | NOT NULL_SQL)? tableColumnPropertyExpr? (COMMENT STRING_LITERAL)? codecExpr? (
302315
TTL columnExpr
303316
)?
304317
| nestedIdentifier columnTypeExpr? tableColumnPropertyExpr (COMMENT STRING_LITERAL)? codecExpr? (
@@ -307,7 +320,7 @@ tableColumnDfnt
307320
;
308321

309322
tableColumnPropertyExpr
310-
: (DEFAULT | MATERIALIZED | ALIAS) columnExpr
323+
: (DEFAULT | MATERIALIZED | ALIAS ) columnExpr
311324
;
312325

313326
tableIndexDfnt
@@ -348,15 +361,15 @@ dropStmt
348361
// EXISTS statement
349362

350363
existsStmt
351-
: EXISTS DATABASE databaseIdentifier # ExistsDatabaseStmt
352-
| EXISTS (DICTIONARY | TEMPORARY? TABLE | VIEW)? tableIdentifier # ExistsTableStmt
364+
: EXISTS DATABASE databaseIdentifier (INTO OUTFILE filename)? (FORMAT identifier)? # ExistsDatabaseStmt
365+
| EXISTS (DICTIONARY | TEMPORARY? TABLE | VIEW)? tableIdentifier (INTO OUTFILE filename)? (FORMAT identifier)? # ExistsTableStmt
353366
;
354367

355368
// EXPLAIN statement
356369

357370
explainStmt
358-
: EXPLAIN AST query # ExplainASTStmt
359-
| EXPLAIN SYNTAX query # ExplainSyntaxStmt
371+
: EXPLAIN (AST | SYNTAX | QUERY TREE | PLAN | PIPELINE | ESTIMATE | TABLE OVERRIDE)? settingExprList? .+?
372+
| EXPLAIN .+?
360373
;
361374

362375
// INSERT statement

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,8 @@ public void setHasErrors(boolean hasErrors) {
136136

137137
@Override
138138
public void enterQueryStmt(ClickHouseParser.QueryStmtContext ctx) {
139-
ClickHouseParser.QueryContext qCtx = ctx.query();
140-
if (qCtx != null) {
141-
if (qCtx.selectStmt() != null || qCtx.selectUnionStmt() != null || qCtx.showStmt() != null || qCtx.describeStmt() != null || qCtx.ctes() != null) {
142-
setHasResultSet(true);
143-
}
139+
if (SqlParser.isStmtWithResultSet(ctx)) {
140+
setHasResultSet(true);
144141
}
145142
}
146143

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,8 @@ public void visitErrorNode(ErrorNode node) {
7878

7979
@Override
8080
public void enterQueryStmt(ClickHouseParser.QueryStmtContext ctx) {
81-
ClickHouseParser.QueryContext qCtx = ctx.query();
82-
if (qCtx != null) {
83-
if (qCtx.selectStmt() != null || qCtx.selectUnionStmt() != null || qCtx.showStmt() != null
84-
|| qCtx.describeStmt() != null) {
85-
setHasResultSet(true);
86-
}
81+
if (SqlParser.isStmtWithResultSet(ctx)) {
82+
setHasResultSet(true);
8783
}
8884
}
8985

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,12 @@ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int
4848
LOG.warn("SQL syntax error at line: " + line + ", pos: " + charPositionInLine + ", " + msg);
4949
}
5050
}
51+
52+
static boolean isStmtWithResultSet(ClickHouseParser.QueryStmtContext stmtContext) {
53+
ClickHouseParser.QueryContext qCtx = stmtContext.query();
54+
55+
return qCtx != null && (qCtx.selectStmt() != null || qCtx.selectUnionStmt() != null ||
56+
qCtx.showStmt() != null || qCtx.explainStmt() != null || qCtx.describeStmt() != null ||
57+
qCtx.existsStmt() != null || qCtx.checkStmt() != null);
58+
}
5159
}

jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/SqlParserTest.java

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -492,12 +492,12 @@ public static Object[][] testStatementWithoutResultSetDP() {
492492
{"SHOW FUNCTIONS LIKE '%max%'", 0, true},
493493
{"SHOW MERGES", 0, true},
494494
{"SHOW MERGES LIKE 'your_t%' LIMIT 1", 0, true},
495-
{"EXPLAIN SELECT sum(number) FROM numbers(10) GROUP BY number % ?;", 1, true},
496-
{"EXPLAIN SELECT sum(number) FROM numbers(10) GROUP BY number % 4;", 0, true},
495+
{"EXPLAIN SELECT sum(number) FROM numbers(10) GROUP BY number", 0, true},
496+
{"EXPLAIN SELECT 1", 0, true},
497+
{"EXPLAIN SELECT sum(number) FROM numbers(10) UNION ALL SELECT sum(number) FROM numbers(10) ORDER BY sum(number) ASC FORMAT TSV", 0, true},
497498
{"DESCRIBE TABLE table", 0, true},
498499
{"DESC TABLE table1", 0, true},
499500
{"EXISTS TABLE `db`.`table01`", 0, true},
500-
{"EXISTS TABLE ?", 1, true},
501501
{"CHECK GRANT SELECT(col2) ON table_2", 0, true},
502502
{"CHECK TABLE test_table", 0, true},
503503
{"CHECK TABLE t0 PARTITION ID '201003' FORMAT PrettyCompactMonoBlock SETTINGS check_query_single_value_result = 0", 0, true},
@@ -512,8 +512,9 @@ public static Object[][] testStatementWithoutResultSetDP() {
512512
{"CREATE DATABASE IF NOT EXISTS `test_db` ON CLUSTER `cluster` ENGINE = Replicated('clickhouse1:9000', 'test_db')", 0, false},
513513
{"CREATE TABLE `test_table` (id UInt64)", 0, false},
514514
{"CREATE TABLE IF NOT EXISTS `test_table` (id UInt64)", 0, false},
515-
{"CREATE TABLE `test_table` (id UInt64) ENGINE = MergeTree() ORDER BY id", 0, false},
516-
{"CREATE TABLE `test_table` (id UInt64 NOT NULL ) ENGINE = MergeTree() ORDER BY id", 0, false},
515+
{"CREATE TABLE `test_table` (id UInt64) ENGINE = MergeTree ORDER BY (id)", 0, false},
516+
{"CREATE TABLE `test_table` (id UInt64) ENGINE = Memory", 0, false},
517+
{"CREATE TABLE `test_table` (id UInt64 NOT NULL ) ENGINE = MergeTree ORDER BY id", 0, false},
517518
{"CREATE TABLE `test_table` (id UInt64 NULL ) ENGINE = MergeTree() ORDER BY id", 0, false},
518519
{"CREATE TABLE `test_table` (id UInt64) ENGINE = MergeTree() ORDER BY id ON CLUSTER `cluster`", 0, false},
519520
{"CREATE TABLE `test_table` (id UInt64) ENGINE = MergeTree() ORDER BY id ON CLUSTER `cluster` ENGINE = Replicated('clickhouse1:9000', 'test_db')", 0, false},
@@ -524,10 +525,9 @@ public static Object[][] testStatementWithoutResultSetDP() {
524525
{"CREATE VIEW `test_db`.`source_table` source AS ( SELECT * FROM source_a UNION SELECT * FROM source_b) ENGINE = MaterializedView", 0, false},
525526
{"CREATE VIEW `test_db`.`source_table` source AS ( SELECT * FROM source_a UNION SELECT * FROM source_b) ENGINE = MaterializedView()", 0, false},
526527
{"CREATE VIEW `test_db`.`source_table` source AS ( SELECT * FROM source_a UNION SELECT * FROM source_b) ENGINE = MaterializedView() COMMENT 'for tests'", 0, false},
527-
{"CREATE DICTIONARY `test_db`.dict1 (k1 UInt64 EXPRESSION(k1 + 1), k2 String DEFAULT 'default', a1 Array(UInt64) DEFAULT []) PRIMARY KEY k1 SOURCE(CLICKHOUSE(db='test_db', table='dict1')) LAYOUT(FLAT()) LIFETIME(MIN 1000 MAX 2000)", 0, false},
528-
{"CREATE DICTIONARY `test_db`.dict1 (k1 UInt64 (k1 + 1), k2 String DEFAULT 'default', a1 Array(UInt64) DEFAULT []) PRIMARY KEY k1 SOURCE(CLICKHOUSE(db='test_db', table='dict1')) LAYOUT(FLAT()) LIFETIME(MIN 1000 MAX 2000) SETTINGS cache_size = 1000 COMMENT 'for tests'", 0, false},
529-
{"CREATE OR REPLACE DICTIONARY IF NOT EXISTS `test_db`.dict1 (k1 UInt64 (k1 + 1), k2 String DEFAULT 'default', a1 Array(UInt64) DEFAULT []) PRIMARY KEY k1 SOURCE(CLICKHOUSE(db='test_db', table='dict1')) LAYOUT(FLAT()) LIFETIME(MIN 1000 MAX 2000) SETTINGS cache_size = 1000 COMMENT 'for tests'", 0, false},
530-
{"CREATE OR REPLACE DICTIONARY IF NOT EXISTS `dict1` (k1 UInt64 (k1 + 1), k2 String DEFAULT 'default', a1 Array(UInt64) DEFAULT []) PRIMARY KEY k1 SOURCE(CLICKHOUSE(db='test_db', table='dict1')) LAYOUT(FLAT()) LIFETIME(MIN 1000 MAX 2000) SETTINGS cache_size = 1000 COMMENT 'for tests'", 0, false},
528+
{ "CREATE DICTIONARY `test_db`.dict1 (k1 UInt64 EXPRESSION(k1 + 1), k2 String DEFAULT 'default', a1 Array(UInt64) DEFAULT []) PRIMARY KEY k1 SOURCE(CLICKHOUSE(db='test_db', table='dict1')) LAYOUT(FLAT()) LIFETIME(MIN 1000 MAX 2000)", 0, false},
529+
{"CREATE DICTIONARY `test_db`.dict1 (k1 UInt64 (k1 + 1), k2 String DEFAULT 'default', a1 Array(UInt64) DEFAULT []) PRIMARY KEY k1 SOURCE(CLICKHOUSE(db='test_db', table='dict1')) LAYOUT(FLAT()) LIFETIME(MIN 1000 MAX 2000) SETTINGS(cache_size = 1000) COMMENT 'for tests'", 0, false},
530+
{"CREATE OR REPLACE DICTIONARY IF NOT EXISTS `test_db`.dict1 (k1 UInt64 (k1 + 1), k2 String DEFAULT 'default', a1 Array(UInt64) DEFAULT []) PRIMARY KEY k1 SOURCE(CLICKHOUSE(db='test_db', table='dict1')) LAYOUT(FLAT()) LIFETIME(MIN 1000 MAX 2000) SETTINGS(cache_size = 1000, v='123') COMMENT 'for tests'", 0, false},
531531
{"CREATE FUNCTION test_func AS () -> 10", 0, false},
532532
{"CREATE FUNCTION test_func AS (x) -> 10 * x", 0, false},
533533
{"CREATE FUNCTION test_func AS (x, y) -> y * x", 0, false},
@@ -542,10 +542,9 @@ public static Object[][] testStatementWithoutResultSetDP() {
542542
{"CREATE QUOTA qB FOR INTERVAL 30 minute MAX execution_time = 0.5, FOR INTERVAL 5 quarter MAX queries = 321, errors = 10 TO default", 0, false},
543543
{"CREATE SETTINGS PROFILE max_memory_usage_profile SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000 TO robin", 0, false},
544544
{"CREATE NAMED COLLECTION foobar AS a = '1', b = '2' OVERRIDABLE", 0, false},
545-
{"ALTER TABLE table1 ALTER COLUMN value Int64", 0, false},
546-
{"alter table t alter column j default 1", 0, false},
547-
{"alter table t modify comment 'comment'", 0, false},
548-
545+
// {"alter table t alter column j default 1", 0, false}, // not supported by CH
546+
{"ALTER TABLE t MODIFY COLUMN j default 1", 0, false},
547+
{"ALTER TABLE t MODIFY COMMENT 'comment'", 0, false},
549548
{"DELETE FROM db.table1 ON CLUSTER `default` WHERE max(a, 10) > ?", 1, false},
550549
{"DELETE FROM table WHERE a = ?", 1, false},
551550
{"DELETE FROM table WHERE a = ? AND b = ?", 2, false},

0 commit comments

Comments
 (0)