Skip to content

Commit a6aee0e

Browse files
committed
feat(parser): model MySQL ANALYZE TABLE
1 parent 4b89a35 commit a6aee0e

6 files changed

Lines changed: 223 additions & 17 deletions

File tree

‎src/main/java/net/sf/jsqlparser/statement/analyze/Analyze.java‎

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

12+
import java.util.ArrayList;
13+
import java.util.Collection;
14+
import java.util.Collections;
15+
import java.util.List;
16+
import java.util.stream.Collectors;
17+
import net.sf.jsqlparser.schema.Column;
1218
import net.sf.jsqlparser.schema.Table;
1319
import net.sf.jsqlparser.statement.Statement;
1420
import net.sf.jsqlparser.statement.StatementVisitor;
1521

1622
public class Analyze implements Statement {
1723

18-
private Table table;
24+
public enum Modifier {
25+
NO_WRITE_TO_BINLOG, LOCAL
26+
}
27+
28+
public enum HistogramAction {
29+
UPDATE, DROP
30+
}
31+
32+
private final List<Table> tables = new ArrayList<>();
33+
private boolean tableKeyword;
34+
private Modifier modifier;
35+
private HistogramAction histogramAction;
36+
private final List<Column> histogramColumns = new ArrayList<>();
37+
private Integer histogramBucketCount;
1938

2039
@Override
2140
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
2241
return statementVisitor.visit(this, context);
2342
}
2443

2544
public Table getTable() {
26-
return table;
45+
return tables.isEmpty() ? null : tables.get(0);
2746
}
2847

2948
public void setTable(Table table) {
30-
this.table = table;
49+
tables.clear();
50+
if (table != null) {
51+
tables.add(table);
52+
}
53+
}
54+
55+
public List<Table> getTables() {
56+
return Collections.unmodifiableList(tables);
57+
}
58+
59+
public void setTables(Collection<? extends Table> tables) {
60+
this.tables.clear();
61+
if (tables != null) {
62+
this.tables.addAll(tables);
63+
}
64+
}
65+
66+
public boolean isTableKeyword() {
67+
return tableKeyword;
68+
}
69+
70+
public void setTableKeyword(boolean tableKeyword) {
71+
this.tableKeyword = tableKeyword;
72+
}
73+
74+
public Modifier getModifier() {
75+
return modifier;
76+
}
77+
78+
public void setModifier(Modifier modifier) {
79+
this.modifier = modifier;
80+
}
81+
82+
public HistogramAction getHistogramAction() {
83+
return histogramAction;
84+
}
85+
86+
public void setHistogramAction(HistogramAction histogramAction) {
87+
this.histogramAction = histogramAction;
88+
}
89+
90+
public List<Column> getHistogramColumns() {
91+
return Collections.unmodifiableList(histogramColumns);
92+
}
93+
94+
public void setHistogramColumns(Collection<? extends Column> columns) {
95+
histogramColumns.clear();
96+
if (columns != null) {
97+
histogramColumns.addAll(columns);
98+
}
99+
}
100+
101+
public Integer getHistogramBucketCount() {
102+
return histogramBucketCount;
103+
}
104+
105+
public void setHistogramBucketCount(Integer histogramBucketCount) {
106+
this.histogramBucketCount = histogramBucketCount;
31107
}
32108

33109
@Override
34110
public String toString() {
35-
return "ANALYZE " + table.toString();
111+
StringBuilder builder = new StringBuilder("ANALYZE");
112+
if (modifier != null) {
113+
builder.append(" ").append(modifier);
114+
}
115+
if (tableKeyword) {
116+
builder.append(" TABLE");
117+
}
118+
builder.append(" ").append(tables.stream().map(Table::toString)
119+
.collect(Collectors.joining(", ")));
120+
if (histogramAction != null) {
121+
builder.append(" ").append(histogramAction).append(" HISTOGRAM ON ")
122+
.append(histogramColumns.stream().map(Column::toString)
123+
.collect(Collectors.joining(", ")));
124+
if (histogramBucketCount != null) {
125+
builder.append(" WITH ").append(histogramBucketCount).append(" BUCKETS");
126+
}
127+
}
128+
return builder.toString();
36129
}
37130

