Skip to content

Unsupported statement #1519

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public P withSquareBracketQuotation(boolean allowSquareBracketQuotation) {
public P withAllowComplexParsing(boolean allowComplexParsing) {
return withFeature(Feature.allowComplexParsing, allowComplexParsing);
}

public P withUnsupportedStatements(boolean allowUnsupportedStatements) {
return withFeature(Feature.allowUnsupportedStatements, allowUnsupportedStatements);
}

public P withFeature(Feature f, boolean enabled) {
getConfiguration().setValue(f, enabled);
return me();
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,16 +271,31 @@ public Statement call() throws Exception {
* @return the statements parsed
*/
public static Statements parseStatements(String sqls) throws JSQLParserException {
return parseStatements(sqls, null);
}

/**
* Parse a statement list.
*
* @return the statements parsed
*/
public static Statements parseStatements(String sqls, Consumer<CCJSqlParser> consumer) throws JSQLParserException {
Statements statements = null;

// first, try to parse fast and simple
try {
CCJSqlParser parser = newParser(sqls).withAllowComplexParsing(false);
if (consumer != null) {
consumer.accept(parser);
}
statements = parseStatements(parser);
} catch (JSQLParserException ex) {
// when fast simple parsing fails, try complex parsing but only if it has a chance to succeed
if (getNestingDepth(sqls)<=ALLOWED_NESTING_DEPTH) {
CCJSqlParser parser = newParser(sqls).withAllowComplexParsing(true);
if (consumer != null) {
consumer.accept(parser);
}
statements = parseStatements(parser);
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/net/sf/jsqlparser/parser/feature/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,13 @@ public enum Feature {
* allows complex expression parameters or named parameters for functions
* will be switched off, when deep nesting of functions is detected
*/
allowComplexParsing(true)
allowComplexParsing(true),

/**
* allows passing through Unsupported Statements as a plain List of Tokens
* needs to be switched off, when VALIDATING statements or parsing blocks
*/
allowUnsupportedStatements(false),
;

private Object value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,6 @@ public interface StatementVisitor {
void visit(PurgeStatement purgeStatement);

void visit(AlterSystemStatement alterSystemStatement);

void visit(UnsupportedStatement unsupportedStatement);
}
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,9 @@ public void visit(PurgeStatement purgeStatement) {
@Override
public void visit(AlterSystemStatement alterSystemStatement) {
}

@Override
public void visit(UnsupportedStatement unsupportedStatement) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2021 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/

package net.sf.jsqlparser.statement;

import java.util.List;
import java.util.Objects;

/**
*
* @author <a href="mailto:andreas@manticore-projects.com">Andreas Reichel</a>
*/

public class UnsupportedStatement implements Statement {
private List<String> declarations;

public UnsupportedStatement(List<String> declarations) {
this.declarations = Objects.requireNonNull(declarations, "The List of Tokens must not be null.");
}

@Override
public void accept(StatementVisitor statementVisitor) {
statementVisitor.visit(this);
}

@SuppressWarnings({"PMD.MissingBreakInSwitch", "PMD.SwitchStmtsShouldHaveDefault", "PMD.CyclomaticComplexity"})
public StringBuilder appendTo(StringBuilder builder) {
int i=0;
for (String s:declarations) {
if (i>0) {
builder.append(" ");
}
builder.append(s);
i++;
}
return builder;
}

@Override
public String toString() {
return appendTo(new StringBuilder()).toString();
}

public boolean isEmpty() {
return declarations.isEmpty();
}
}
5 changes: 5 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,11 @@ public void visit(AlterSystemStatement alterSystemStatement) {
// no tables involved in this statement
}

@Override
public void visit(UnsupportedStatement unsupportedStatement) {
// no tables involved in this statement
}

@Override
public void visit(GeometryDistance geometryDistance) {
visitBinaryExpression(geometryDistance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.Statements;
import net.sf.jsqlparser.statement.UnsupportedStatement;
import net.sf.jsqlparser.statement.UseStatement;
import net.sf.jsqlparser.statement.alter.Alter;
import net.sf.jsqlparser.statement.alter.AlterSession;
Expand Down Expand Up @@ -373,4 +374,9 @@ public void visit(PurgeStatement purgeStatement) {
public void visit(AlterSystemStatement alterSystemStatement) {
alterSystemStatement.appendTo(buffer);
}

@Override
public void visit(UnsupportedStatement unsupportedStatement) {
unsupportedStatement.appendTo(buffer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.Statements;
import net.sf.jsqlparser.statement.UnsupportedStatement;
import net.sf.jsqlparser.statement.UseStatement;
import net.sf.jsqlparser.statement.alter.Alter;
import net.sf.jsqlparser.statement.alter.AlterSession;
Expand Down Expand Up @@ -303,4 +304,9 @@ public void visit(PurgeStatement purgeStatement) {
public void visit(AlterSystemStatement alterSystemStatement) {
//TODO: not yet implemented
}

@Override
public void visit(UnsupportedStatement unsupportedStatement) {

}
}
87 changes: 71 additions & 16 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ Statement Statement() #Statement:
stm = SingleStatement() { ifElseStatement = new IfElseStatement(condition, stm); }
[ <ST_SEMICOLON> { ifElseStatement.setUsingSemicolonForIfStatement(true); } ]
[ LOOKAHEAD(2)
<K_ELSE> stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); }
<K_ELSE> stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); }
[ <ST_SEMICOLON> { ifElseStatement.setUsingSemicolonForElseStatement(true); }]
]
<EOF>
Expand All @@ -519,6 +519,8 @@ Statement Statement() #Statement:
[ <ST_SEMICOLON> ]
<EOF>
)
|
LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) stm = UnsupportedStatement()
} catch (ParseException e) {
if (errorRecovery) {
parseErrors.add(e);
Expand Down Expand Up @@ -655,10 +657,27 @@ Block Block() #Block : {
}
{
<K_BEGIN>
(<ST_SEMICOLON>)*
(<ST_SEMICOLON>)*
try {
(stm = SingleStatement() | stm = Block()) { list.add(stm); } <ST_SEMICOLON>
( (stm = SingleStatement() | stm = Block()) <ST_SEMICOLON> { list.add(stm); } )*
(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest I find your version much harder to read.

(
stm = SingleStatement()
| stm = Block()
)
<ST_SEMICOLON>
{ list.add(stm); }
)

(
(
(
stm = SingleStatement()
| stm = Block()
)
<ST_SEMICOLON>
{ list.add(stm); }
)
)*
} catch (ParseException e) {
if (errorRecovery) {
parseErrors.add(e);
Expand All @@ -667,11 +686,13 @@ Block Block() #Block : {
throw e;
}
}

{
stmts.setStatements(list);
block.setStatements(stmts);
}
<K_END>

<K_END> [LOOKAHEAD(2) <ST_SEMICOLON>]
{
return block;
}
Expand Down Expand Up @@ -707,33 +728,40 @@ Statements Statements() #Statements : {

[ LOOKAHEAD(2) <ST_SEMICOLON> ]
) { list.add(stm); }
|
LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) stm = UnsupportedStatement()
{ if ( !((UnsupportedStatement) stm).isEmpty() ) list.add(stm); }
)


(
<ST_SEMICOLON> { if (stm2!=null)
ifElseStatement.setUsingSemicolonForElseStatement(true);
else if (ifElseStatement!=null)
ifElseStatement.setUsingSemicolonForIfStatement(true); }
(
<ST_SEMICOLON> { if (stm2!=null)
ifElseStatement.setUsingSemicolonForElseStatement(true);
else if (ifElseStatement!=null)
ifElseStatement.setUsingSemicolonForIfStatement(true); }
[
(
<K_IF> condition=Condition()
<K_IF> condition=Condition()
stm = SingleStatement() { ifElseStatement = new IfElseStatement(condition, stm); }
[ LOOKAHEAD(2)
[ LOOKAHEAD(2)
[ <ST_SEMICOLON> { ifElseStatement.setUsingSemicolonForIfStatement(true); } ]
<K_ELSE> stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); }
<K_ELSE> stm2 = SingleStatement() { ifElseStatement.setElseStatement(stm2); }
]

{ list.add( ifElseStatement ); }
)
|
(
stm = SingleStatement()
stm = SingleStatement()
| stm = Block()

[ LOOKAHEAD(2) <ST_SEMICOLON> ]
) { list.add(stm); }
]
|
// For any reason, we can't LOOKAHEAD( { getAsBoolean(Feature.allowUnsupportedStatements) } ) here
// As it will result in a Stack Overflow
stm = UnsupportedStatement()
{ if ( !((UnsupportedStatement) stm).isEmpty() ) list.add(stm); }
]
)*
<EOF>
} catch (ParseException e) {
Expand Down Expand Up @@ -6286,6 +6314,17 @@ Synonym Synonym() #Synonym :
}
}

UnsupportedStatement UnsupportedStatement():
{
List<String> tokens = new LinkedList<String>();
}
{
tokens=captureUnsupportedStatementDeclaration()
{
return new UnsupportedStatement(tokens);
}
}

JAVACODE
List<String> captureRest() {
List<String> tokens = new LinkedList<String>();
Expand All @@ -6300,3 +6339,19 @@ List<String> captureRest() {
}
return tokens;
}

JAVACODE
List<String> captureUnsupportedStatementDeclaration() {
List<String> tokens = new LinkedList<String>();
Token tok;

while(true) {
tok = getToken(1);
if( tok.kind == EOF || tok.kind== ST_SEMICOLON || tok.kind== K_END ) {
break;
}
tokens.add(tok.image);
tok = getNextToken();
}
return tokens;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

public class CCJSqlParserUtilTest {
Expand Down Expand Up @@ -160,7 +162,10 @@ public void accept(Statement statement) {
}

@Test
@Disabled
public void testParseStatementsFail() throws Exception {
// This will not fail, but always return the Unsupported Statements
// Since we can't LOOKAHEAD in the Statements() production
assertThrows(JSQLParserException.class, () -> CCJSqlParserUtil.parseStatements("select * from dual;WHATEVER!!"));
}

Expand Down
Loading