Skip to content

Commit a34db0c

Browse files
authored
fix(clickhouse): support SELECT ... SETTINGS (#2395)
* fix(clickhouse): support SELECT ... SETTINGS * fix keywords
1 parent 4f982e7 commit a34db0c

File tree

5 files changed

+67
-11
lines changed

5 files changed

+67
-11
lines changed

src/main/java/net/sf/jsqlparser/parser/ParserKeywordsUtils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ public class ParserKeywordsUtils {
134134
{"SELECT", RESTRICTED_ALIAS},
135135
{"SEMI", RESTRICTED_JSQLPARSER},
136136
{"SET", RESTRICTED_JSQLPARSER},
137+
{"SETTINGS", RESTRICTED_JSQLPARSER},
137138
{"SOME", RESTRICTED_JSQLPARSER},
138139
{"START", RESTRICTED_JSQLPARSER},
139140
{"STATEMENT", RESTRICTED_JSQLPARSER},

src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@
99
*/
1010
package net.sf.jsqlparser.statement.select;
1111

12-
import net.sf.jsqlparser.expression.Alias;
13-
import net.sf.jsqlparser.expression.Expression;
14-
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
15-
import net.sf.jsqlparser.expression.OracleHint;
16-
import net.sf.jsqlparser.expression.PreferringClause;
17-
import net.sf.jsqlparser.expression.WindowDefinition;
18-
import net.sf.jsqlparser.schema.Table;
12+
import static java.util.stream.Collectors.joining;
1913

2014
import java.util.ArrayList;
2115
import java.util.Arrays;
@@ -24,8 +18,14 @@
2418
import java.util.Iterator;
2519
import java.util.List;
2620
import java.util.Optional;
27-
28-
import static java.util.stream.Collectors.joining;
21+
import net.sf.jsqlparser.expression.Alias;
22+
import net.sf.jsqlparser.expression.Expression;
23+
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
24+
import net.sf.jsqlparser.expression.OracleHint;
25+
import net.sf.jsqlparser.expression.PreferringClause;
26+
import net.sf.jsqlparser.expression.WindowDefinition;
27+
import net.sf.jsqlparser.schema.Table;
28+
import net.sf.jsqlparser.statement.update.UpdateSet;
2929

3030
@SuppressWarnings({"PMD.CyclomaticComplexity"})
3131
public class PlainSelect extends Select {
@@ -65,6 +65,7 @@ public class PlainSelect extends Select {
6565
private boolean isUsingOnly = false;
6666
private boolean useWithNoLog = false;
6767
private Table intoTempTable = null;
68+
private List<UpdateSet> settings = null;
6869

6970
public PlainSelect() {}
7071

@@ -323,6 +324,19 @@ public PlainSelect withIntoTempTable(Table intoTempTable) {
323324
return this;
324325
}
325326

327+
public List<UpdateSet> getSettings() {
328+
return settings;
329+
}
330+
331+
public void setSettings(List<UpdateSet> settings) {
332+
this.settings = settings;
333+
}
334+
335+
public PlainSelect withSettings(List<UpdateSet> settings) {
336+
this.setSettings(settings);
337+
return this;
338+
}
339+
326340
@Override
327341
public <T, S> T accept(SelectVisitor<T> selectVisitor, S context) {
328342
return selectVisitor.visit(this, context);
@@ -632,6 +646,11 @@ public String toString() {
632646
StringBuilder builder = new StringBuilder();
633647
super.appendTo(builder);
634648

649+
if (settings != null && !settings.isEmpty()) {
650+
builder.append(" SETTINGS ");
651+
UpdateSet.appendUpdateSetsTo(builder, settings);
652+
}
653+
635654
if (optimizeFor != null) {
636655
builder.append(optimizeFor);
637656
}
@@ -779,6 +798,18 @@ public PlainSelect addJoins(Collection<? extends Join> joins) {
779798
return this.withJoins(collection);
780799
}
781800

801+
public PlainSelect addSettings(UpdateSet... settings) {
802+
List<UpdateSet> collection = Optional.ofNullable(getSettings()).orElseGet(ArrayList::new);
803+
Collections.addAll(collection, settings);
804+
return this.withSettings(collection);
805+
}
806+
807+
public PlainSelect addSettings(Collection<? extends UpdateSet> settings) {
808+
List<UpdateSet> collection = Optional.ofNullable(getSettings()).orElseGet(ArrayList::new);
809+
collection.addAll(settings);
810+
return this.withSettings(collection);
811+
}
812+
782813
public <E extends FromItem> E getFromItem(Class<E> type) {
783814
return type.cast(getFromItem());
784815
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,10 @@ public <S> StringBuilder visit(PlainSelect plainSelect, S context) {
369369
builder.append(" SKIP LOCKED");
370370
}
371371
}
372+
if (plainSelect.getSettings() != null && !plainSelect.getSettings().isEmpty()) {
373+
builder.append(" SETTINGS ");
374+
deparseUpdateSets(plainSelect.getSettings(), builder, expressionVisitor);
375+
}
372376
if (plainSelect.getOptimizeFor() != null) {
373377
deparseOptimizeFor(plainSelect.getOptimizeFor());
374378
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
603603
| <K_SEPARATOR:"SEPARATOR">
604604
| <K_SESSION:"SESSION">
605605
| <K_SET:"SET">
606+
| <K_SETTINGS:"SETTINGS">
606607
| <K_SETS:"SETS">
607608
| <K_SHOW : "SHOW">
608609
| <K_SHUTDOWN : "SHUTDOWN">
@@ -4292,6 +4293,7 @@ PlainSelect PlainSelect() #PlainSelect:
42924293
String windowName = null;
42934294
WindowDefinition winDef;
42944295
Table intoTempTable = null;
4296+
List<UpdateSet> settings = null;
42954297
Distinct distinct;
42964298
}
42974299
{
@@ -4408,6 +4410,7 @@ PlainSelect PlainSelect() #PlainSelect:
44084410
[ LOOKAHEAD(2) (<K_NOWAIT> { plainSelect.setNoWait(true); }
44094411
| <K_SKIP> <K_LOCKED> { plainSelect.setSkipLocked(true); }) ]
44104412
]
4413+
[ LOOKAHEAD(2) <K_SETTINGS> settings = UpdateSets() { plainSelect.setSettings(settings); } ]
44114414
[ LOOKAHEAD(<K_OPTIMIZE>) optimize = OptimizeFor() { plainSelect.setOptimizeFor(optimize); } ]
44124415
[ LOOKAHEAD(3) <K_INTO> <K_TEMP> intoTempTable = Table() { plainSelect.setIntoTempTable(intoTempTable);} ]
44134416
[ LOOKAHEAD(3)<K_WITH> <K_NO> <K_LOG> { plainSelect.setUseWithNoLog(true); } ]

src/test/java/net/sf/jsqlparser/statement/select/ClickHouseTest.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
*/
1010
package net.sf.jsqlparser.statement.select;
1111

12+
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
13+
1214
import net.sf.jsqlparser.JSQLParserException;
1315
import net.sf.jsqlparser.expression.Function;
1416
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
1517
import org.junit.jupiter.api.Assertions;
1618
import org.junit.jupiter.api.Test;
1719
import org.junit.jupiter.api.function.Executable;
1820

19-
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
20-
2121
public class ClickHouseTest {
2222

2323
@Test
@@ -132,4 +132,21 @@ public void testParameterizedAggregateFunctionIssue2125() throws JSQLParserExcep
132132
Assertions.assertEquals(1, function.getParameters().size());
133133
Assertions.assertEquals(1, function.getChainedParameters().size());
134134
}
135+
136+
@Test
137+
public void testSettingsClauseIssue2362() throws JSQLParserException {
138+
String sql = "SELECT *\nFROM events\nSETTINGS max_threads = 1";
139+
PlainSelect select = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sql, true);
140+
Assertions.assertNotNull(select.getSettings());
141+
Assertions.assertEquals(1, select.getSettings().size());
142+
Assertions.assertEquals("max_threads = 1", select.getSettings().get(0).toString());
143+
}
144+
145+
@Test
146+
public void testMultipleSettingsClauseIssue2362() throws JSQLParserException {
147+
String sql = "SELECT * FROM events SETTINGS max_threads = 1, max_rows_to_read = 1000";
148+
PlainSelect select = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sql, true);
149+
Assertions.assertNotNull(select.getSettings());
150+
Assertions.assertEquals(2, select.getSettings().size());
151+
}
135152
}

0 commit comments

Comments
 (0)