38131
public Analyze withTable(Table table) {
39132
this.setTable(table);
40133
return this;
41134
}
135+
136+
public Analyze withTables(Collection<? extends Table> tables) {
137+
setTables(tables);
138+
return this;
139+
}
140+
141+
public Analyze addTables(Table... tables) {
142+
Collections.addAll(this.tables, tables);
143+
return this;
144+
}
145+
146+
public Analyze withTableKeyword(boolean tableKeyword) {
147+
setTableKeyword(tableKeyword);
148+
return this;
149+
}
150+
151+
public Analyze withModifier(Modifier modifier) {
152+
setModifier(modifier);
153+
return this;
154+
}
155+
156+
public Analyze withHistogramAction(HistogramAction histogramAction) {
157+
setHistogramAction(histogramAction);
158+
return this;
159+
}
160+
161+
public Analyze withHistogramColumns(Collection<? extends Column> columns) {
162+
setHistogramColumns(columns);
163+
return this;
164+
}
165+
166+
public Analyze addHistogramColumns(Column... columns) {
167+
Collections.addAll(histogramColumns, columns);
168+
return this;
169+
}
170+
171+
public Analyze withHistogramBucketCount(Integer histogramBucketCount) {
172+
setHistogramBucketCount(histogramBucketCount);
173+
return this;
174+
}
42175
}

