Skip to content
Merged
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
47 changes: 26 additions & 21 deletions src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,14 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.Select;

/**
* An {@code EXPLAIN} statement
*/
public class ExplainStatement implements Statement {
private String keyword;
private Select select;
private Statement statement;
private LinkedHashMap<OptionType, Option> options;
private Table table;

Expand All @@ -37,24 +35,17 @@ public ExplainStatement() {
public ExplainStatement(String keyword, Table table) {
this.keyword = keyword;
this.table = table;
this.select = null;
}

public ExplainStatement(String keyword, Select select, List<Option> optionList) {
public ExplainStatement(String keyword, Statement statement, List<Option> optionList) {
this.keyword = keyword;
this.select = select;
this.table = null;
setStatement(statement);

if (optionList != null && !optionList.isEmpty()) {
options = new LinkedHashMap<>();
for (Option o : optionList) {
options.put(o.getType(), o);
}
}
initializeOptions(optionList);
}

public ExplainStatement(Select select) {
this("EXPLAIN", select, null);
public ExplainStatement(Statement statement) {
this("EXPLAIN", statement, null);
}

public Table getTable() {
Expand All @@ -63,15 +54,20 @@ public Table getTable() {

public ExplainStatement setTable(Table table) {
this.table = table;
if (table != null) {
this.statement = null;
}
return this;
}

public Select getStatement() {
return select;
public Statement getStatement() {
return statement;
}

public void setStatement(Select select) {
this.select = select;
public ExplainStatement setStatement(Statement statement) {
this.table = null;
this.statement = statement;
return this;
}

public LinkedHashMap<OptionType, Option> getOptions() {
Expand Down Expand Up @@ -122,8 +118,8 @@ public String toString() {
}

builder.append(" ");
if (select != null) {
select.appendTo(builder);
if (statement != null) {
builder.append(statement);
}
}

Expand All @@ -135,6 +131,15 @@ public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
return statementVisitor.visit(this, context);
}

private void initializeOptions(List<Option> optionList) {
if (optionList != null && !optionList.isEmpty()) {
options = new LinkedHashMap<>();
for (Option o : optionList) {
options.put(o.getType(), o);
}
}
}

public enum OptionType {
ANALYZE, VERBOSE, COSTS, BUFFERS, FORMAT, PLAN, PLAN_FOR;

Expand Down
16 changes: 13 additions & 3 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -2359,7 +2359,8 @@ DescribeStatement Describe(): {
ExplainStatement Explain():
{
Token tk;
Select select;
Statement statement;
List<WithItem<?>> with = null;
Table table;
List<ExplainStatement.Option> options;
ExplainStatement es;
Expand All @@ -2369,9 +2370,18 @@ ExplainStatement Explain():
(
LOOKAHEAD(3)(
options= ExplainStatementOptions()
select = Select( )
(
[ LOOKAHEAD(2) with=WithList() ]
(
statement = SelectWithWithItems( with )
| statement = InsertWithWithItems( with )
| statement = UpdateWithWithItems( with )
| statement = DeleteWithWithItems( with )
| statement = Merge( with )
)
)
{
es = new ExplainStatement(tk.image, select, options);
es = new ExplainStatement(tk.image, statement, options);
}
)
|
Expand Down
36 changes: 34 additions & 2 deletions src/test/java/net/sf/jsqlparser/statement/ExplainTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
*/
package net.sf.jsqlparser.statement;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import static net.sf.jsqlparser.test.TestUtils.*;
import static org.assertj.core.api.Assertions.assertThat;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.delete.Delete;
import org.junit.jupiter.api.Test;

public class ExplainTest {
Expand Down Expand Up @@ -72,4 +74,34 @@ public void getOption_returnsValues() throws JSQLParserException {
explain = (ExplainStatement) CCJSqlParserUtil.parse("EXPLAIN SELECT * FROM mytable");
assertThat(explain.getOption(ExplainStatement.OptionType.ANALYZE)).isNull();
}

@Test
public void testDelete() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("EXPLAIN DELETE FROM mytable");
}

@Test
public void testUpdate() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("EXPLAIN UPDATE mytable SET col = 1");
}

@Test
public void testInsert() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("EXPLAIN INSERT INTO mytable (col) VALUES (1)");
}

@Test
public void explainDelete_usesGenericStatementSlot() throws JSQLParserException {
ExplainStatement explain =
(ExplainStatement) CCJSqlParserUtil.parse("EXPLAIN DELETE FROM mytable");
assertThat(explain.getStatement()).isInstanceOf(Delete.class);
}

@Test
public void testDeleteInStatementsList() throws JSQLParserException {
Statements statements = CCJSqlParserUtil.parseStatements("EXPLAIN DELETE FROM mytable;");
assertThat(statements).isNotNull();
assertThat(statements).hasSize(1);
assertThat(statements.get(0)).isInstanceOf(ExplainStatement.class);
}
}