Skip to content

Commit 3e75aa8

Browse files
committed
Merge upstream master into fix/keep-feature-fallback-references-semantic
Signed-off-by: 付典 <fudianchn@gmail.com>
2 parents cd35c83 + 26d3e02 commit 3e75aa8

6 files changed

Lines changed: 388 additions & 12 deletions

File tree

‎src/main/java/net/sf/jsqlparser/expression/SpannerInterleaveIn.java‎

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

12-
import java.util.Locale;
13-
import net.sf.jsqlparser.schema.Table;
14-
12+
import java.io.Serializable;
1513
import java.util.Collections;
1614
import java.util.List;
15+
import java.util.Locale;
16+
import net.sf.jsqlparser.schema.Table;
1717

18-
public class SpannerInterleaveIn {
18+
public class SpannerInterleaveIn implements Serializable {
1919

2020
private Table table;
2121
private OnDelete onDelete;

‎src/main/java/net/sf/jsqlparser/statement/StatementFeatureVisitor.java‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,20 @@
2525
import net.sf.jsqlparser.expression.TranscodingFunction;
2626
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
2727
import net.sf.jsqlparser.statement.alter.Alter;
28+
import net.sf.jsqlparser.statement.alter.AlterCollation;
2829
import net.sf.jsqlparser.statement.alter.AlterDomain;
2930
import net.sf.jsqlparser.statement.alter.AlterExtension;
3031
import net.sf.jsqlparser.statement.alter.AlterPublication;
3132
import net.sf.jsqlparser.statement.alter.AlterSession;
33+
import net.sf.jsqlparser.statement.alter.AlterStatistics;
3234
import net.sf.jsqlparser.statement.alter.AlterSubscription;
3335
import net.sf.jsqlparser.statement.alter.AlterSystemStatement;
36+
import net.sf.jsqlparser.statement.alter.AlterTablespaceMove;
37+
import net.sf.jsqlparser.statement.alter.AlterTextSearchConfiguration;
3438
import net.sf.jsqlparser.statement.alter.AlterType;
3539
import net.sf.jsqlparser.statement.alter.RenameTableStatement;
40+
import net.sf.jsqlparser.statement.alter.database.AlterDatabase;
41+
import net.sf.jsqlparser.statement.alter.schema.AlterSchema;
3642
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
3743
import net.sf.jsqlparser.statement.analyze.Analyze;
3844
import net.sf.jsqlparser.statement.comment.Comment;
@@ -51,8 +57,10 @@
5157
import net.sf.jsqlparser.statement.create.subscription.SubscriptionOption;
5258
import net.sf.jsqlparser.statement.create.synonym.CreateSynonym;
5359
import net.sf.jsqlparser.statement.create.table.CreateTable;
60+
import net.sf.jsqlparser.statement.create.textsearch.CreateTextSearchConfiguration;
5461
import net.sf.jsqlparser.statement.create.trigger.CreateTrigger;
5562
import net.sf.jsqlparser.statement.create.type.CreateType;
63+
import net.sf.jsqlparser.statement.create.user.CreateUser;
5664
import net.sf.jsqlparser.statement.create.view.AlterView;
5765
import net.sf.jsqlparser.statement.create.view.CreateView;
5866
import net.sf.jsqlparser.statement.delete.Delete;
@@ -1159,4 +1167,45 @@ public <S> Void visit(OracleNullStatement statement, S context) {
11591167
public <S> Void visit(CreateAccessMethod statement, S context) {
11601168
return schemaOnly();
11611169
}
1170+
1171+
@Override
1172+
public <S> Void visit(AlterCollation statement, S context) {
1173+
return schemaOnly();
1174+
}
1175+
1176+
@Override
1177+
public <S> Void visit(AlterDatabase statement, S context) {
1178+
return schemaOnly();
1179+
}
1180+
1181+
@Override
1182+
public <S> Void visit(AlterSchema statement, S context) {
1183+
return schemaOnly();
1184+
}
1185+
1186+
@Override
1187+
public <S> Void visit(AlterStatistics statement, S context) {
1188+
return schemaOnly();
1189+
}
1190+
1191+
@Override
1192+
public <S> Void visit(AlterTablespaceMove statement, S context) {
1193+
return schemaOnly();
1194+
}
1195+
1196+
@Override
1197+
public <S> Void visit(AlterTextSearchConfiguration statement, S context) {
1198+
return schemaOnly();
1199+
}
1200+
1201+
@Override
1202+
public <S> Void visit(CreateTextSearchConfiguration statement, S context) {
1203+
return schemaOnly();
1204+
}
1205+
1206+
@Override
1207+
public <S> Void visit(CreateUser statement, S context) {
1208+
return schemaOnly();
1209+
}
1210+
11621211
}

‎src/main/java/net/sf/jsqlparser/statement/select/JoinHint.java‎

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

12+
import java.io.Serializable;
1213
import java.util.Objects;
1314

1415
/**
@@ -19,7 +20,7 @@
1920
* (Transact-SQL) - Join</a>
2021
*/
2122

22-
public class JoinHint {
23+
public class JoinHint implements Serializable {
2324
public enum Position {
2425
BEFORE_JOIN, AFTER_JOIN
2526
}

‎src/main/java/net/sf/jsqlparser/statement/select/SampleClause.java‎

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

12+
import java.io.Serializable;
1213
import java.util.Locale;
1314

14-
public class SampleClause {
15+
public class SampleClause implements Serializable {
1516
private SampleKeyword keyword;
1617
private SampleMethod method;
1718
private Number percentageArgument;

‎src/test/java/net/sf/jsqlparser/statement/SerializationTest.java‎

Lines changed: 196 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,29 @@
99
*/
1010
package net.sf.jsqlparser.statement;
1111

12-
import net.sf.jsqlparser.JSQLParserException;
13-
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
14-
import net.sf.jsqlparser.statement.select.PlainSelect;
15-
import org.junit.jupiter.api.Assertions;
16-
import org.junit.jupiter.api.Test;
17-
1812
import java.io.ByteArrayInputStream;
1913
import java.io.ByteArrayOutputStream;
2014
import java.io.IOException;
2115
import java.io.ObjectInputStream;
2216
import java.io.ObjectOutputStream;
17+
import java.math.BigDecimal;
18+
import java.util.stream.Stream;
19+
import net.sf.jsqlparser.JSQLParserException;
20+
import net.sf.jsqlparser.expression.SpannerInterleaveIn;
21+
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
22+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
23+
import net.sf.jsqlparser.schema.Table;
24+
import net.sf.jsqlparser.statement.create.table.CreateTable;
25+
import net.sf.jsqlparser.statement.select.JoinHint;
26+
import net.sf.jsqlparser.statement.select.PlainSelect;
27+
import net.sf.jsqlparser.statement.select.SampleClause;
28+
import net.sf.jsqlparser.test.TestUtils;
29+
import org.junit.jupiter.api.Assertions;
30+
import org.junit.jupiter.api.Test;
31+
import org.junit.jupiter.params.ParameterizedTest;
32+
import org.junit.jupiter.params.provider.Arguments;
33+
import org.junit.jupiter.params.provider.MethodSource;
34+
import org.junit.jupiter.params.provider.ValueSource;
2335

2436
public class SerializationTest {
2537
@Test
@@ -49,4 +61,182 @@ void serializeWithItem() throws JSQLParserException, IOException, ClassNotFoundE
4961
"The deserialized object should be equal to the original");
5062
}
5163

64+
@ParameterizedTest
65+
@ValueSource(strings = {"LOOP", "HASH", "MERGE", "REMOTE"})
66+
void serializeSqlServerJoinHint(String keyword) throws Exception {
67+
PlainSelect original = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(
68+
"SELECT a.id FROM a INNER " + keyword + " JOIN b ON a.id = b.id");
69+
PlainSelect copy = roundTrip(original);
70+
JoinHint hint = copy.getJoins().get(0).getJoinHint();
71+
Assertions.assertEquals(keyword, hint.getKeyword());
72+
Assertions.assertEquals(JoinHint.Position.BEFORE_JOIN, hint.getPosition());
73+
Assertions.assertEquals("b", ((Table) copy.getJoins().get(0).getFromItem()).getName());
74+
Assertions.assertEquals("a.id = b.id",
75+
copy.getJoins().get(0).getOnExpressions().iterator().next().toString());
76+
}
77+
78+
@ParameterizedTest
79+
@ValueSource(strings = {"shuffle", "BROADCAST"})
80+
void serializeDorisJoinHint(String keyword) throws Exception {
81+
PlainSelect original = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(
82+
"SELECT a.id FROM a LEFT JOIN [" + keyword + "] b USING (id)", false,
83+
parser -> parser.withDialect(Dialect.DORIS));
84+
PlainSelect copy = roundTrip(original);
85+
JoinHint hint = copy.getJoins().get(0).getJoinHint();
86+
Assertions.assertEquals(keyword, hint.getKeyword());
87+
Assertions.assertEquals(JoinHint.Position.AFTER_JOIN, hint.getPosition());
88+
Assertions.assertEquals("id",
89+
copy.getJoins().get(0).getUsingColumns().get(0).getColumnName());
90+
Assertions.assertTrue(copy.getJoins().get(0).isLeft());
91+
}
92+
93+
static Stream<Arguments> samplingClauses() {
94+
return Stream.of(
95+
Arguments.of("TABLESAMPLE BERNOULLI (10)",
96+
new SampleClause("TABLESAMPLE", "BERNOULLI", 10L, null, null, null)),
97+
Arguments.of("TABLESAMPLE SYSTEM (10.5 PERCENT) REPEATABLE (7)",
98+
new SampleClause("TABLESAMPLE", "SYSTEM", 10.5, "PERCENT", 7L, null)),
99+
Arguments.of("SAMPLE (99)",
100+
new SampleClause("SAMPLE", null, 99L, null, null, null)),
101+
Arguments.of("SAMPLE BLOCK (99.1) SEED (10.1)",
102+
new SampleClause("SAMPLE", "BLOCK", 99.1, null, null, 10.1)),
103+
Arguments.of("SAMPLE 0.1 OFFSET 1000",
104+
new SampleClause("SAMPLE", null, 0.1, null, null, null, false, 1000L)),
105+
Arguments.of("USING SAMPLE 10%",
106+
new SampleClause("USING SAMPLE", null, 10L, "%", null, null, false, null)),
107+
Arguments.of("USING SAMPLE 10 ROWS (system, 377)",
108+
new SampleClause("USING SAMPLE", "SYSTEM", 10L, "ROWS", null, 377L,
109+
false, null).setMethodInBrackets(true)),
110+
Arguments.of("USING SAMPLE RESERVOIR (50 ROWS)",
111+
new SampleClause("USING SAMPLE", "RESERVOIR", 50L, "ROWS", null, null)));
112+
}
113+
114+
@ParameterizedTest
115+
@MethodSource("samplingClauses")
116+
void serializeTableSampleClause(String clause, SampleClause expected) throws Exception {
117+
PlainSelect original = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(
118+
"SELECT id FROM events " + clause + " WHERE id > 0");
119+
assertSampleClause(expected, ((Table) original.getFromItem()).getSampleClause());
120+
PlainSelect copy = roundTrip(original);
121+
assertSampleClause(expected, ((Table) copy.getFromItem()).getSampleClause());
122+
Assertions.assertEquals("events", ((Table) copy.getFromItem()).getName());
123+
Assertions.assertEquals("id > 0", copy.getWhere().toString());
124+
Assertions.assertEquals("id", copy.getSelectItem(0).toString());
125+
}
126+
127+
@ParameterizedTest
128+
@ValueSource(strings = {
129+
"SELECT * FROM (SELECT id FROM events) TABLESAMPLE SYSTEM (10 PERCENT)",
130+
"SELECT * FROM (events) TABLESAMPLE SYSTEM (10 PERCENT)",
131+
"SELECT * FROM events MATCH_RECOGNIZE (PATTERN (A) DEFINE A AS id > 0) "
132+
+ "TABLESAMPLE SYSTEM (10 PERCENT)"
133+
})
134+
void serializeOtherSampleClauseOwners(String sql) throws Exception {
135+
PlainSelect original = (PlainSelect) CCJSqlParserUtil.parse(sql);
136+
PlainSelect copy = roundTrip(original);
137+
assertSampleClause(new SampleClause("TABLESAMPLE", "SYSTEM", 10L, "PERCENT", null, null),
138+
copy.getFromItem().getSampleClause());
139+
}
140+
141+
@Test
142+
void serializeSampleClauseAfterMutation() throws Exception {
143+
PlainSelect original = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(
144+
"SELECT * FROM events SAMPLE BLOCK (10) SEED (7)");
145+
SampleClause sample = original.getFromItem().getSampleClause();
146+
sample.setPercentageArgument(new BigDecimal("12.5"));
147+
sample.setSeedArgument(new BigDecimal("7.5"));
148+
PlainSelect copy = roundTrip(original);
149+
SampleClause copiedSample = copy.getFromItem().getSampleClause();
150+
assertSampleClause(new SampleClause("SAMPLE", "BLOCK", new BigDecimal("12.5"), null,
151+
null, new BigDecimal("7.5")), copiedSample);
152+
Assertions.assertNotSame(sample, copiedSample);
153+
sample.setSeedArgument(99L);
154+
Assertions.assertEquals(new BigDecimal("7.5"), copiedSample.getSeedArgument());
155+
}
156+
157+
@ParameterizedTest
158+
@ValueSource(strings = {"", " ON DELETE CASCADE", " ON DELETE NO ACTION"})
159+
void serializeSpannerInterleaveIn(String action) throws Exception {
160+
CreateTable original = (CreateTable) TestUtils.assertSqlCanBeParsedAndDeparsed(
161+
"CREATE TABLE child (id INT) PRIMARY KEY (id), INTERLEAVE IN PARENT parent"
162+
+ action);
163+
CreateTable copy = roundTrip(original);
164+
SpannerInterleaveIn interleave = copy.getSpannerInterleaveIn();
165+
Assertions.assertEquals("parent", interleave.getTable().getName());
166+
SpannerInterleaveIn.OnDelete expected = action.isEmpty() ? null
167+
: action.endsWith("CASCADE") ? SpannerInterleaveIn.OnDelete.CASCADE
168+
: SpannerInterleaveIn.OnDelete.NO_ACTION;
169+
Assertions.assertEquals(expected, interleave.getOnDelete());
170+
Assertions.assertEquals("child", copy.getTable().getName());
171+
Assertions.assertEquals("id", copy.getColumnDefinitions().get(0).getColumnName());
172+
Assertions.assertEquals("INT",
173+
copy.getColumnDefinitions().get(0).getColDataType().getDataType());
174+
original.getSpannerInterleaveIn().getTable().setName("changed");
175+
Assertions.assertEquals("parent", interleave.getTable().getName());
176+
}
177+
178+
@Test
179+
void serializeCombinedHelpers() throws Exception {
180+
PlainSelect original = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(
181+
"SELECT a.id FROM a TABLESAMPLE SYSTEM (10) INNER LOOP JOIN b "
182+
+ "ON a.id = b.id JOIN c ON b.id = c.id");
183+
PlainSelect copy = roundTrip(original);
184+
Assertions.assertEquals("LOOP", copy.getJoins().get(0).getJoinHint().getKeyword());
185+
assertSampleClause(new SampleClause("TABLESAMPLE", "SYSTEM", 10L, null, null, null),
186+
((Table) copy.getFromItem()).getSampleClause());
187+
Assertions.assertNull(((Table) copy.getJoins().get(0).getFromItem()).getSampleClause());
188+
Assertions.assertNull(copy.getJoins().get(1).getJoinHint());
189+
Assertions.assertNull(((Table) copy.getJoins().get(1).getFromItem()).getSampleClause());
190+
}
191+
192+
@Test
193+
void serializeSelectWithoutHelpers() throws Exception {
194+
PlainSelect original = (PlainSelect) TestUtils.assertSqlCanBeParsedAndDeparsed(
195+
"SELECT a.id FROM a INNER JOIN b ON a.id = b.id WHERE b.id > 0");
196+
PlainSelect copy = roundTrip(original);
197+
Assertions.assertNull(copy.getJoins().get(0).getJoinHint());
198+
Assertions.assertNull(((Table) copy.getFromItem()).getSampleClause());
199+
Assertions.assertEquals("b.id > 0", copy.getWhere().toString());
200+
}
201+
202+
@Test
203+
void serializeCreateTableWithoutInterleave() throws Exception {
204+
CreateTable original = (CreateTable) TestUtils.assertSqlCanBeParsedAndDeparsed(
205+
"CREATE TABLE ordinary (id INT)");
206+
CreateTable copy = roundTrip(original);
207+
Assertions.assertNull(copy.getSpannerInterleaveIn());
208+
Assertions.assertEquals("ordinary", copy.getTable().getName());
209+
Assertions.assertEquals("id", copy.getColumnDefinitions().get(0).getColumnName());
210+
}
211+
212+
private static void assertSampleClause(SampleClause expected, SampleClause actual) {
213+
Assertions.assertNotNull(actual);
214+
Assertions.assertEquals(expected.getKeyword(), actual.getKeyword());
215+
Assertions.assertEquals(expected.getMethod(), actual.getMethod());
216+
Assertions.assertEquals(expected.getPercentageArgument(), actual.getPercentageArgument());
217+
Assertions.assertEquals(expected.getPercentageUnit(), actual.getPercentageUnit());
218+
Assertions.assertEquals(expected.isArgumentInBrackets(), actual.isArgumentInBrackets());
219+
Assertions.assertEquals(expected.isMethodInBrackets(), actual.isMethodInBrackets());
220+
Assertions.assertEquals(expected.getOffsetArgument(), actual.getOffsetArgument());
221+
Assertions.assertEquals(expected.getRepeatArgument(), actual.getRepeatArgument());
222+
Assertions.assertEquals(expected.getSeedArgument(), actual.getSeedArgument());
223+
}
224+
225+
@SuppressWarnings("unchecked")
226+
private static <T extends Statement> T roundTrip(T original)
227+
throws IOException, ClassNotFoundException {
228+
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
229+
try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
230+
out.writeObject(original);
231+
}
232+
T copy;
233+
try (ObjectInputStream in =
234+
new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
235+
copy = (T) in.readObject();
236+
}
237+
Assertions.assertNotSame(original, copy);
238+
Assertions.assertEquals(original.toString(), copy.toString());
239+
return copy;
240+
}
241+
52242
}

0 commit comments

Comments
 (0)