Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 137 additions & 4 deletions src/main/java/net/sf/jsqlparser/statement/analyze/Analyze.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,167 @@
*/
package net.sf.jsqlparser.statement.analyze;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;

public class Analyze implements Statement {

private Table table;
public enum Modifier {
NO_WRITE_TO_BINLOG, LOCAL
}

public enum HistogramAction {
UPDATE, DROP
}

private final List<Table> tables = new ArrayList<>();
private boolean tableKeyword;
private Modifier modifier;
private HistogramAction histogramAction;
private final List<Column> histogramColumns = new ArrayList<>();
private Integer histogramBucketCount;

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

public Table getTable() {
return table;
return tables.isEmpty() ? null : tables.get(0);
}

public void setTable(Table table) {
this.table = table;
tables.clear();
if (table != null) {
tables.add(table);
}
}

public List<Table> getTables() {
return Collections.unmodifiableList(tables);
}

public void setTables(Collection<? extends Table> tables) {
this.tables.clear();
if (tables != null) {
this.tables.addAll(tables);
}
}

public boolean isTableKeyword() {
return tableKeyword;
}

public void setTableKeyword(boolean tableKeyword) {
this.tableKeyword = tableKeyword;
}

public Modifier getModifier() {
return modifier;
}

public void setModifier(Modifier modifier) {
this.modifier = modifier;
}

public HistogramAction getHistogramAction() {
return histogramAction;
}

public void setHistogramAction(HistogramAction histogramAction) {
this.histogramAction = histogramAction;
}

public List<Column> getHistogramColumns() {
return Collections.unmodifiableList(histogramColumns);
}

public void setHistogramColumns(Collection<? extends Column> columns) {
histogramColumns.clear();
if (columns != null) {
histogramColumns.addAll(columns);
}
}

public Integer getHistogramBucketCount() {
return histogramBucketCount;
}

public void setHistogramBucketCount(Integer histogramBucketCount) {
this.histogramBucketCount = histogramBucketCount;
}

@Override
public String toString() {
return "ANALYZE " + table.toString();
StringBuilder builder = new StringBuilder("ANALYZE");
if (modifier != null) {
builder.append(" ").append(modifier);
}
if (tableKeyword) {
builder.append(" TABLE");
}
builder.append(" ").append(tables.stream().map(Table::toString)
.collect(Collectors.joining(", ")));
if (histogramAction != null) {
builder.append(" ").append(histogramAction).append(" HISTOGRAM ON ")
.append(histogramColumns.stream().map(Column::toString)
.collect(Collectors.joining(", ")));
if (histogramBucketCount != null) {
builder.append(" WITH ").append(histogramBucketCount).append(" BUCKETS");
}
}
return builder.toString();
}

public Analyze withTable(Table table) {
this.setTable(table);
return this;
}

public Analyze withTables(Collection<? extends Table> tables) {
setTables(tables);
return this;
}

public Analyze addTables(Table... tables) {
Collections.addAll(this.tables, tables);
return this;
}

public Analyze withTableKeyword(boolean tableKeyword) {
setTableKeyword(tableKeyword);
return this;
}

public Analyze withModifier(Modifier modifier) {
setModifier(modifier);
return this;
}

public Analyze withHistogramAction(HistogramAction histogramAction) {
setHistogramAction(histogramAction);
return this;
}

public Analyze withHistogramColumns(Collection<? extends Column> columns) {
setHistogramColumns(columns);
return this;
}

public Analyze addHistogramColumns(Column... columns) {
Collections.addAll(histogramColumns, columns);
return this;
}

public Analyze withHistogramBucketCount(Integer histogramBucketCount) {
setHistogramBucketCount(histogramBucketCount);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1491,7 +1491,7 @@ public void visit(Insert insert) {

@Override
public <S> Void visit(Analyze analyze, S context) {
visit(analyze.getTable(), context);
analyze.getTables().forEach(table -> visit(table, context));
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,7 @@ public <S> StringBuilder visit(Update update, S context) {
}

public <S> StringBuilder visit(Analyze analyzer, S context) {
builder.append("ANALYZE ");
builder.append(analyzer.getTable());
builder.append(analyzer);
return builder;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public class AnalyzeValidator extends AbstractValidator<Analyze> {
public void validate(Analyze analyze) {
for (ValidationCapability c : getCapabilities()) {
validateFeature(c, Feature.analyze);
validateName(c, NamedObject.table, analyze.getTable().getFullyQualifiedName(), true);
analyze.getTables().forEach(table -> validateName(c, NamedObject.table,
table.getFullyQualifiedName(), true));
}
}
}
35 changes: 32 additions & 3 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,7 @@ String NonReservedWord() :
| tk=<K_BREADTH:"BREADTH">
| tk=<K_BRANCH:"BRANCH">
| tk=<K_BROWSE:"BROWSE">
| tk=<K_BUCKETS:"BUCKETS">
| tk=<K_BY:"BY">
| tk=<K_BYTES: "BYTES">
| tk=<K_CACHE: "CACHE">
Expand Down Expand Up @@ -1592,6 +1593,7 @@ String NonReservedWord() :
| tk=<K_HIGH : "HIGH">
| tk=<K_HIGH_PRIORITY : "HIGH_PRIORITY">
| tk=<K_HISTORY : "HISTORY">
| tk=<K_HISTOGRAM: "HISTOGRAM">
| tk=<K_HOPPING:"HOPPING">
| tk=<K_IDENTIFIED:"IDENTIFIED">
| tk=<K_IDENTITY:"IDENTITY">
Expand Down Expand Up @@ -1666,6 +1668,7 @@ String NonReservedWord() :
| tk=<K_NOCACHE:"NOCACHE">
| tk=<K_NOKEEP:"NOKEEP">
| tk=<K_NOLOCK:"NOLOCK">
| tk=<K_NO_WRITE_TO_BINLOG:"NO_WRITE_TO_BINLOG">
| tk=<K_NOMAXVALUE:"NOMAXVALUE">
| tk=<K_NOMINVALUE:"NOMINVALUE">
| tk=<K_NONE:"NONE">
Expand Down Expand Up @@ -11958,14 +11961,40 @@ Analyze Analyze():
{
Analyze analyze = new Analyze();
Table table = null;
Column column = null;
Token modifier = null;
Token histogramAction = null;
Token bucketCount = null;
}
{
<K_ANALYZE>
table=Table()
[
LOOKAHEAD(2)
(modifier=<K_NO_WRITE_TO_BINLOG> | modifier=<K_LOCAL>)
{ analyze.setModifier(Analyze.Modifier.valueOf(modifier.image.toUpperCase(Locale.ROOT))); }
]
[ LOOKAHEAD(2) <K_TABLE> { analyze.setTableKeyword(true); } ]
table=Table() { analyze.addTables(table); }
( "," table=Table() { analyze.addTables(table); } )*
[
LOOKAHEAD(2)
(histogramAction=<K_UPDATE> | histogramAction=<K_DROP>)
{
analyze.setHistogramAction(Analyze.HistogramAction.valueOf(
histogramAction.image.toUpperCase(Locale.ROOT)));
}
<K_HISTOGRAM> <K_ON>
column=Column() { analyze.addHistogramColumns(column); }
( "," column=Column() { analyze.addHistogramColumns(column); } )*
[
LOOKAHEAD(3)
<K_WITH> bucketCount=<S_LONG> <K_BUCKETS>
{ analyze.setHistogramBucketCount(Integer.valueOf(bucketCount.image)); }
]
]

{
analyze.setTable(table);
return analyze;
return analyze;
}
}

Expand Down
57 changes: 51 additions & 6 deletions src/test/java/net/sf/jsqlparser/statement/analyze/AnalyzeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@
*/
package net.sf.jsqlparser.statement.analyze;

import static net.sf.jsqlparser.test.TestUtils.assertDeparse;
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.StringReader;
import java.util.List;
import java.util.stream.Collectors;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import org.junit.jupiter.api.Test;

import java.io.StringReader;

import static net.sf.jsqlparser.test.TestUtils.assertDeparse;
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class AnalyzeTest {

private final CCJSqlParserManager parserManager = new CCJSqlParserManager();
Expand All @@ -38,4 +40,47 @@ public void testAnalyze() throws JSQLParserException {
public void testAnalyze2() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("ANALYZE mytable");
}

@Test
public void testMySqlAnalyzeTableList() throws JSQLParserException {
String sql = "ANALYZE TABLE t2, t3";
Analyze analyze = (Analyze) parserManager.parse(new StringReader(sql));

assertEquals(List.of("t2", "t3"), analyze.getTables().stream()
.map(Table::getFullyQualifiedName).collect(Collectors.toList()));
assertEquals("t2", analyze.getTable().getFullyQualifiedName());
assertEquals(sql, analyze.toString());

assertDeparse(new Analyze().withTableKeyword(true)
.withTables(List.of(new Table("t2"), new Table("t3"))), sql);
}

@Test
public void testMySqlAnalyzeUpdateHistogram() throws JSQLParserException {
String sql = "ANALYZE TABLE t1 UPDATE HISTOGRAM ON c1, c2 WITH 64 BUCKETS";
Analyze analyze = (Analyze) assertSqlCanBeParsedAndDeparsed(sql);

assertEquals(Analyze.HistogramAction.UPDATE, analyze.getHistogramAction());
assertEquals(List.of("c1", "c2"), analyze.getHistogramColumns().stream()
.map(Column::getFullyQualifiedName).collect(Collectors.toList()));
assertEquals(64, analyze.getHistogramBucketCount());
}

@Test
public void testMySqlAnalyzeDropHistogram() throws JSQLParserException {
String sql = "ANALYZE LOCAL TABLE t2 DROP HISTOGRAM ON c1";
Analyze analyze = (Analyze) assertSqlCanBeParsedAndDeparsed(sql);

assertEquals(Analyze.Modifier.LOCAL, analyze.getModifier());
assertEquals(Analyze.HistogramAction.DROP, analyze.getHistogramAction());
assertEquals("c1", analyze.getHistogramColumns().get(0).getFullyQualifiedName());
}

@Test
public void testMySqlAnalyzeNoWriteToBinlog() throws JSQLParserException {
String sql = "ANALYZE NO_WRITE_TO_BINLOG TABLE t1";
Analyze analyze = (Analyze) assertSqlCanBeParsedAndDeparsed(sql);

assertEquals(Analyze.Modifier.NO_WRITE_TO_BINLOG, analyze.getModifier());
}
}
Loading