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
16 changes: 8 additions & 8 deletions src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -429,10 +429,11 @@ public static Statements parseStatements(String sqls, Consumer<CCJSqlParser> con
}

ExecutorService executorService = Executors.newSingleThreadExecutor();
final Statements statements = parseStatements(sqls, executorService, consumer);
executorService.shutdown();

return statements;
try {
return parseStatements(sqls, executorService, consumer);
} finally {
executorService.shutdown();
}
}

/**
Expand All @@ -447,7 +448,6 @@ public static Statements parseStatements(String sqls, ExecutorService executorSe
return null;
}

Statements statements = null;
CCJSqlParser parser = newParser(sqls);
if (consumer != null) {
consumer.accept(parser);
Expand All @@ -457,7 +457,7 @@ public static Statements parseStatements(String sqls, ExecutorService executorSe

// first, try to parse fast and simple
try {
statements = parseStatements(parser.withAllowComplexParsing(false), executorService);
return parseStatements(parser.withAllowComplexParsing(false), executorService);
} catch (JSQLParserException ex) {
// when fast simple parsing fails, try complex parsing but only if it has a chance to
// succeed
Expand All @@ -468,10 +468,10 @@ public static Statements parseStatements(String sqls, ExecutorService executorSe
if (consumer != null) {
consumer.accept(parser);
}
statements = parseStatements(parser.withAllowComplexParsing(true), executorService);
return parseStatements(parser.withAllowComplexParsing(true), executorService);
}
throw ex;
}
return statements;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.parser;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.statement.UnsupportedStatement;
import org.junit.jupiter.api.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.junit.jupiter.api.Assertions.*;

class ParseStatementsFailureTest {
@Test
void reportsFailureWhenComplexParsingIsDisabled() {
JSQLParserException exception = assertThrows(JSQLParserException.class,
() -> CCJSqlParserUtil.parseStatements("SELECT FROM",
parser -> parser.withAllowComplexParsing(false)));
assertNotNull(exception.getCause());
}

@Test
void reportsFailureWhenNestingPreventsRetry() {
assertThrows(JSQLParserException.class,
() -> CCJSqlParserUtil.parseStatements("SELECT (( FROM",
parser -> parser.withAllowComplexParsing(true).withAllowedNestingDepth(0)));
}

@Test
void leavesCallerExecutorUsableAfterFailure() throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
assertThrows(JSQLParserException.class,
() -> CCJSqlParserUtil.parseStatements("SELECT FROM", executor,
parser -> parser.withAllowComplexParsing(false)));
assertFalse(executor.isShutdown());
assertEquals(2, CCJSqlParserUtil.parseStatements("SELECT 1; SELECT 2", executor,
parser -> parser.withAllowComplexParsing(false)).size());
} finally {
executor.shutdownNow();
}
}

@Test
void reportsTimeoutWhenComplexParsingIsDisabled() {
ExecutorService executor = Executors.newSingleThreadExecutor();
CountDownLatch release = new CountDownLatch(1);
executor.submit(() -> release.await(30, TimeUnit.SECONDS));
try {
JSQLParserException exception = assertThrows(JSQLParserException.class,
() -> CCJSqlParserUtil.parseStatements("SELECT 1", executor,
parser -> parser.withAllowComplexParsing(false).withTimeOut(50)));
assertInstanceOf(TimeoutException.class, exception.getCause());
} finally {
release.countDown();
executor.shutdownNow();
}
}

@Test
void preservesEmptyInputAndUnsupportedStatementContracts() throws Exception {
assertNull(CCJSqlParserUtil.parseStatements((String) null));
assertNull(CCJSqlParserUtil.parseStatements(""));
assertInstanceOf(UnsupportedStatement.class,
CCJSqlParserUtil.parseStatements("SELECT 1; WHATEVER !",
parser -> parser.withAllowComplexParsing(false)
.withUnsupportedStatements(true))
.get(1));
}
}
Loading