You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2026/10/24 13:52:06 UTC
(shardingsphere) branch master updated: Fix PostgreSQL pipeline DDL statement splitting (#40362)
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 fe313582daf Fix PostgreSQL pipeline DDL statement splitting (#40362)
fe313582daf is described below
commit fe313582daf370e62e6f18be65524f4febd9aaf9
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Sat Oct 24 21:51:59 2026 +0800
Fix PostgreSQL pipeline DDL statement splitting (#40362)
---
.../sqlbuilder/PostgreSQLPipelineSQLBuilder.java | 27 +++++++++++++++++++---
.../PostgreSQLPipelineSQLBuilderTest.java | 12 ++++++----
2 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/sqlbuilder/PostgreSQLPipelineSQLBuilder.java b/kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/sqlbuilder/PostgreSQLPipelineSQLBuilder.java
index aa7eed4d35f..278810fe385 100644
--- a/kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/sqlbuilder/PostgreSQLPipelineSQLBuilder.java
+++ b/kernel/data-pipeline/dialect/postgresql/src/main/java/org/apache/shardingsphere/data/pipeline/postgresql/sqlbuilder/PostgreSQLPipelineSQLBuilder.java
@@ -17,6 +17,9 @@
package org.apache.shardingsphere.data.pipeline.postgresql.sqlbuilder;
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.Interval;
import org.apache.shardingsphere.data.pipeline.core.ingest.record.Column;
import org.apache.shardingsphere.data.pipeline.core.ingest.record.DataRecord;
import org.apache.shardingsphere.data.pipeline.core.sqlbuilder.dialect.DialectPipelineSQLBuilder;
@@ -27,11 +30,12 @@ import org.apache.shardingsphere.data.pipeline.postgresql.sqlbuilder.ddl.index.P
import org.apache.shardingsphere.data.pipeline.postgresql.sqlbuilder.ddl.table.PostgreSQLTablePropertiesLoader;
import org.apache.shardingsphere.data.pipeline.postgresql.sqlbuilder.template.PostgreSQLPipelineFreemarkerManager;
import org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
+import org.apache.shardingsphere.sql.parser.engine.postgresql.parser.PostgreSQLLexer;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
@@ -96,8 +100,7 @@ public final class PostgreSQLPipelineSQLBuilder implements DialectPipelineSQLBui
Map<String, Object> materials = loadMaterials(tableName, schemaName, connection, majorVersion, minorVersion);
String tableSQL = generateCreateTableSQL(majorVersion, minorVersion, materials);
String indexSQL = generateCreateIndexSQL(connection, majorVersion, minorVersion, materials);
- // TODO use ";" to split is not always correct if return value's comments contains ";"
- return Arrays.asList((tableSQL + System.lineSeparator() + indexSQL).trim().split(";"));
+ return splitStatements(tableSQL + System.lineSeparator() + indexSQL);
}
}
@@ -117,6 +120,24 @@ public final class PostgreSQLPipelineSQLBuilder implements DialectPipelineSQLBui
return new PostgreSQLIndexSQLGenerator(connection, majorVersion, minorVersion).generate(materials);
}
+ private Collection<String> splitStatements(final String sql) {
+ Collection<String> result = new ArrayList<>();
+ PostgreSQLLexer lexer = new PostgreSQLLexer(CharStreams.fromString(sql));
+ int start = 0;
+ Token token;
+ do {
+ token = lexer.nextToken();
+ if (PostgreSQLLexer.SEMI_ == token.getType() || Token.EOF == token.getType()) {
+ String statement = lexer.getInputStream().getText(Interval.of(start, token.getStartIndex() - 1)).trim();
+ if (!statement.isEmpty()) {
+ result.add(statement);
+ }
+ start = token.getStopIndex() + 1;
+ }
+ } while (Token.EOF != token.getType());
+ return result;
+ }
+
@SuppressWarnings("unchecked")
private void formatColumns(final Map<String, Object> context) {
Collection<Map<String, Object>> columns = (Collection<Map<String, Object>>) context.get("columns");
diff --git a/kernel/data-pipeline/dialect/postgresql/src/test/java/org/apache/shardingsphere/data/pipeline/postgresql/sqlbuilder/PostgreSQLPipelineSQLBuilderTest.java b/kernel/data-pipeline/dialect/postgresql/src/test/java/org/apache/shardingsphere/data/pipeline/postgresql/sqlbuilder/PostgreSQLPipelineSQLBuilderTest.java
index cc73dabaaa4..48e8c65e7c0 100644
--- a/kernel/data-pipeline/dialect/postgresql/src/test/java/org/apache/shardingsphere/data/pipeline/postgresql/sqlbuilder/PostgreSQLPipelineSQLBuilderTest.java
+++ b/kernel/data-pipeline/dialect/postgresql/src/test/java/org/apache/shardingsphere/data/pipeline/postgresql/sqlbuilder/PostgreSQLPipelineSQLBuilderTest.java
@@ -37,6 +37,8 @@ import org.apache.shardingsphere.infra.metadata.identifier.IdentifierCasePolicyR
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.test.infra.fixture.jdbc.MockedDataSource;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.MockedConstruction;
import org.mockito.MockedStatic;
import org.postgresql.replication.LogSequenceNumber;
@@ -145,8 +147,9 @@ class PostgreSQLPipelineSQLBuilderTest {
assertThat(sqlBuilder.wrapWithPageQuery("SELECT * FROM foo_tbl"), is("SELECT * FROM foo_tbl LIMIT ?"));
}
- @Test
- void assertBuildCreateTableSQLs() throws SQLException {
+ @ParameterizedTest
+ @ValueSource(strings = {"'a;b'", "E'owner''s;comment'", "$$a;b$$", "'😀;value'"})
+ void assertBuildCreateTableSQLs(final String defaultValue) throws SQLException {
Connection connection = mock(Connection.class, RETURNS_DEEP_STUBS);
when(connection.getMetaData().getDatabaseMajorVersion()).thenReturn(10);
when(connection.getMetaData().getDatabaseMinorVersion()).thenReturn(1);
@@ -169,11 +172,12 @@ class PostgreSQLPipelineSQLBuilderTest {
MockedConstruction<PostgreSQLConstraintsPropertiesAppender> ignoredConstraintsAppender = mockConstruction(PostgreSQLConstraintsPropertiesAppender.class);
MockedConstruction<PostgreSQLIndexSQLGenerator> ignoredIndexGenerator =
mockConstruction(PostgreSQLIndexSQLGenerator.class, (mocked, mockContext) -> when(mocked.generate(materials)).thenReturn("CREATE INDEX foo_index"))) {
- freemarkerManager.when(() -> PostgreSQLPipelineFreemarkerManager.getSQLByVersion(materials, "component/table/%s/create.ftl", 10, 1)).thenReturn("CREATE TABLE foo;");
+ freemarkerManager.when(() -> PostgreSQLPipelineFreemarkerManager.getSQLByVersion(materials, "component/table/%s/create.ftl", 10, 1))
+ .thenReturn("CREATE TABLE foo (note text DEFAULT " + defaultValue + ");");
Collection<String> actual = sqlBuilder.buildCreateTableSQLs(dataSource, "public", "foo_tbl");
List<String> actualList = actual.stream().map(String::trim).toList();
assertThat(actualList.size(), is(2));
- assertThat(actualList.get(0), is("CREATE TABLE foo"));
+ assertThat(actualList.get(0), is("CREATE TABLE foo (note text DEFAULT " + defaultValue + ")"));
assertThat(actualList.get(1), is("CREATE INDEX foo_index"));
assertThat(arrayColumn.get("cltype"), is("int4"));
assertTrue((boolean) arrayColumn.get("hasSqrBracket"));