Skip to content

Commit 45f98f8

Browse files
Fix: DESC and EXPLAIN (#1933)
* Fix: DESC and EXPLAIN * Fix: DESC and EXPLAIN * add test
1 parent dce6a20 commit 45f98f8

File tree

11 files changed

+111
-34
lines changed

11 files changed

+111
-34
lines changed

src/main/java/net/sf/jsqlparser/parser/feature/Feature.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,14 @@ public enum Feature {
593593
* @see DescribeStatement
594594
*/
595595
describe,
596+
597+
/**
598+
* SQL "DESC" statement is allowed
599+
*
600+
* @see DescribeStatement
601+
*/
602+
desc,
603+
596604
/**
597605
* SQL "EXPLAIN" statement is allowed
598606
*

src/main/java/net/sf/jsqlparser/statement/DescribeStatement.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
public class DescribeStatement implements Statement {
1515

1616
private Table table;
17+
private String describeType;
1718

1819
public DescribeStatement() {
1920
// empty constructor
@@ -33,7 +34,7 @@ public void setTable(Table table) {
3334

3435
@Override
3536
public String toString() {
36-
return "DESCRIBE " + table.getFullyQualifiedName();
37+
return this.describeType + " " + table.getFullyQualifiedName();
3738
}
3839

3940
@Override
@@ -45,4 +46,13 @@ public DescribeStatement withTable(Table table) {
4546
this.setTable(table);
4647
return this;
4748
}
49+
50+
public String getDescribeType() {
51+
return describeType;
52+
}
53+
54+
public DescribeStatement setDescribeType(String describeType) {
55+
this.describeType = describeType;
56+
return this;
57+
}
4858
}

src/main/java/net/sf/jsqlparser/statement/ExplainStatement.java

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

12-
import net.sf.jsqlparser.statement.select.Select;
13-
1412
import java.io.Serializable;
1513
import java.util.LinkedHashMap;
1614
import java.util.stream.Collectors;
15+
import net.sf.jsqlparser.schema.Table;
16+
import net.sf.jsqlparser.statement.select.Select;
1717

1818
/**
1919
* An {@code EXPLAIN} statement
@@ -22,11 +22,21 @@ public class ExplainStatement implements Statement {
2222

2323
private Select select;
2424
private LinkedHashMap<OptionType, Option> options;
25+
private Table table;
2526

2627
public ExplainStatement() {
2728
// empty constructor
2829
}
2930

31+
public Table getTable() {
32+
return table;
33+
}
34+
35+
public ExplainStatement setTable(Table table) {
36+
this.table = table;
37+
return this;
38+
}
39+
3040
public ExplainStatement(Select select) {
3141
this.select = select;
3242
}
@@ -68,14 +78,21 @@ public Option getOption(OptionType optionType) {
6878
@Override
6979
public String toString() {
7080
StringBuilder statementBuilder = new StringBuilder("EXPLAIN");
71-
if (options != null) {
81+
if (table != null) {
82+
statementBuilder.append(" ").append(table);
83+
} else {
84+
if (options != null) {
85+
statementBuilder.append(" ");
86+
statementBuilder.append(options.values().stream().map(Option::formatOption)
87+
.collect(Collectors.joining(" ")));
88+
}
89+
7290
statementBuilder.append(" ");
73-
statementBuilder.append(options.values().stream().map(Option::formatOption)
74-
.collect(Collectors.joining(" ")));
91+
if (select != null) {
92+
statementBuilder.append(select.toString());
93+
}
7594
}
7695

77-
statementBuilder.append(" ");
78-
statementBuilder.append(select.toString());
7996
return statementBuilder.toString();
8097
}
8198

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,9 @@ public void visit(DescribeStatement describe) {
10671067

10681068
@Override
10691069
public void visit(ExplainStatement explain) {
1070-
explain.getStatement().accept((StatementVisitor) this);
1070+
if (explain.getStatement() != null) {
1071+
explain.getStatement().accept((StatementVisitor) this);
1072+
}
10711073
}
10721074

10731075
@Override

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
*/
1010
package net.sf.jsqlparser.util.deparser;
1111

12+
import java.util.Iterator;
13+
import java.util.List;
14+
import java.util.stream.Collectors;
1215
import net.sf.jsqlparser.statement.Block;
1316
import net.sf.jsqlparser.statement.Commit;
1417
import net.sf.jsqlparser.statement.CreateFunctionalStatement;
@@ -59,10 +62,6 @@
5962
import net.sf.jsqlparser.statement.update.Update;
6063
import net.sf.jsqlparser.statement.upsert.Upsert;
6164

62-
import java.util.Iterator;
63-
import java.util.List;
64-
import java.util.stream.Collectors;
65-
6665
public class StatementDeParser extends AbstractDeParser<Statement> implements StatementVisitor {
6766

6867
private final ExpressionDeParser expressionDeParser;
@@ -347,19 +346,25 @@ public void visit(Comment comment) {
347346

348347
@Override
349348
public void visit(DescribeStatement describe) {
350-
buffer.append("DESCRIBE ");
349+
buffer.append(describe.getDescribeType());
350+
buffer.append(" ");
351351
buffer.append(describe.getTable());
352352
}
353353

354354
@Override
355355
public void visit(ExplainStatement explain) {
356356
buffer.append("EXPLAIN ");
357-
if (explain.getOptions() != null) {
357+
if (explain.getTable() != null) {
358+
buffer.append(explain.getTable());
359+
} else if (explain.getOptions() != null) {
358360
buffer.append(explain.getOptions().values().stream()
359361
.map(ExplainStatement.Option::formatOption).collect(Collectors.joining(" ")));
360362
buffer.append(" ");
361363
}
362-
explain.getStatement().accept(this);
364+
if (explain.getStatement() != null) {
365+
explain.getStatement().accept(this);
366+
367+
}
363368
}
364369

365370
@Override

src/main/java/net/sf/jsqlparser/util/validation/feature/MySqlVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ public enum MySqlVersion implements Version {
115115

116116
// https://dev.mysql.com/doc/refman/8.0/en/describe.html
117117
Feature.describe,
118+
Feature.desc,
118119
// https://dev.mysql.com/doc/refman/8.0/en/explain.html
119120
Feature.explain,
120121
// https://dev.mysql.com/doc/refman/8.0/en/show.html

src/main/java/net/sf/jsqlparser/util/validation/validator/StatementValidator.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,16 @@ public void visit(Comment comment) {
209209
@Override
210210
public void visit(DescribeStatement describe) {
211211
validateFeature(Feature.describe);
212+
validateFeature(Feature.desc);
212213
validateOptionalFromItem(describe.getTable());
213214
}
214215

215216
@Override
216217
public void visit(ExplainStatement explain) {
217218
validateFeature(Feature.explain);
218-
explain.getStatement().accept(this);
219+
if (explain.getStatement() != null) {
220+
explain.getStatement().accept(this);
221+
}
219222
}
220223

221224

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

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,29 +1056,43 @@ PurgeStatement PurgeStatement(): {
10561056

10571057
DescribeStatement Describe(): {
10581058
Table table;
1059+
DescribeStatement stmt = new DescribeStatement();
1060+
Token tk = null;
10591061
} {
1060-
<K_DESCRIBE> table = Table()
1062+
(tk=<K_DESCRIBE> | tk=<K_DESC>)
1063+
table = Table() { stmt.setDescribeType(tk.image).setTable(table); }
10611064
{
1062-
return new DescribeStatement(table);
1065+
return stmt;
10631066
}
10641067
}
10651068

10661069
ExplainStatement Explain(): {
10671070
Select select;
1071+
Table table = null;
10681072
List<ExplainStatement.Option> options = null;
1073+
ExplainStatement es = new ExplainStatement();
10691074
} {
10701075
<K_EXPLAIN>
1071-
options=ExplainStatementOptions()
1072-
select = Select( )
1073-
{
1074-
ExplainStatement es = new ExplainStatement(select);
1075-
if(options != null && !options.isEmpty()) {
1076-
for(ExplainStatement.Option o : options) {
1077-
es.addOption(o);
1078-
}
1079-
}
1080-
return es;
1081-
}
1076+
(
1077+
LOOKAHEAD(3)(
1078+
options=ExplainStatementOptions()
1079+
select = Select( )
1080+
{
1081+
es.setStatement(select);
1082+
if (options != null && !options.isEmpty()) {
1083+
for(ExplainStatement.Option o : options) {
1084+
es.addOption(o);
1085+
}
1086+
}
1087+
}
1088+
)
1089+
|
1090+
(
1091+
table=Table( ) { es.setTable(table); }
1092+
)
1093+
1094+
)
1095+
{ return es; }
10821096
}
10831097

10841098
/**

src/test/java/net/sf/jsqlparser/statement/DescribeTest.java

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

12-
import net.sf.jsqlparser.JSQLParserException;
1312
import static net.sf.jsqlparser.test.TestUtils.*;
13+
14+
import net.sf.jsqlparser.JSQLParserException;
1415
import org.junit.jupiter.api.Test;
1516

1617
public class DescribeTest {
@@ -20,6 +21,12 @@ public void testDescribe() throws JSQLParserException {
2021
assertSqlCanBeParsedAndDeparsed("DESCRIBE foo.products");
2122
}
2223

24+
@Test
25+
public void testDescribeIssue1931() throws JSQLParserException {
26+
assertSqlCanBeParsedAndDeparsed("DESC table_name");
27+
assertSqlCanBeParsedAndDeparsed("EXPLAIN table_name");
28+
}
29+
2330
@Test
2431
public void testDescribeIssue1212() throws JSQLParserException {
2532
assertSqlCanBeParsedAndDeparsed("DESCRIBE file_azbs.productcategory.json");

src/test/java/net/sf/jsqlparser/util/validation/validator/StatementValidatorTest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,19 @@ public void testValidateCreateSchema() throws JSQLParserException {
2929

3030
@Test
3131
public void testValidateCreateSchemaNotAllowed() throws JSQLParserException {
32-
for (String sql : Arrays.asList("CREATE SCHEMA my_schema", "CREATE SCHEMA myschema AUTHORIZATION myauth")) {
32+
for (String sql : Arrays.asList("CREATE SCHEMA my_schema",
33+
"CREATE SCHEMA myschema AUTHORIZATION myauth")) {
3334
validateNotAllowed(sql, 1, 1, FeaturesAllowed.DML, Feature.createSchema);
3435
}
3536
}
3637

38+
@Test
39+
public void testValidateDescNoErrors() throws JSQLParserException {
40+
for (String sql : Arrays.asList("DESC table_name", "EXPLAIN table_name")) {
41+
validateNoErrors(sql, 1, DatabaseType.MYSQL);
42+
}
43+
}
44+
3745
@Test
3846
public void testValidateTruncate() throws JSQLParserException {
3947
validateNoErrors("TRUNCATE TABLE my_table", 1, DatabaseType.DATABASES);
@@ -53,7 +61,8 @@ public void testValidateBlock() throws JSQLParserException {
5361
@Test
5462
public void testValidateComment() throws JSQLParserException {
5563
for (String sql : Arrays.asList("COMMENT ON VIEW myschema.myView IS 'myComment'",
56-
"COMMENT ON COLUMN myTable.myColumn is 'Some comment'", "COMMENT ON TABLE table1 IS 'comment1'")) {
64+
"COMMENT ON COLUMN myTable.myColumn is 'Some comment'",
65+
"COMMENT ON TABLE table1 IS 'comment1'")) {
5766
validateNoErrors(sql, 1, DatabaseType.H2, DatabaseType.ORACLE, DatabaseType.POSTGRESQL);
5867
}
5968
}

src/test/resources/net/sf/jsqlparser/statement/select/oracle-tests/explain01.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ explain plan
1616
(select department_id from departments
1717
where location_id = 1700)
1818

19-
--@FAILURE: Encountered unexpected token: "plan" <S_IDENTIFIER> recorded first on Aug 3, 2021, 7:20:08 AM
19+
--@FAILURE: Encountered unexpected token: "plan" <S_IDENTIFIER> recorded first on Aug 3, 2021, 7:20:08 AM
20+
--@FAILURE: Encountered unexpected token: "set" "SET" recorded first on 2023年12月23日 下午1:38:33

0 commit comments

Comments
 (0)