Skip to content

Commit 4df4e09

Browse files
committed
Protect shared dialect presets from external mutation
1 parent 0ecf096 commit 4df4e09

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import net.sf.jsqlparser.parser.feature.FeatureConfiguration;
1414

1515
import java.util.ArrayList;
16+
import java.util.Collections;
1617
import java.util.Arrays;
1718
import java.util.EnumSet;
1819
import java.util.List;
@@ -61,8 +62,9 @@ public enum Dialect {
6162
this(AdjacentStringLiterals.OFF, lexerFeatures);
6263
}
6364

65+
/** Returns the immutable lexer defaults shared by this dialect preset. */
6466
public Set<Feature> getLexerFeatures() {
65-
return lexerFeatures;
67+
return Collections.unmodifiableSet(lexerFeatures);
6668
}
6769

6870
public AdjacentStringLiterals getAdjacentStringLiterals() {
@@ -111,6 +113,10 @@ public P withTimeOut(long timeOutMillSeconds) {
111113
return withFeature(Feature.timeOut, timeOutMillSeconds);
112114
}
113115

116+
/**
117+
* Applies this dialect's enabled lexer defaults to the current configuration. Existing options
118+
* remain set; apply explicit overrides after this call, or use a new parser for a fresh preset.
119+
*/
114120
public P withDialect(Dialect dialect) {
115121
withFeature(Feature.dialect, dialect.name());
116122
if (dialect.getAdjacentStringLiterals() != AdjacentStringLiterals.OFF) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2019 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.parser;
11+
12+
import static org.junit.jupiter.api.Assertions.*;
13+
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
14+
import net.sf.jsqlparser.parser.feature.Feature;
15+
import org.junit.jupiter.api.Test;
16+
17+
class DialectPresetIsolationTest {
18+
@Test
19+
void callersCannotMutateSharedPresets() {
20+
for (Dialect dialect : Dialect.values()) {
21+
assertThrows(UnsupportedOperationException.class,
22+
() -> dialect.getLexerFeatures().add(Feature.allowHashLineComments));
23+
assertThrows(UnsupportedOperationException.class,
24+
() -> dialect.getLexerFeatures().clear());
25+
}
26+
}
27+
28+
@Test
29+
void explicitParserOverridesAreLocalAndDoNotModifyPresetDefaults() {
30+
CCJSqlParser first = CCJSqlParserUtil.newParser("SELECT 1").withDialect(Dialect.MYSQL)
31+
.withHashLineComments(false);
32+
CCJSqlParser second = CCJSqlParserUtil.newParser("SELECT 1").withDialect(Dialect.MYSQL);
33+
assertFalse(first.getAsBoolean(Feature.allowHashLineComments));
34+
assertTrue(second.getAsBoolean(Feature.allowHashLineComments));
35+
assertTrue(Dialect.MYSQL.getLexerFeatures().contains(Feature.allowHashLineComments));
36+
}
37+
38+
@Test
39+
void preservesAdditivePresetApplicationAndExplicitOverrideOrder() {
40+
CCJSqlParser parser = CCJSqlParserUtil.newParser("SELECT 1").withDialect(Dialect.SQLSERVER)
41+
.withDialect(Dialect.POSTGRESQL);
42+
assertTrue(parser.getAsBoolean(Feature.allowSquareBracketQuotation));
43+
parser.withSquareBracketQuotation(false);
44+
assertFalse(parser.getAsBoolean(Feature.allowSquareBracketQuotation));
45+
assertFalse(CCJSqlParserUtil.newParser("SELECT 1").withDialect(Dialect.POSTGRESQL)
46+
.getAsBoolean(Feature.allowSquareBracketQuotation));
47+
}
48+
}

0 commit comments

Comments
 (0)