This is an automated email from the ASF dual-hosted git repository.
terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 15e55e398f1 Fix PostgreSQL external regression script loading (#40126)
15e55e398f1 is described below
commit 15e55e398f10e860a7833d31151a6fd9b60925cb
Author: Liang Zhang <[email protected]>
AuthorDate: Sat Oct 10 13:41:43 2026 +0800
Fix PostgreSQL external regression script loading (#40126)
* Suppress routine Jev usage feedback in task reports
* Fix PostgreSQL external regression script loading
---
...ostgreSQLExternalTestParameterLoadTemplate.java | 398 +++++++++++++++++++++
.../StandardExternalTestParameterLoadTemplate.java | 81 -----
...reSQLExternalTestParameterLoadTemplateTest.java | 187 ++++++++++
.../postgresql/ExternalPostgreSQLParserIT.java | 4 +-
4 files changed, 587 insertions(+), 83 deletions(-)
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/dialect/PostgreSQLExternalTestParameterLoadTemplate.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/dialect/PostgreSQLExternalTestParameterLoadTemplate.java
new file mode 100644
index 00000000000..6c1f48507d7
--- /dev/null
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/dialect/PostgreSQLExternalTestParameterLoadTemplate.java
@@ -0,0 +1,398 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package
org.apache.shardingsphere.test.it.sql.parser.external.loader.template.dialect;
+
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CodePointBuffer;
+import org.antlr.v4.runtime.CodePointCharStream;
+import org.antlr.v4.runtime.ConsoleErrorListener;
+import org.antlr.v4.runtime.Lexer;
+import org.antlr.v4.runtime.LexerNoViableAltException;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.Interval;
+import
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.sql.parser.spi.DialectSQLParserFacade;
+import
org.apache.shardingsphere.test.it.sql.parser.external.ExternalSQLTestParameter;
+import
org.apache.shardingsphere.test.it.sql.parser.external.loader.template.ExternalTestParameterLoadTemplate;
+
+import java.nio.CharBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * External test parameter load template for PostgreSQL.
+ */
+public final class PostgreSQLExternalTestParameterLoadTemplate implements
ExternalTestParameterLoadTemplate {
+
+ @Override
+ public Collection<ExternalSQLTestParameter> load(final String
sqlCaseFileName, final List<String> sqlCaseFileContent,
+ final List<String>
resultFileContent, final String databaseType, final String reportType) {
+ List<ScriptStatement> statements = new
ScriptReader(sqlCaseFileContent, databaseType).read();
+ int[] echoes = findEchoes(statements, resultFileContent);
+ Collection<ExternalSQLTestParameter> result = new
ArrayList<>(statements.size());
+ for (int i = 0; i < statements.size(); i++) {
+ ScriptStatement statement = statements.get(i);
+ if (!statement.sql.isEmpty() && !hasNativeError(statement, i,
echoes, resultFileContent)) {
+ result.add(new ExternalSQLTestParameter(sqlCaseFileName +
(result.size() + 1), databaseType, statement.sql, reportType));
+ }
+ }
+ return result;
+ }
+
+ private int[] findEchoes(final List<ScriptStatement> statements, final
List<String> expectedLines) {
+ Map<String, List<Integer>> linePositions = IntStream.range(0,
expectedLines.size()).boxed().collect(Collectors.groupingBy(expectedLines::get));
+ Map<List<String>, Integer> occurrences =
statements.stream().collect(Collectors.toMap(each -> each.echo, each -> 1,
Integer::sum));
+ Map<List<String>, Iterator<Integer>> matches =
occurrences.entrySet().stream()
+ .collect(Collectors.toMap(Entry::getKey, entry ->
matchEcho(entry.getKey(), linePositions, expectedLines,
entry.getValue()).iterator()));
+ int[] result = new int[statements.size()];
+ Arrays.fill(result, -1);
+ int cursor = 0;
+ for (int i = 0; i < statements.size(); i++) {
+ List<String> echo = statements.get(i).echo;
+ Iterator<Integer> positions = matches.get(echo);
+ int position = positions.hasNext() ? positions.next() : -1;
+ if (position >= cursor) {
+ result[i] = position;
+ cursor = result[i] + echo.size();
+ }
+ }
+ return result;
+ }
+
+ private List<Integer> matchEcho(final List<String> echo, final Map<String,
List<Integer>> linePositions, final List<String> expectedLines, final int
occurrences) {
+ Collection<Integer> positions =
linePositions.getOrDefault(echo.get(0), Collections.emptyList());
+ List<Integer> result = positions.stream().mapToInt(each -> each)
+ .filter(each -> each + echo.size() <= expectedLines.size() &&
expectedLines.subList(each, each +
echo.size()).equals(echo)).boxed().collect(Collectors.toList());
+ return result.size() == occurrences ? result : Collections.emptyList();
+ }
+
+ private boolean hasNativeError(final ScriptStatement statement, final int
index, final int[] echoes, final List<String> expectedLines) {
+ if (!statement.filterable || echoes[index] < 0 || index + 1 <
echoes.length && echoes[index + 1] < 0) {
+ return false;
+ }
+ int end = index + 1 == echoes.length ? expectedLines.size() :
echoes[index + 1];
+ for (int i = echoes[index] + statement.echo.size(); i < end; i++) {
+ String line = expectedLines.get(i);
+ if (line.startsWith("NOTICE:") || line.startsWith("WARNING:") ||
line.startsWith("INFO:") || line.startsWith("LOG:") ||
line.startsWith("DEBUG:")) {
+ return false;
+ }
+ if (line.startsWith("ERROR:")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @RequiredArgsConstructor
+ private static final class ScriptStatement {
+
+ private final String sql;
+
+ private final List<String> echo;
+
+ private final boolean filterable;
+ }
+
+ private static final class ScriptReader extends BaseErrorListener {
+
+ private final List<String> lines;
+
+ private final DatabaseType databaseType;
+
+ private final CharStream input;
+
+ private final Lexer lexer;
+
+ private final int[] lineStarts;
+
+ private final boolean[] quotedLines;
+
+ private final List<ScriptStatement> statements = new ArrayList<>();
+
+ private int start = -1;
+
+ private int parentheses;
+
+ private int atomicBlocks;
+
+ private int caseBlocks;
+
+ private String previousKind = "";
+
+ private boolean firstToken = true;
+
+ private boolean copyStatement;
+
+ private boolean copyOutput;
+
+ private boolean pendingCopy;
+
+ private boolean unsafe;
+
+ private boolean clientBuffer;
+
+ private boolean echoAll = true;
+
+ private boolean clientStateKnown = true;
+
+ private ScriptReader(final List<String> lines, final String
databaseType) {
+ this.lines = lines;
+ this.databaseType = TypedSPILoader.getService(DatabaseType.class,
databaseType);
+ input =
CodePointCharStream.fromBuffer(CodePointBuffer.withChars(CharBuffer.wrap(String.join("\n",
lines).toCharArray())));
+ lexer = createLexer(input);
+ lexer.addErrorListener(this);
+ lineStarts = new int[lines.size()];
+ quotedLines = new boolean[lines.size()];
+ for (int i = 1; i < lineStarts.length; i++) {
+ lineStarts[i] = lineStarts[i - 1] + lines.get(i - 1).length()
+ 1;
+ }
+ }
+
+ @SneakyThrows(ReflectiveOperationException.class)
+ private Lexer createLexer(final CharStream characters) {
+ Lexer result = (Lexer)
DatabaseTypedSPILoader.getService(DialectSQLParserFacade.class,
databaseType).getLexerClass().getConstructor(CharStream.class).newInstance(characters);
+ result.removeErrorListener(ConsoleErrorListener.INSTANCE);
+ return result;
+ }
+
+ private List<ScriptStatement> read() {
+ for (Token token = lexer.nextToken(); Token.EOF !=
token.getType(); token = lexer.nextToken()) {
+ markQuotedLines(token);
+ if (Token.DEFAULT_CHANNEL != token.getChannel()) {
+ if (start < 0) {
+ statements.add(new ScriptStatement("",
getEcho(lineAt(token.getStartIndex()), lineAt(token.getStopIndex())), false));
+ }
+ continue;
+ }
+ String kind =
lexer.getVocabulary().getSymbolicName(token.getType());
+ if ("BACKSLASH_".equals(kind) &&
readCommand(token.getStartIndex())) {
+ continue;
+ }
+ if (start < 0) {
+ start = token.getStartIndex();
+ }
+ readBlock(kind, token);
+ readCopy(kind);
+ previousKind = kind;
+ if ("COLON_".equals(kind)) {
+ unsafe = true;
+ }
+ if ("SEMI_".equals(kind) && (clientBuffer || 0 == parentheses
&& 0 == atomicBlocks)) {
+ submit(token.getStopIndex() + 1, token.getStopIndex() + 1,
true);
+ }
+ }
+ if (start >= 0) {
+ submit(input.size(), input.size(), 0 == parentheses && 0 ==
atomicBlocks);
+ }
+ return statements;
+ }
+
+ private void markQuotedLines(final Token token) {
+ if (lexer.getLine() > token.getLine()) {
+ int lastLine = lineAt(token.getStopIndex());
+ for (int i = token.getLine(); i <= lastLine; i++) {
+ quotedLines[i] = true;
+ }
+ }
+ }
+
+ private List<String> getEcho(final int firstLine, final int lastLine) {
+ return IntStream.rangeClosed(firstLine, lastLine).filter(i ->
!lines.get(i).isEmpty() ||
quotedLines[i]).mapToObj(lines::get).collect(Collectors.toList());
+ }
+
+ private boolean readCommand(final int offset) {
+ int line = lineAt(offset);
+ int end = lineStarts[line] + lines.get(line).length();
+ String command = input.getText(Interval.of(offset + 1, end - 1));
+ if (command.startsWith(";")) {
+ unsafe = true;
+ clientBuffer = true;
+ firstToken = true;
+ previousKind = "";
+ seek(offset + 2);
+ return true;
+ }
+ String name = command.split("\\s|\\\\", 2)[0];
+ if (command.indexOf('\\') >= 0) {
+ unsafe = true;
+ clientBuffer = true;
+ return false;
+ }
+ if (Arrays.asList("g", "gx", "gset", "gexec").contains(name)) {
+ boolean copy = pendingCopy;
+ if (start >= 0) {
+ submit(offset, end, "g".equals(command.trim()) ||
"gset".equals(command.trim()));
+ } else {
+ statements.add(new ScriptStatement("", lines.subList(line,
line + 1), false));
+ }
+ if (!copy) {
+ seek(Math.min(input.size(), end + 1));
+ }
+ return true;
+ }
+ if (start >= 0) {
+ unsafe = true;
+ clientBuffer = true;
+ return false;
+ }
+ if ("copy".equals(name)) {
+ start = offset;
+ unsafe = true;
+ boolean copy = isCopyFromStdin(command);
+ pendingCopy = copy;
+ submit(end, end, false);
+ if (!copy) {
+ seek(Math.min(input.size(), end + 1));
+ }
+ return true;
+ }
+ statements.add(new ScriptStatement("", lines.subList(line, line +
1), false));
+ if (command.startsWith("set ECHO ")) {
+ echoAll = "all".equals(command.substring("set ECHO
".length()).trim());
+ } else if (!Arrays.asList("echo", "qecho").contains(name)) {
+ clientStateKnown = false;
+ }
+ seek(Math.min(input.size(), end + 1));
+ return true;
+ }
+
+ private boolean isCopyFromStdin(final String command) {
+ Lexer header =
createLexer(CodePointCharStream.fromBuffer(CodePointBuffer.withChars(CharBuffer.wrap(command.toCharArray()))));
+ int depth = 0;
+ boolean from = false;
+ for (Token token = header.nextToken(); Token.EOF !=
token.getType(); token = header.nextToken()) {
+ if (Token.DEFAULT_CHANNEL != token.getChannel()) {
+ continue;
+ }
+ String kind =
header.getVocabulary().getSymbolicName(token.getType());
+ if ("LP_".equals(kind)) {
+ depth++;
+ } else if ("RP_".equals(kind)) {
+ depth--;
+ } else if (0 == depth && "STDIN".equals(kind) && from) {
+ return true;
+ }
+ from = "FROM".equals(kind);
+ }
+ return false;
+ }
+
+ private void seek(final int offset) {
+ input.seek(offset);
+ if (offset < input.size()) {
+ int line = lineAt(offset);
+ lexer.setLine(line + 1);
+ lexer.setCharPositionInLine(offset - lineStarts[line]);
+ }
+ }
+
+ private int lineAt(final int offset) {
+ int index = Arrays.binarySearch(lineStarts, offset);
+ return index >= 0 ? index : -index - 2;
+ }
+
+ private void readBlock(final String kind, final Token token) {
+ if ("LP_".equals(kind)) {
+ parentheses++;
+ } else if ("RP_".equals(kind) && parentheses > 0) {
+ parentheses--;
+ } else if ("BEGIN".equals(previousKind) &&
"ATOMIC".equalsIgnoreCase(token.getText())) {
+ atomicBlocks++;
+ } else if (atomicBlocks > 0 && "CASE".equals(kind)) {
+ caseBlocks++;
+ } else if (atomicBlocks > 0 && "END".equals(kind)) {
+ if (caseBlocks > 0) {
+ caseBlocks--;
+ } else {
+ atomicBlocks--;
+ }
+ }
+ }
+
+ private void readCopy(final String kind) {
+ if (firstToken) {
+ copyStatement = "COPY".equals(kind);
+ firstToken = false;
+ }
+ if (copyStatement && 0 == parentheses &&
"FROM".equals(previousKind) && "STDIN".equals(kind)) {
+ pendingCopy = true;
+ }
+ if (copyStatement && 0 == parentheses && "TO".equals(previousKind)
&& "STDOUT".equals(kind)) {
+ copyOutput = true;
+ }
+ }
+
+ private void submit(final int sqlEnd, final int echoEnd, final boolean
filterable) {
+ int end = sqlEnd;
+ int firstLine = lineAt(start);
+ int lastLine = lineAt(echoEnd - 1);
+ boolean exclusive =
input.getText(Interval.of(lineStarts[firstLine], start - 1)).trim().isEmpty()
+ && input.getText(Interval.of(echoEnd, lineStarts[lastLine]
+ lines.get(lastLine).length() - 1)).trim().isEmpty();
+ if (pendingCopy) {
+ int marker = IntStream.range(lastLine + 1,
lines.size()).filter(i -> "\\.".equals(lines.get(i))).findFirst().orElse(-1);
+ if (marker < 0) {
+ end = input.size();
+ unsafe = true;
+ seek(input.size());
+ } else {
+ seek(Math.min(input.size(), lineStarts[marker] +
lines.get(marker).length() + 1));
+ }
+ }
+ statements.add(new
ScriptStatement(input.getText(Interval.of(start, end - 1)).trim(),
getEcho(firstLine, lastLine),
+ filterable && exclusive && !unsafe && !copyOutput &&
echoAll && clientStateKnown));
+ reset();
+ }
+
+ private void reset() {
+ start = -1;
+ parentheses = 0;
+ atomicBlocks = 0;
+ caseBlocks = 0;
+ previousKind = "";
+ firstToken = true;
+ copyStatement = false;
+ copyOutput = false;
+ pendingCopy = false;
+ unsafe = false;
+ clientBuffer = false;
+ }
+
+ @Override
+ public void syntaxError(final Recognizer<?, ?> recognizer, final
Object offendingSymbol, final int line, final int charPositionInLine, final
String msg, final RecognitionException ex) {
+ unsafe = true;
+ if (start < 0) {
+ start = ((LexerNoViableAltException) ex).getStartIndex();
+ }
+ }
+ }
+}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/type/StandardExternalTestParameterLoadTemplate.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/type/StandardExternalTestParameterLoadTemplate.java
deleted file mode 100644
index b9231c99ec4..00000000000
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/type/StandardExternalTestParameterLoadTemplate.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package
org.apache.shardingsphere.test.it.sql.parser.external.loader.template.type;
-
-import
org.apache.shardingsphere.test.it.sql.parser.external.ExternalSQLTestParameter;
-import
org.apache.shardingsphere.test.it.sql.parser.external.loader.SQLLineComment;
-import
org.apache.shardingsphere.test.it.sql.parser.external.loader.template.ExternalTestParameterLoadTemplate;
-
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Standard external test parameter load template.
- */
-public final class StandardExternalTestParameterLoadTemplate implements
ExternalTestParameterLoadTemplate {
-
- @Override
- public Collection<ExternalSQLTestParameter> load(final String
sqlCaseFileName, final List<String> sqlCaseFileContent,
- final List<String>
resultFileContent, final String databaseType, final String reportType) {
- Collection<ExternalSQLTestParameter> result = new LinkedList<>();
- String completedSQL = "";
- int sqlCaseEnum = 1;
- int statementLines = 0;
- int resultIndex = 0;
- boolean inProcedure = false;
- for (String each : sqlCaseFileContent) {
- inProcedure = isInProcedure(inProcedure, each.trim());
- completedSQL = getStatement(completedSQL, each.trim(),
inProcedure);
- statementLines = completedSQL.isEmpty() ? 0 : statementLines + 1;
- if (completedSQL.contains(";") && !inProcedure) {
- resultIndex = searchInResultContent(resultIndex,
resultFileContent, completedSQL, statementLines);
- if (resultIndex >= resultFileContent.size() ||
!resultFileContent.get(resultIndex).contains("ERROR")) {
- String sqlCaseId = sqlCaseFileName + sqlCaseEnum;
- result.add(new ExternalSQLTestParameter(sqlCaseId,
databaseType, completedSQL, reportType));
- sqlCaseEnum++;
- }
- completedSQL = "";
- statementLines = 0;
- }
- }
- return result;
- }
-
- private boolean isInProcedure(final boolean inProcedure, final String
statementLines) {
- if (statementLines.contains("{") && statementLines.contains("}")) {
- return inProcedure;
- }
- return (statementLines.contains("{") || statementLines.contains("}")
|| statementLines.contains("$$")) != inProcedure;
- }
-
- private String getStatement(final String completedSQL, final String
rawSQLLine, final boolean inProcedure) {
- return (rawSQLLine.isEmpty() || SQLLineComment.isComment(rawSQLLine))
&& !inProcedure ? "" : completedSQL + rawSQLLine + " ";
- }
-
- private int searchInResultContent(final int resultIndex, final
List<String> resultLines, final String completedSQL, final int statementLines) {
- int index = resultIndex;
- while (index < resultLines.size() &&
!completedSQL.startsWith(resultLines.get(index).trim())) {
- index++;
- }
- if (index != resultLines.size()) {
- return index + statementLines;
- }
- return resultIndex;
- }
-}
diff --git
a/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/dialect/PostgreSQLExternalTestParameterLoadTemplateTest.java
b/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/dialect/PostgreSQLExternalTestParameterLoadTemplateTest.java
new file mode 100644
index 00000000000..f442f4c3da7
--- /dev/null
+++
b/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/external/loader/template/dialect/PostgreSQLExternalTestParameterLoadTemplateTest.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package
org.apache.shardingsphere.test.it.sql.parser.external.loader.template.dialect;
+
+import
org.apache.shardingsphere.test.it.sql.parser.external.ExternalSQLTestParameter;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class PostgreSQLExternalTestParameterLoadTemplateTest {
+
+ private final PostgreSQLExternalTestParameterLoadTemplate template = new
PostgreSQLExternalTestParameterLoadTemplate();
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource({"sqlCases", "expectedCases"})
+ void assertLoadSQL(final String name, final String source, final String
expectedEcho, final Collection<String> expectedSQL) {
+ List<String> expectedFileContent = expectedEcho.isEmpty() ?
Collections.emptyList() : Arrays.asList(expectedEcho.split("\n", -1));
+ Collection<ExternalSQLTestParameter> actual = template.load("sample",
Arrays.asList(source.split("\n", -1)), expectedFileContent, "PostgreSQL",
"CSV");
+
assertThat(actual.stream().map(ExternalSQLTestParameter::getSql).collect(Collectors.toList()),
is(expectedSQL));
+
assertThat(actual.stream().map(ExternalSQLTestParameter::getSqlCaseId).collect(Collectors.toList()),
+ is(IntStream.rangeClosed(1, expectedSQL.size()).mapToObj(index
-> "sample" + index).collect(Collectors.toList())));
+ }
+
+ private static Stream<Arguments> sqlCases() {
+ return Stream.of(
+ Arguments.of("tagged dollar body", "DO $x$\nDECLARE\n foo
integer;\nBEGIN\n foo := 1;\nEND;\n$x$;\nSELECT 2;", "",
+ Arrays.asList("DO $x$\nDECLARE\n foo
integer;\nBEGIN\n foo := 1;\nEND;\n$x$;", "SELECT 2;")),
+ Arguments.of("nested dollar text", "DO $x$ BEGIN PERFORM
$y$foo;bar$y$; END $x$; SELECT 2;", "", Arrays.asList("DO $x$ BEGIN PERFORM
$y$foo;bar$y$; END $x$;", "SELECT 2;")),
+ Arguments.of("untagged dollar body", "CREATE FUNCTION foo()
RETURNS integer AS $$ BEGIN RETURN 1; END; $$ LANGUAGE plpgsql; SELECT 2;", "",
+ Arrays.asList("CREATE FUNCTION foo() RETURNS integer
AS $$ BEGIN RETURN 1; END; $$ LANGUAGE plpgsql;", "SELECT 2;")),
+ Arguments.of("single quoted body", "CREATE FUNCTION foo()
RETURNS integer AS 'BEGIN\nRETURN 1;\nEND' LANGUAGE plpgsql;\nSELECT 2;", "",
+ Arrays.asList("CREATE FUNCTION foo() RETURNS integer
AS 'BEGIN\nRETURN 1;\nEND' LANGUAGE plpgsql;", "SELECT 2;")),
+ Arguments.of("escaped single quote", "SELECT 'foo'';bar';
SELECT 2;", "", Arrays.asList("SELECT 'foo'';bar';", "SELECT 2;")),
+ Arguments.of("escape string", "SELECT E'foo\\';bar'; SELECT
2;", "", Arrays.asList("SELECT E'foo\\';bar';", "SELECT 2;")),
+ Arguments.of("quoted identifier", "SELECT \"foo;\"\"bar\";
SELECT 2;", "", Arrays.asList("SELECT \"foo;\"\"bar\";", "SELECT 2;")),
+ Arguments.of("line comment in statement",
"SELECT\n--foo;bar\n1;\nSELECT 2;", "", Arrays.asList("SELECT\n--foo;bar\n1;",
"SELECT 2;")),
+ Arguments.of("nested block comment", "SELECT /* foo; /* bar;
*/ baz; */ 1; SELECT 2;", "", Arrays.asList("SELECT /* foo; /* bar; */ baz; */
1;", "SELECT 2;")),
+ Arguments.of("blank line in statement", "SELECT\n\n -- foo\n
1;\nSELECT 2;", "", Arrays.asList("SELECT\n\n -- foo\n 1;", "SELECT 2;")),
+ Arguments.of("blank lines in quoted text", "SELECT
'foo\n\nbar', \"foo\n\nbar\", $x$foo\n\nbar$x$ /*foo\n\nbar*/;\nSELECT 2;", "",
+ Arrays.asList("SELECT 'foo\n\nbar', \"foo\n\nbar\",
$x$foo\n\nbar$x$ /*foo\n\nbar*/;", "SELECT 2;")),
+ Arguments.of("leading comments", "-- foo;\n/* bar; */\nSELECT
1;", "", Collections.singletonList("SELECT 1;")),
+ Arguments.of("same line statements", "SELECT 1; SELECT 2;
SELECT 3;", "", Arrays.asList("SELECT 1;", "SELECT 2;", "SELECT 3;")),
+ Arguments.of("atomic body with case", "CREATE FUNCTION foo()
RETURNS integer BEGIN ATOMIC SELECT CASE WHEN true THEN 1 ELSE 2 END; SELECT 3;
END; SELECT 4;", "",
+ Arrays.asList("CREATE FUNCTION foo() RETURNS integer
BEGIN ATOMIC SELECT CASE WHEN true THEN 1 ELSE 2 END; SELECT 3; END;", "SELECT
4;")),
+ Arguments.of("transaction begin", "BEGIN; SELECT 1; COMMIT;",
"", Arrays.asList("BEGIN;", "SELECT 1;", "COMMIT;")),
+ Arguments.of("unmatched closing parenthesis", "SELECT
);\nSELECT 2;", "", Arrays.asList("SELECT );", "SELECT 2;")),
+ Arguments.of("rule action parentheses", "CREATE RULE foo AS ON
INSERT TO bar DO ALSO (INSERT INTO baz VALUES (1); INSERT INTO baz VALUES (2));
SELECT 3;", "",
+ Arrays.asList("CREATE RULE foo AS ON INSERT TO bar DO
ALSO (INSERT INTO baz VALUES (1); INSERT INTO baz VALUES (2));", "SELECT 3;")),
+ Arguments.of("submit g", "SELECT 1 \\g\nSELECT 2;", "",
Arrays.asList("SELECT 1", "SELECT 2;")),
+ Arguments.of("submit gx", "SELECT 1 \\gx\nSELECT 2;", "",
Arrays.asList("SELECT 1", "SELECT 2;")),
+ Arguments.of("submit gset", "SELECT 1 \\gset\nSELECT 2;", "",
Arrays.asList("SELECT 1", "SELECT 2;")),
+ Arguments.of("submit gexec", "SELECT 1 \\gexec\nSELECT 2;",
"", Arrays.asList("SELECT 1", "SELECT 2;")),
+ Arguments.of("multiline submit", "SELECT\n 1\n\\gset\nSELECT
2;", "", Arrays.asList("SELECT\n 1", "SELECT 2;")),
+ Arguments.of("copy payload", "COPY foo FROM
STDIN;\nfoo';\n$x$;\n\\.\nSELECT 2;", "", Arrays.asList("COPY foo FROM STDIN;",
"SELECT 2;")),
+ Arguments.of("copy payload until eof", "COPY foo FROM
STDIN;\nfoo';\n$x$;", "", Collections.singletonList("COPY foo FROM
STDIN;\nfoo';\n$x$;")),
+ Arguments.of("copy submitted with g", "COPY foo FROM STDIN
\\g\nfoo';\n$x$;\n\\.\nSELECT 2;", "", Arrays.asList("COPY foo FROM STDIN",
"SELECT 2;")),
+ Arguments.of("copy submitted with g until eof", "COPY foo FROM
STDIN \\g\nfoo';\n$x$;", "", Collections.singletonList("COPY foo FROM STDIN
\\g\nfoo';\n$x$;")),
+ Arguments.of("client copy payload", "\\copy foo FROM
STDIN\nfoo';\n$x$;\n\\.\nSELECT 2;", "", Arrays.asList("\\copy foo FROM STDIN",
"SELECT 2;")),
+ Arguments.of("client copy payload until eof", "\\copy foo FROM
STDIN\nfoo';\n$x$;", "", Collections.singletonList("\\copy foo FROM
STDIN\nfoo';\n$x$;")),
+ Arguments.of("client copy query with stdin table", "\\copy
(SELECT * FROM stdin /*comment*/) TO STDOUT;\nSELECT 2;", "",
+ Arrays.asList("\\copy (SELECT * FROM stdin
/*comment*/) TO STDOUT;", "SELECT 2;")),
+ Arguments.of("client copy stdin table", "\\copy stdin TO
STDOUT\nSELECT 2;", "", Arrays.asList("\\copy stdin TO STDOUT", "SELECT 2;")),
+ Arguments.of("copy in multiple query buffer", "SELECT 1 \\;
COPY foo FROM STDIN;\nfoo';\n$x$;\n\\.\nSELECT 2;", "", Arrays.asList("SELECT 1
\\; COPY foo FROM STDIN;", "SELECT 2;")),
+ Arguments.of("copy in multiple query buffer until eof",
"SELECT 1 \\; COPY foo FROM STDIN;\nfoo';\n$x$;", "",
+ Collections.singletonList("SELECT 1 \\; COPY foo FROM
STDIN;\nfoo';\n$x$;")),
+ Arguments.of("stdin table in copy query", "COPY (SELECT * FROM
stdin) TO STDOUT;\nSELECT 2;", "", Arrays.asList("COPY (SELECT * FROM stdin) TO
STDOUT;", "SELECT 2;")),
+ Arguments.of("copy file paths", "COPY foo FROM
'/tmp/in';\nCOPY foo TO '/tmp/out';\nSELECT 3;", "", Arrays.asList("COPY foo
FROM '/tmp/in';", "COPY foo TO '/tmp/out';", "SELECT 3;")),
+ Arguments.of("psql variables", "SELECT :foo, :'bar', :\"baz\",
:{?qux}, $1, 1::integer;", "", Collections.singletonList("SELECT :foo, :'bar',
:\"baz\", :{?qux}, $1, 1::integer;")),
+ Arguments.of("unknown command in buffer", "SELECT 1\n\\unknown
foo\nSELECT 2;", "", Collections.singletonList("SELECT 1\n\\unknown foo\nSELECT
2;")),
+ Arguments.of("mixed commands in buffer", "SELECT 1 \\g \\echo
foo;\nSELECT 2;", "", Arrays.asList("SELECT 1 \\g \\echo foo;", "SELECT 2;")),
+ Arguments.of("unterminated sql", "SELECT\n 1", "",
Collections.singletonList("SELECT\n 1")),
+ Arguments.of("unclosed parenthesis at eof", "SELECT
(1;\nSELECT 2;", "", Collections.singletonList("SELECT (1;\nSELECT 2;")),
+ Arguments.of("unclosed atomic body at eof", "CREATE FUNCTION
foo() RETURNS integer BEGIN ATOMIC SELECT 1;\nSELECT 2;", "",
+ Collections.singletonList("CREATE FUNCTION foo()
RETURNS integer BEGIN ATOMIC SELECT 1;\nSELECT 2;")),
+ Arguments.of("unknown lexical character", "SELECT 1 " + (char)
1 + "; SELECT 2;", "", Arrays.asList("SELECT 1 " + (char) 1 + ";", "SELECT
2;")),
+ Arguments.of("unknown leading lexical character", (char) 127 +
"SELECT 1;\nSELECT 2;", "", Arrays.asList((char) 127 + "SELECT 1;", "SELECT
2;")),
+ Arguments.of("unicode offsets", "SELECT 'foo😀bar;'; SELECT
2;", "", Arrays.asList("SELECT 'foo😀bar;';", "SELECT 2;")),
+ Arguments.of("literal brace and dollar", "SELECT '{foo',
'}bar', '$$;'; SELECT 2;", "", Arrays.asList("SELECT '{foo', '}bar', '$$;';",
"SELECT 2;")));
+ }
+
+ private static Stream<Arguments> expectedCases() {
+ return Stream.of(
+ Arguments.of("blank is not echo anchor", "SELECT 1;\nSELECT
2;", "\nSELECT 1;\nERROR: foo\nSELECT 2;", Collections.singletonList("SELECT
2;")),
+ Arguments.of("notice before error", "DO $x$\nBEGIN\n RAISE
NOTICE 'foo';\n RAISE EXCEPTION 'bar';\nEND $x$;\nSELECT 2;",
+ "DO $x$\nBEGIN\n RAISE NOTICE 'foo';\n RAISE
EXCEPTION 'bar';\nEND $x$;\nNOTICE: foo\nERROR: bar\nSELECT 2;",
+ Arrays.asList("DO $x$\nBEGIN\n RAISE NOTICE 'foo';\n
RAISE EXCEPTION 'bar';\nEND $x$;", "SELECT 2;")),
+ Arguments.of("notice continuation with error text", "DO $$
BEGIN RAISE NOTICE E'foo\\nERROR: fake'; END $$;\nSELECT 2;",
+ "DO $$ BEGIN RAISE NOTICE E'foo\\nERROR: fake'; END
$$;\nNOTICE: foo\nERROR: fake\nSELECT 2;",
+ Arrays.asList("DO $$ BEGIN RAISE NOTICE E'foo\\nERROR:
fake'; END $$;", "SELECT 2;")),
+ Arguments.of("warning continuation with error text", "SELECT
1;\nSELECT 2;", "SELECT 1;\nWARNING: foo\nERROR: fake\nSELECT 2;",
Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("info continuation with error text", "SELECT
1;\nSELECT 2;", "SELECT 1;\nINFO: foo\nERROR: fake\nSELECT 2;",
Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("log continuation with error text", "SELECT
1;\nSELECT 2;", "SELECT 1;\nLOG: foo\nERROR: fake\nSELECT 2;",
Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("debug continuation with error text", "SELECT
1;\nSELECT 2;", "SELECT 1;\nDEBUG: foo\nERROR: fake\nSELECT 2;",
Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("multiline echo", "SELECT\n\n -- foo\n
1;\nSELECT 2;", "SELECT\n -- foo\n 1;\nERROR: bar\nSELECT 2;",
Collections.singletonList("SELECT 2;")),
+ Arguments.of("space only line in echo", "SELECT\n \n
1;\nSELECT 2;", "SELECT\n \n 1;\nERROR: foo\nSELECT 2;",
Collections.singletonList("SELECT 2;")),
+ Arguments.of("blank line in string echo", "SELECT
'foo\n\nbar';\nSELECT 2;", "SELECT 'foo\n\nbar';\nERROR: foo\nSELECT 2;",
Collections.singletonList("SELECT 2;")),
+ Arguments.of("blank line in identifier echo", "SELECT
\"foo\n\nbar\";\nSELECT 2;", "SELECT \"foo\n\nbar\";\nERROR: foo\nSELECT 2;",
Collections.singletonList("SELECT 2;")),
+ Arguments.of("blank line in comment echo", "SELECT
/*foo\n\nbar*/ 1;\nSELECT 2;", "SELECT /*foo\n\nbar*/ 1;\nERROR: foo\nSELECT
2;", Collections.singletonList("SELECT 2;")),
+ Arguments.of("blank line in dollar echo", "SELECT
$x$foo\n\nbar$x$;\nSELECT 2;", "SELECT $x$foo\n\nbar$x$;\nERROR: foo\nSELECT
2;", Collections.singletonList("SELECT 2;")),
+ Arguments.of("error in output literal", "SELECT 'ERROR' AS
foo;\nSELECT 2;", "SELECT 'ERROR' AS foo;\n foo\n-----\n ERROR\n(1 row)\nSELECT
2;",
+ Arrays.asList("SELECT 'ERROR' AS foo;", "SELECT 2;")),
+ Arguments.of("error in echoed string", "SELECT 'foo\nERROR:
bar\nbaz';\nSELECT 2;", "SELECT 'foo\nERROR: bar\nbaz';\n foo\nSELECT 2;",
+ Arrays.asList("SELECT 'foo\nERROR: bar\nbaz';",
"SELECT 2;")),
+ Arguments.of("copy output error literal", "COPY (SELECT
'ERROR: client text') TO STDOUT;\nSELECT 2;",
+ "COPY (SELECT 'ERROR: client text') TO STDOUT;\nERROR:
client text\nSELECT 2;", Arrays.asList("COPY (SELECT 'ERROR: client text') TO
STDOUT;", "SELECT 2;")),
+ Arguments.of("error in leading block comment", "SELECT
1;\n/*\nERROR: literal\n*/\nSELECT 2;", "SELECT 1;\n/*\nERROR:
literal\n*/\nSELECT 2;", Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("unresolved variables with error", "SELECT :foo,
:'foo', :\"foo\", :{?foo};\nSELECT 2;", "SELECT :foo, :'foo', :\"foo\",
:{?foo};\nERROR: bar\nSELECT 2;",
+ Arrays.asList("SELECT :foo, :'foo', :\"foo\",
:{?foo};", "SELECT 2;")),
+ Arguments.of("cast and parameter native error", "SELECT
$1::integer;\nSELECT 2;", "SELECT $1::integer;\nERROR: foo\nSELECT 2;",
Collections.singletonList("SELECT 2;")),
+ Arguments.of("array slice in rule action", "CREATE RULE foo AS
ON INSERT TO bar DO ALSO (SELECT a[1:2] FROM baz; SELECT 2);\nSELECT 3;",
+ "CREATE RULE foo AS ON INSERT TO bar DO ALSO (SELECT
a[1:2] FROM baz; SELECT 2);\nERROR: foo\nSELECT 3;",
+ Arrays.asList("CREATE RULE foo AS ON INSERT TO bar DO
ALSO (SELECT a[1:2] FROM baz; SELECT 2);", "SELECT 3;")),
+ Arguments.of("variable in atomic body", "CREATE FUNCTION foo()
RETURNS integer BEGIN ATOMIC SELECT :foo; SELECT 2; END;\nSELECT 3;",
+ "CREATE FUNCTION foo() RETURNS integer BEGIN ATOMIC
SELECT :foo; SELECT 2; END;\nERROR: foo\nSELECT 3;",
+ Arrays.asList("CREATE FUNCTION foo() RETURNS integer
BEGIN ATOMIC SELECT :foo; SELECT 2; END;", "SELECT 3;")),
+ Arguments.of("missing echo", "SELECT 1;\nSELECT 2;", "ERROR:
foo\nSELECT 2;", Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("reversed echo order", "SELECT 1;\nSELECT 2;",
"SELECT 2;\nERROR: foo\nSELECT 1;\nERROR: bar", Arrays.asList("SELECT 1;",
"SELECT 2;")),
+ Arguments.of("incomplete multiline echo", "SELECT\n
1;\nSELECT 2;", "SELECT", Arrays.asList("SELECT\n 1;", "SELECT 2;")),
+ Arguments.of("different multiline echo", "SELECT\n 1;\nSELECT
2;", "SELECT\n 2;\nERROR: foo\nSELECT 2;", Arrays.asList("SELECT\n 1;",
"SELECT 2;")),
+ Arguments.of("missing next echo", "SELECT 1;\nSELECT 2;",
"SELECT 1;\nERROR: foo", Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("echo prefix mismatch", "SELECT 12;\nSELECT 2;",
"SELECT 1;\nERROR: foo\nSELECT 2;", Arrays.asList("SELECT 12;", "SELECT 2;")),
+ Arguments.of("missing duplicate echo", "SELECT 1;\nSELECT 1;",
"SELECT 1;\nERROR: foo", Arrays.asList("SELECT 1;", "SELECT 1;")),
+ Arguments.of("shared echo line", "SELECT 1; SELECT 2;",
"SELECT 1; SELECT 2;\nERROR: foo", Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("repeated echo with context", "SELECT 1;\nSELECT
2;\nSELECT 1;", "SELECT 1;\n foo\nSELECT 2;\n bar\nSELECT 1;\nERROR: baz",
Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("repeated echo after rejected position", "SELECT
1;\nSELECT 2;\nSELECT 1;\nSELECT 1;", "SELECT 1;\nSELECT 1;\nSELECT 2;\nSELECT
1;\nERROR: foo",
+ Arrays.asList("SELECT 1;", "SELECT 2;", "SELECT 1;")),
+ Arguments.of("command response boundary", "SELECT 1;\n\\echo
foo\nSELECT 2;", "SELECT 1;\n\\echo foo\nERROR: client text\nSELECT 2;",
Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("empty query buffer submission", "SELECT
1;\n\\g\nSELECT 2;", "SELECT 1;\n\\g\nERROR: client text\nSELECT 2;",
Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("echo errors mode", "\\set ECHO errors\nSELECT
1;\n\\set ECHO all\nSELECT 2;", "\\set ECHO errors\nERROR: foo\nSTATEMENT:
SELECT 1;\nSELECT 2;",
+ Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("unaligned format after echo all", "\\pset format
unaligned\n\\set ECHO all\nSELECT 'ERROR: client text';",
+ "\\pset format unaligned\nOutput format is
unaligned.\n\\set ECHO all\nSELECT 'ERROR: client text';\n?column?\nERROR:
client text\n(1 row)",
+ Collections.singletonList("SELECT 'ERROR: client
text';")),
+ Arguments.of("printed query buffer", "SELECT 1;\n\\p\nSELECT
2;", "SELECT 1;\n foo\n\\p\nSELECT 1;\nERROR: client text\nSELECT 2;",
Arrays.asList("SELECT 1;", "SELECT 2;")),
+ Arguments.of("expanded field with error text", "SELECT 1 AS
\"ERROR:\" \\gx\nSELECT 2;", "SELECT 1 AS \"ERROR:\" \\gx\n-[ RECORD 1
]-\nERROR: | 1\nSELECT 2;",
+ Arrays.asList("SELECT 1 AS \"ERROR:\"", "SELECT 2;")),
+ Arguments.of("unaligned output with error text", "SELECT
'ERROR: literal' \\g (format=unaligned)\nSELECT 2;",
+ "SELECT 'ERROR: literal' \\g
(format=unaligned)\n?column?\nERROR: literal\n(1 row)\nSELECT 2;",
Arrays.asList("SELECT 'ERROR: literal'", "SELECT 2;")),
+ Arguments.of("g native error", "SELECT 1 \\g\nSELECT 2;",
"SELECT 1 \\g\nERROR: foo\nSELECT 2;", Collections.singletonList("SELECT 2;")),
+ Arguments.of("gset native error", "SELECT 1 \\gset\nSELECT
2;", "SELECT 1 \\gset\nERROR: foo\nSELECT 2;",
Collections.singletonList("SELECT 2;")),
+ Arguments.of("multiline g native error", "SELECT\n
1\n\\g\nSELECT 2;", "SELECT\n 1\n\\g\nERROR: foo\nSELECT 2;",
Collections.singletonList("SELECT 2;")),
+ Arguments.of("gexec generated query", "SELECT 'SELECT 2;'
\\gexec\nSELECT 3;", "SELECT 'SELECT 2;' \\gexec\nSELECT 2;\nERROR: foo\nSELECT
3;",
+ Arrays.asList("SELECT 'SELECT 2;'", "SELECT 3;")),
+ Arguments.of("copy error without payload echo", "COPY foo FROM
STDIN;\nfoo';\n$x$;\n\\.\nSELECT 2;", "COPY foo FROM STDIN;\nERROR:
bar\nCONTEXT: COPY foo\nSELECT 2;",
+ Collections.singletonList("SELECT 2;")));
+ }
+
+ @Test
+ void assertLoadNativeError() {
+ Collection<ExternalSQLTestParameter> actual = template.load("sample",
Collections.singletonList("SELECT 1;"), Arrays.asList("SELECT 1;", "ERROR:
foo"), "PostgreSQL", "CSV");
+ assertTrue(actual.isEmpty());
+ }
+
+ @Test
+ void assertLoadEmptySource() {
+ Collection<ExternalSQLTestParameter> actual = template.load("sample",
Collections.emptyList(), Collections.emptyList(), "PostgreSQL", "CSV");
+ assertTrue(actual.isEmpty());
+ }
+}
diff --git
a/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/postgresql/ExternalPostgreSQLParserIT.java
b/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/postgresql/ExternalPostgreSQLParserIT.java
index d3f9e15a343..2eddc569320 100644
---
a/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/postgresql/ExternalPostgreSQLParserIT.java
+++
b/test/it/parser/src/test/java/org/apache/shardingsphere/test/it/sql/parser/postgresql/ExternalPostgreSQLParserIT.java
@@ -19,10 +19,10 @@ package
org.apache.shardingsphere.test.it.sql.parser.postgresql;
import
org.apache.shardingsphere.test.it.sql.parser.external.ExternalCaseSettings;
import
org.apache.shardingsphere.test.it.sql.parser.external.ExternalSQLParserIT;
-import
org.apache.shardingsphere.test.it.sql.parser.external.loader.template.type.StandardExternalTestParameterLoadTemplate;
+import
org.apache.shardingsphere.test.it.sql.parser.external.loader.template.dialect.PostgreSQLExternalTestParameterLoadTemplate;
@ExternalCaseSettings(value = "PostgreSQL", caseURL =
ExternalPostgreSQLParserIT.CASE_URL, resultURL =
ExternalPostgreSQLParserIT.RESULT_URL,
- template = StandardExternalTestParameterLoadTemplate.class)
+ template = PostgreSQLExternalTestParameterLoadTemplate.class)
class ExternalPostgreSQLParserIT extends ExternalSQLParserIT {
static final String CASE_URL =
"https://github.com/postgres/postgres/tree/master/src/test/regress/sql";