‎src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1491,7 +1491,7 @@ public void visit(Insert insert) {
14911491

14921492
@Override
14931493
public <S> Void visit(Analyze analyze, S context) {
1494-
visit(analyze.getTable(), context);
1494+
analyze.getTables().forEach(table -> visit(table, context));
14951495
return null;
14961496
}
14971497

‎src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,7 @@ public <S> StringBuilder visit(Update update, S context) {
263263
}
264264

265265
public <S> StringBuilder visit(Analyze analyzer, S context) {
266-
builder.append("ANALYZE ");
267-
builder.append(analyzer.getTable());
266+
builder.append(analyzer);
268267
return builder;
269268
}
270269

‎src/main/java/net/sf/jsqlparser/util/validation/validator/AnalyzeValidator.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public class AnalyzeValidator extends AbstractValidator<Analyze> {
1919
public void validate(Analyze analyze) {
2020
for (ValidationCapability c : getCapabilities()) {
2121
validateFeature(c, Feature.analyze);
22-
validateName(c, NamedObject.table, analyze.getTable().getFullyQualifiedName(), true);
22+
analyze.getTables().forEach(table -> validateName(c, NamedObject.table,
23+
table.getFullyQualifiedName(), true));
2324
}
2425
}
2526
}

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

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,7 @@ String NonReservedWord() :
14881488
| tk=<K_BREADTH:"BREADTH">
14891489
| tk=<K_BRANCH:"BRANCH">
14901490
| tk=<K_BROWSE:"BROWSE">
1491+
| tk=<K_BUCKETS:"BUCKETS">
14911492
| tk=<K_BY:"BY">
14921493
| tk=<K_BYTES: "BYTES">
14931494
| tk=<K_CACHE: "CACHE">
@@ -1592,6 +1593,7 @@ String NonReservedWord() :
15921593
| tk=<K_HIGH : "HIGH">
15931594
| tk=<K_HIGH_PRIORITY : "HIGH_PRIORITY">
15941595
| tk=<K_HISTORY : "HISTORY">
1596+
| tk=<K_HISTOGRAM: "HISTOGRAM">
15951597
| tk=<K_HOPPING:"HOPPING">
15961598
| tk=<K_IDENTIFIED:"IDENTIFIED">
15971599
| tk=<K_IDENTITY:"IDENTITY">
@@ -1666,6 +1668,7 @@ String NonReservedWord() :
16661668
| tk=<K_NOCACHE:"NOCACHE">
16671669
| tk=<K_NOKEEP:"NOKEEP">
16681670
| tk=<K_NOLOCK:"NOLOCK">
1671+
| tk=<K_NO_WRITE_TO_BINLOG:"NO_WRITE_TO_BINLOG">
16691672
| tk=<K_NOMAXVALUE:"NOMAXVALUE">
16701673
| tk=<K_NOMINVALUE:"NOMINVALUE">
16711674
| tk=<K_NONE:"NONE">
@@ -11958,14 +11961,40 @@ Analyze Analyze():
1195811961
{
1195911962
Analyze analyze = new Analyze();
1196011963
Table table = null;
11964+
Column column = null;
11965+
Token modifier = null;
11966+
Token histogramAction = null;
11967+
Token bucketCount = null;
1196111968
}
1196211969
{
1196311970
<K_ANALYZE>
11964-
table=Table()
11971+
[
11972+
LOOKAHEAD(2)
11973+
(modifier=<K_NO_WRITE_TO_BINLOG> | modifier=<K_LOCAL>)
11974+
{ analyze.setModifier(Analyze.Modifier.valueOf(modifier.image.toUpperCase(Locale.ROOT))); }
11975+
]
11976+
[ LOOKAHEAD(2) <K_TABLE> { analyze.setTableKeyword(true); } ]
11977+
table=Table() { analyze.addTables(table); }
11978+
( "," table=Table() { analyze.addTables(table); } )*
11979+
[
11980+
LOOKAHEAD(2)
11981+
(histogramAction=<K_UPDATE> | histogramAction=<K_DROP>)
11982+
{
11983+
analyze.setHistogramAction(Analyze.HistogramAction.valueOf(
11984+
histogramAction.image.toUpperCase(Locale.ROOT)));
11985+
}
11986+
<K_HISTOGRAM> <K_ON>
11987+
column=Column() { analyze.addHistogramColumns(column); }
11988+
( "," column=Column() { analyze.addHistogramColumns(column); } )*
11989+
[
11990+
LOOKAHEAD(3)
11991+
<K_WITH> bucketCount=<S_LONG> <K_BUCKETS>
11992+
{ analyze.setHistogramBucketCount(Integer.valueOf(bucketCount.image)); }
11993+
]
11994+
]
1196511995

1196611996
{
11967-
analyze.setTable(table);
11968-
return analyze;
11997+
return analyze;
1196911998
}
1197011999
}
1197112000

‎src/test/java/net/sf/jsqlparser/statement/analyze/AnalyzeTest.java‎

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

12+
import static net.sf.jsqlparser.test.TestUtils.assertDeparse;
13+
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
14+
import static org.junit.jupiter.api.Assertions.assertEquals;
15+
16+
import java.io.StringReader;
17+
import java.util.List;
1218
import net.sf.jsqlparser.JSQLParserException;
1319
import net.sf.jsqlparser.parser.CCJSqlParserManager;
20+
import net.sf.jsqlparser.schema.Column;
1421
import net.sf.jsqlparser.schema.Table;
1522
import org.junit.jupiter.api.Test;
1623

17-
import java.io.StringReader;
18-
19-
import static net.sf.jsqlparser.test.TestUtils.assertDeparse;
20-
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
21-
import static org.junit.jupiter.api.Assertions.assertEquals;
22-
2324
public class AnalyzeTest {
2425

2526
private final CCJSqlParserManager parserManager = new CCJSqlParserManager();
@@ -38,4 +39,47 @@ public void testAnalyze() throws JSQLParserException {
3839
public void testAnalyze2() throws JSQLParserException {
3940
assertSqlCanBeParsedAndDeparsed("ANALYZE mytable");
4041
}
42+
43+
@Test
44+
public void testMySqlAnalyzeTableList() throws JSQLParserException {
45+
String sql = "ANALYZE TABLE t2, t3";
46+
Analyze analyze = (Analyze) parserManager.parse(new StringReader(sql));
47+
48+
assertEquals(List.of("t2", "t3"), analyze.getTables().stream()
49+
.map(Table::getFullyQualifiedName).toList());
50+
assertEquals("t2", analyze.getTable().getFullyQualifiedName());
51+
assertEquals(sql, analyze.toString());
52+
53+
assertDeparse(new Analyze().withTableKeyword(true)
54+
.withTables(List.of(new Table("t2"), new Table("t3"))), sql);
55+
}
56+
57+
@Test
58+
public void testMySqlAnalyzeUpdateHistogram() throws JSQLParserException {
59+
String sql = "ANALYZE TABLE t1 UPDATE HISTOGRAM ON c1, c2 WITH 64 BUCKETS";
60+
Analyze analyze = (Analyze) assertSqlCanBeParsedAndDeparsed(sql);
61+
62+
assertEquals(Analyze.HistogramAction.UPDATE, analyze.getHistogramAction());
63+
assertEquals(List.of("c1", "c2"), analyze.getHistogramColumns().stream()
64+
.map(Column::getFullyQualifiedName).toList());
65+
assertEquals(64, analyze.getHistogramBucketCount());
66+
}
67+
68+
@Test
69+
public void testMySqlAnalyzeDropHistogram() throws JSQLParserException {
70+
String sql = "ANALYZE LOCAL TABLE t2 DROP HISTOGRAM ON c1";
71+
Analyze analyze = (Analyze) assertSqlCanBeParsedAndDeparsed(sql);
72+
73+
assertEquals(Analyze.Modifier.LOCAL, analyze.getModifier());
74+
assertEquals(Analyze.HistogramAction.DROP, analyze.getHistogramAction());
75+
assertEquals("c1", analyze.getHistogramColumns().get(0).getFullyQualifiedName());
76+
}
77+
78+
@Test
79+
public void testMySqlAnalyzeNoWriteToBinlog() throws JSQLParserException {
80+
String sql = "ANALYZE NO_WRITE_TO_BINLOG TABLE t1";
81+
Analyze analyze = (Analyze) assertSqlCanBeParsedAndDeparsed(sql);
82+
83+
assertEquals(Analyze.Modifier.NO_WRITE_TO_BINLOG, analyze.getModifier());
84+
}
4185
}

0 commit comments

Comments
 (0)