diff --git a/.editorconfig b/.editorconfig
index 18b50af..7062954 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -45,3 +45,6 @@ insert_final_newline = unset
trim_trailing_whitespace = unset
indent_style = unset
indent_size = unset
+
+[.flattened-pom.xml]
+insert_final_newline = false
diff --git a/deparser/api/pom.xml b/deparser/api/pom.xml
new file mode 100644
index 0000000..c720fa3
--- /dev/null
+++ b/deparser/api/pom.xml
@@ -0,0 +1,39 @@
+
+
+
+ * This package provides the factory interface for creating dialect-aware SQL deparsers
+ * that generate proper SQL syntax according to the target database dialect.
+ */
+@org.osgi.annotation.bundle.Export
+@org.osgi.annotation.versioning.Version("0.0.1")
+package org.eclipse.daanse.sql.deparser.api;
diff --git a/deparser/jsqlparser/pom.xml b/deparser/jsqlparser/pom.xml
new file mode 100644
index 0000000..cb6dbf4
--- /dev/null
+++ b/deparser/jsqlparser/pom.xml
@@ -0,0 +1,49 @@
+
+
+ StringBuilder visit(Column tableColumn, S context) {
+ final Table table = tableColumn.getTable();
+ String tableName = null;
+
+ if (table != null) {
+ if (table.getAlias() != null) {
+ tableName = table.getAlias().getName();
+ } else {
+ tableName = table.getFullyQualifiedName();
+ }
+ }
+
+ if (tableName != null && !tableName.isEmpty()) {
+ dialect.quoteIdentifier(builder, tableName, tableColumn.getColumnName());
+ } else {
+ dialect.quoteIdentifier(builder, tableColumn.getColumnName());
+ }
+
+ if (tableColumn.getArrayConstructor() != null) {
+ tableColumn.getArrayConstructor().accept(this, context);
+ }
+
+ if (tableColumn.getCommentText() != null) {
+ builder.append(" /* ").append(tableColumn.getCommentText()).append(" */");
+ }
+
+ return builder;
+ }
+
+ // String Literal Quoting
+
+ @Override
+ public StringBuilder visit(StringValue stringValue, S context) {
+ if (stringValue.getPrefix() != null) {
+ builder.append(stringValue.getPrefix());
+ }
+ dialect.quoteStringLiteral(builder, stringValue.getValue());
+ return builder;
+ }
+
+ // Date/Time/Timestamp Literal Quoting
+
+ @Override
+ public StringBuilder visit(DateValue dateValue, S context) {
+ dialect.quoteDateLiteral(builder, dateValue.getValue().toString());
+ return builder;
+ }
+
+ @Override
+ public StringBuilder visit(TimeValue timeValue, S context) {
+ dialect.quoteTimeLiteral(builder, timeValue.getValue().toString());
+ return builder;
+ }
+
+ @Override
+ public StringBuilder visit(TimestampValue timestampValue, S context) {
+ dialect.quoteTimestampLiteral(builder, timestampValue.getValue().toString());
+ return builder;
+ }
+
+ // Numeric Literal Formatting
+
+ @Override
+ public StringBuilder visit(LongValue longValue, S context) {
+ dialect.quoteNumericLiteral(builder, longValue.getStringValue());
+ return builder;
+ }
+
+ @Override
+ public StringBuilder visit(DoubleValue doubleValue, S context) {
+ String valueString = doubleValue.toString();
+ if (dialect.needsExponent(doubleValue.getValue(), valueString)) {
+ valueString += "E0";
+ }
+ dialect.quoteNumericLiteral(builder, valueString);
+ return builder;
+ }
+}
diff --git a/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/BasicDialectSelectDeParser.java b/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/BasicDialectSelectDeParser.java
new file mode 100644
index 0000000..6c23ac3
--- /dev/null
+++ b/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/BasicDialectSelectDeParser.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2025 Contributors to the Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * SmartCity Jena - initial
+ * Stefan Bischof (bipolis.org) - initial
+ */
+package org.eclipse.daanse.sql.deparser.jsqlparser;
+
+import org.eclipse.daanse.jdbc.db.dialect.api.Dialect;
+
+import net.sf.jsqlparser.expression.Alias;
+import net.sf.jsqlparser.expression.ExpressionVisitor;
+import net.sf.jsqlparser.schema.Table;
+import net.sf.jsqlparser.statement.select.SelectItem;
+import net.sf.jsqlparser.util.deparser.SelectDeParser;
+
+public class BasicDialectSelectDeParser extends SelectDeParser {
+
+ private final Dialect dialect;
+
+ public BasicDialectSelectDeParser(StringBuilder buffer, Dialect dialect) {
+ super(buffer);
+ this.dialect = dialect;
+ }
+
+ public BasicDialectSelectDeParser(ExpressionVisitor StringBuilder visit(Table table, S context) {
+ // Quote catalog, schema, and table name
+ String catalog = table.getDatabaseName(); // Gets database/catalog
+ String schema = table.getSchemaName();
+ String tableName = table.getName();
+
+ if (catalog != null && !catalog.isEmpty()) {
+ dialect.quoteIdentifier(builder, catalog);
+ builder.append(".");
+ }
+
+ if (schema != null && !schema.isEmpty()) {
+ dialect.quoteIdentifier(builder, schema);
+ builder.append(".");
+ }
+
+ if (tableName != null) {
+ dialect.quoteIdentifier(builder, tableName);
+ }
+
+ // Handle table alias
+ Alias alias = table.getAlias();
+ if (alias != null) {
+ if (dialect.allowsAs()) {
+ builder.append(" AS ");
+ } else {
+ builder.append(" ");
+ }
+ // Don't quote the alias - it's user-defined and may be intentionally unquoted
+ builder.append(alias.getName());
+ }
+
+ // Handle pivot/unpivot if present
+ if (table.getPivot() != null) {
+ table.getPivot().accept(this, context);
+ }
+ if (table.getUnPivot() != null) {
+ table.getUnPivot().accept(this, context);
+ }
+
+ // Handle sample clause
+ if (table.getSampleClause() != null) {
+ builder.append(table.getSampleClause());
+ }
+
+ return builder;
+ }
+
+ @Override
+ public StringBuilder visit(SelectItem> selectItem, S context) {
+ // Use parent implementation for the expression
+ selectItem.getExpression().accept(getExpressionVisitor(), context);
+
+ // Handle alias
+ Alias alias = selectItem.getAlias();
+ if (alias != null) {
+ if (dialect.allowsFieldAs() && alias.isUseAs()) {
+ builder.append(" AS ");
+ } else {
+ builder.append(" ");
+ }
+ builder.append(alias.getName());
+ }
+
+ return builder;
+ }
+}
diff --git a/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/BasicDialectStatementDeParser.java b/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/BasicDialectStatementDeParser.java
new file mode 100644
index 0000000..b9c0514
--- /dev/null
+++ b/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/BasicDialectStatementDeParser.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2025 Contributors to the Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * SmartCity Jena - initial
+ * Stefan Bischof (bipolis.org) - initial
+ */
+package org.eclipse.daanse.sql.deparser.jsqlparser;
+
+import org.eclipse.daanse.jdbc.db.dialect.api.Dialect;
+
+import net.sf.jsqlparser.util.deparser.StatementDeParser;
+
+public class BasicDialectStatementDeParser extends StatementDeParser {
+
+ public BasicDialectStatementDeParser(StringBuilder buffer, Dialect dialect) {
+
+ super(createExpressionDeParser(dialect, buffer), createSelectDeParser(buffer, dialect), buffer);
+
+ BasicDialectSelectDeParser selectDeParser = (BasicDialectSelectDeParser) getSelectDeParser();
+ BasicDialectExpressionDeParser expressionDeParser = (BasicDialectExpressionDeParser) getExpressionDeParser();
+ selectDeParser.setExpressionVisitor(expressionDeParser);
+ expressionDeParser.setSelectVisitor(selectDeParser);
+ }
+
+ private static BasicDialectExpressionDeParser createExpressionDeParser(Dialect dialect, StringBuilder buffer) {
+ return new BasicDialectExpressionDeParser(dialect);
+ }
+
+ private static BasicDialectSelectDeParser createSelectDeParser(StringBuilder buffer, Dialect dialect) {
+ return new BasicDialectSelectDeParser(buffer, dialect);
+ }
+
+}
diff --git a/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/package-info.java b/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/package-info.java
new file mode 100644
index 0000000..cc5a563
--- /dev/null
+++ b/deparser/jsqlparser/src/main/java/org/eclipse/daanse/sql/deparser/jsqlparser/package-info.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2025 Contributors to the Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * SmartCity Jena - initial
+ * Stefan Bischof (bipolis.org) - initial
+ */
+
+@org.osgi.annotation.versioning.Version("0.0.1")
+package org.eclipse.daanse.sql.deparser.jsqlparser;
diff --git a/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/BaiscDialectExpressionDeParserTest.java b/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/BaiscDialectExpressionDeParserTest.java
new file mode 100644
index 0000000..eba899e
--- /dev/null
+++ b/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/BaiscDialectExpressionDeParserTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2025 Contributors to the Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * SmartCity Jena - initial
+ * Stefan Bischof (bipolis.org) - initial
+ */
+package org.eclipse.daanse.sql.deparser.jsqlparser;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.eclipse.daanse.jdbc.db.dialect.api.Dialect;
+import org.junit.jupiter.api.Test;
+
+import net.sf.jsqlparser.expression.DateValue;
+import net.sf.jsqlparser.expression.DoubleValue;
+import net.sf.jsqlparser.expression.LongValue;
+import net.sf.jsqlparser.expression.StringValue;
+import net.sf.jsqlparser.expression.TimeValue;
+import net.sf.jsqlparser.expression.TimestampValue;
+import net.sf.jsqlparser.schema.Column;
+import net.sf.jsqlparser.schema.Table;
+
+class BaiscDialectExpressionDeParserTest {
+
+ @Test
+ void testColumnWithoutTable_AnsiDialect() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ Column column = new Column("columnName");
+ deparser.visit(column, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("\"columnName\"");
+ }
+
+ @Test
+ void testColumnWithoutTable_MySqlDialect() {
+ Dialect dialect = MockDialectHelper.createMySqlDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ Column column = new Column("columnName");
+ deparser.visit(column, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("`columnName`");
+ }
+
+ @Test
+ void testColumnWithoutTable_SqlServerDialect() {
+ Dialect dialect = MockDialectHelper.createSqlServerDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ Column column = new Column("columnName");
+ deparser.visit(column, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("[columnName]");
+ }
+
+ @Test
+ void testColumnWithTable_AnsiDialect() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ Table table = new Table("tableName");
+ Column column = new Column(table, "columnName");
+ deparser.visit(column, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("\"tableName\".\"columnName\"");
+ }
+
+ @Test
+ void testColumnWithTable_MySqlDialect() {
+ Dialect dialect = MockDialectHelper.createMySqlDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ Table table = new Table("tableName");
+ Column column = new Column(table, "columnName");
+ deparser.visit(column, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("`tableName`.`columnName`");
+ }
+
+ @Test
+ void testColumnWithTableAlias() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ Table table = new Table("tableName");
+ table.setAlias(new net.sf.jsqlparser.expression.Alias("t"));
+ Column column = new Column(table, "columnName");
+ deparser.visit(column, null);
+
+ // When table has alias, use alias name
+ assertThat(deparser.getBuilder().toString()).isEqualTo("\"t\".\"columnName\"");
+ }
+
+ @Test
+ void testColumnWithSchemaAndTable() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ Table table = new Table("schemaName", "tableName");
+ Column column = new Column(table, "columnName");
+ deparser.visit(column, null);
+
+ // Should use fully qualified name from table
+ assertThat(deparser.getBuilder().toString()).isEqualTo("\"schemaName.tableName\".\"columnName\"");
+ }
+
+ @Test
+ void testStringValue_SimpleString() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ StringValue stringValue = new StringValue("hello");
+ deparser.visit(stringValue, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("'hello'");
+ }
+
+ @Test
+ void testStringValue_WithSingleQuote() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ StringValue stringValue = new StringValue("it's");
+ deparser.visit(stringValue, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("'it''s'");
+ }
+
+ @Test
+ void testDateValue_AnsiDialect() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ // Use java.sql.Date directly to avoid parsing issues
+ DateValue dateValue = new DateValue(java.sql.Date.valueOf("2023-12-15"));
+ deparser.visit(dateValue, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("DATE '2023-12-15'");
+ }
+
+ @Test
+ void testTimeValue_AnsiDialect() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ // Use withValue to set java.sql.Time directly to avoid timezone issues
+ TimeValue timeValue = new TimeValue().withValue(java.sql.Time.valueOf("14:30:00"));
+ deparser.visit(timeValue, null);
+
+ // The output depends on timezone; just verify it contains TIME keyword and
+ // proper format
+ assertThat(deparser.getBuilder().toString()).startsWith("TIME '");
+ assertThat(deparser.getBuilder().toString()).endsWith("'");
+ }
+
+ @Test
+ void testTimestampValue_AnsiDialect() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ // Use withValue to set java.sql.Timestamp directly
+ TimestampValue tsValue = new TimestampValue().withValue(java.sql.Timestamp.valueOf("2023-12-15 14:30:00"));
+ deparser.visit(tsValue, null);
+
+ assertThat(deparser.getBuilder().toString()).startsWith("TIMESTAMP '");
+ assertThat(deparser.getBuilder().toString()).contains("2023-12-15");
+ }
+
+ @Test
+ void testDateValue_SqlServerDialect() {
+ Dialect dialect = MockDialectHelper.createSqlServerDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ DateValue dateValue = new DateValue(java.sql.Date.valueOf("2023-12-15"));
+ deparser.visit(dateValue, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("CONVERT(DATE, '2023-12-15')");
+ }
+
+ @Test
+ void testLongValue() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ LongValue longValue = new LongValue(12345);
+ deparser.visit(longValue, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("12345");
+ }
+
+ @Test
+ void testDoubleValue() {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ BasicDialectExpressionDeParser deparser = new BasicDialectExpressionDeParser(dialect);
+
+ DoubleValue doubleValue = new DoubleValue("123.45");
+ deparser.visit(doubleValue, null);
+
+ assertThat(deparser.getBuilder().toString()).isEqualTo("123.45");
+ }
+
+}
diff --git a/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/DialectStatementDeParserTest.java b/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/DialectStatementDeParserTest.java
new file mode 100644
index 0000000..636bef8
--- /dev/null
+++ b/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/DialectStatementDeParserTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2025 Contributors to the Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * SmartCity Jena - initial
+ * Stefan Bischof (bipolis.org) - initial
+ */
+package org.eclipse.daanse.sql.deparser.jsqlparser;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.eclipse.daanse.jdbc.db.dialect.api.Dialect;
+import org.junit.jupiter.api.Test;
+
+import net.sf.jsqlparser.JSQLParserException;
+import net.sf.jsqlparser.parser.CCJSqlParserUtil;
+import net.sf.jsqlparser.statement.Statement;
+
+class DialectStatementDeParserTest {
+
+ @Test
+ void testSimpleSelect_AnsiDialect() throws JSQLParserException {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ StringBuilder buffer = new StringBuilder();
+ BasicDialectStatementDeParser deparser = new BasicDialectStatementDeParser(buffer, dialect);
+
+ Statement stmt = CCJSqlParserUtil.parse("SELECT col1 FROM table1");
+ stmt.accept(deparser);
+
+ String result = buffer.toString();
+ // The column and table names should be quoted
+ assertThat(result).contains("\"col1\"");
+ }
+
+ @Test
+ void testSimpleSelect_MySqlDialect() throws JSQLParserException {
+ Dialect dialect = MockDialectHelper.createMySqlDialect();
+ StringBuilder buffer = new StringBuilder();
+ BasicDialectStatementDeParser deparser = new BasicDialectStatementDeParser(buffer, dialect);
+
+ Statement stmt = CCJSqlParserUtil.parse("SELECT col1 FROM table1");
+ stmt.accept(deparser);
+
+ String result = buffer.toString();
+ // MySQL uses backticks
+ assertThat(result).contains("`col1`");
+ }
+
+ @Test
+ void testSelectWithStringLiteral() throws JSQLParserException {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ StringBuilder buffer = new StringBuilder();
+ BasicDialectStatementDeParser deparser = new BasicDialectStatementDeParser(buffer, dialect);
+
+ Statement stmt = CCJSqlParserUtil.parse("SELECT * FROM table1 WHERE name = 'test'");
+ stmt.accept(deparser);
+
+ String result = buffer.toString();
+ assertThat(result).contains("'test'");
+ }
+
+ @Test
+ void testSelectWithDateLiteral() throws JSQLParserException {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ StringBuilder buffer = new StringBuilder();
+ BasicDialectStatementDeParser deparser = new BasicDialectStatementDeParser(buffer, dialect);
+
+ Statement stmt = CCJSqlParserUtil.parse("SELECT * FROM table1 WHERE created = DATE '2023-12-15'");
+ stmt.accept(deparser);
+
+ String result = buffer.toString();
+ assertThat(result).contains("DATE '2023-12-15'");
+ }
+
+ @Test
+ void testSelectWithJoin() throws JSQLParserException {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ StringBuilder buffer = new StringBuilder();
+ BasicDialectStatementDeParser deparser = new BasicDialectStatementDeParser(buffer, dialect);
+
+ Statement stmt = CCJSqlParserUtil
+ .parse("SELECT t1.col1, t2.col2 FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id");
+ stmt.accept(deparser);
+
+ String result = buffer.toString();
+ // Columns with table aliases should be quoted
+ assertThat(result).contains("\"t1\"");
+ assertThat(result).contains("\"col1\"");
+ }
+
+ @Test
+ void testSelectWithSubquery() throws JSQLParserException {
+ Dialect dialect = MockDialectHelper.createAnsiDialect();
+ StringBuilder buffer = new StringBuilder();
+ BasicDialectStatementDeParser deparser = new BasicDialectStatementDeParser(buffer, dialect);
+
+ Statement stmt = CCJSqlParserUtil.parse("SELECT * FROM table1 WHERE id IN (SELECT id FROM table2)");
+ stmt.accept(deparser);
+
+ String result = buffer.toString();
+ assertThat(result).contains("\"id\"");
+ }
+
+}
diff --git a/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/MockDialectHelper.java b/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/MockDialectHelper.java
new file mode 100644
index 0000000..a5a03fe
--- /dev/null
+++ b/deparser/jsqlparser/src/test/java/org/eclipse/daanse/sql/deparser/jsqlparser/MockDialectHelper.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2025 Contributors to the Eclipse Foundation.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * SmartCity Jena - initial
+ * Stefan Bischof (bipolis.org) - initial
+ */
+package org.eclipse.daanse.sql.deparser.jsqlparser;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.eclipse.daanse.jdbc.db.dialect.api.Dialect;
+
+public class MockDialectHelper {
+
+ public static Dialect createAnsiDialect() {
+ return createDialectWithQuote("\"");
+ }
+
+ public static Dialect createMySqlDialect() {
+ return createDialectWithQuote("`");
+ }
+
+ public static Dialect createSqlServerDialect() {
+ Dialect dialect = mock(Dialect.class);
+
+ when(dialect.getQuoteIdentifierString()).thenReturn("[");
+
+ when(dialect.quoteIdentifier(any(CharSequence.class))).thenAnswer(inv -> {
+ CharSequence val = inv.getArgument(0);
+ return new StringBuilder("[").append(val).append("]");
+ });
+
+ doAnswer(inv -> {
+ String val = inv.getArgument(0);
+ StringBuilder buf = inv.getArgument(1);
+ if (val != null) {
+ buf.append("[").append(val).append("]");
+ }
+ return null;
+ }).when(dialect).quoteIdentifier(anyString(), any(StringBuilder.class));
+
+ when(dialect.quoteIdentifier(anyString(), anyString())).thenAnswer(inv -> {
+ String qual = inv.getArgument(0);
+ String name = inv.getArgument(1);
+ StringBuilder sb = new StringBuilder();
+ if (qual != null) {
+ sb.append("[").append(qual).append("].");
+ }
+ sb.append("[").append(name).append("]");
+ return sb.toString();
+ });
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ Object[] args = inv.getArguments();
+ boolean first = true;
+ for (int i = 1; i < args.length; i++) {
+ String name = (String) args[i];
+ if (name == null)
+ continue;
+ if (!first)
+ buf.append(".");
+ buf.append("[").append(name).append("]");
+ first = false;
+ }
+ return null;
+ }).when(dialect).quoteIdentifier(any(StringBuilder.class), (String[]) any());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String s = inv.getArgument(1);
+ buf.append("'").append(s.replace("'", "''")).append("'");
+ return null;
+ }).when(dialect).quoteStringLiteral(any(StringBuilder.class), anyString());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String value = inv.getArgument(1);
+ buf.append("CONVERT(DATE, '").append(value).append("')");
+ return null;
+ }).when(dialect).quoteDateLiteral(any(StringBuilder.class), anyString());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String value = inv.getArgument(1);
+ buf.append("CONVERT(TIME, '").append(value).append("')");
+ return null;
+ }).when(dialect).quoteTimeLiteral(any(StringBuilder.class), anyString());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String value = inv.getArgument(1);
+ buf.append("CONVERT(DATETIME, '").append(value).append("')");
+ return null;
+ }).when(dialect).quoteTimestampLiteral(any(StringBuilder.class), anyString());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String value = inv.getArgument(1);
+ buf.append(value);
+ return null;
+ }).when(dialect).quoteNumericLiteral(any(StringBuilder.class), anyString());
+
+ when(dialect.allowsAs()).thenReturn(true);
+ when(dialect.allowsFieldAs()).thenReturn(true);
+ when(dialect.needsExponent(any(), anyString())).thenReturn(false);
+ when(dialect.getDialectName()).thenReturn("sqlserver");
+
+ return dialect;
+ }
+
+ public static Dialect createDialectWithQuote(String quoteChar) {
+ Dialect dialect = mock(Dialect.class);
+
+ when(dialect.getQuoteIdentifierString()).thenReturn(quoteChar);
+
+ when(dialect.quoteIdentifier(any(CharSequence.class))).thenAnswer(inv -> {
+ CharSequence val = inv.getArgument(0);
+ return new StringBuilder(quoteChar).append(val).append(quoteChar);
+ });
+
+ doAnswer(inv -> {
+ String val = inv.getArgument(0);
+ StringBuilder buf = inv.getArgument(1);
+ if (val != null) {
+ buf.append(quoteChar).append(val).append(quoteChar);
+ }
+ return null;
+ }).when(dialect).quoteIdentifier(anyString(), any(StringBuilder.class));
+
+ when(dialect.quoteIdentifier(anyString(), anyString())).thenAnswer(inv -> {
+ String qual = inv.getArgument(0);
+ String name = inv.getArgument(1);
+ StringBuilder sb = new StringBuilder();
+ if (qual != null) {
+ sb.append(quoteChar).append(qual).append(quoteChar).append(".");
+ }
+ sb.append(quoteChar).append(name).append(quoteChar);
+ return sb.toString();
+ });
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ Object[] args = inv.getArguments();
+ boolean first = true;
+ for (int i = 1; i < args.length; i++) {
+ String name = (String) args[i];
+ if (name == null)
+ continue;
+ if (!first)
+ buf.append(".");
+ buf.append(quoteChar).append(name).append(quoteChar);
+ first = false;
+ }
+ return null;
+ }).when(dialect).quoteIdentifier(any(StringBuilder.class), (String[]) any());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String s = inv.getArgument(1);
+ buf.append("'").append(s.replace("'", "''")).append("'");
+ return null;
+ }).when(dialect).quoteStringLiteral(any(StringBuilder.class), anyString());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String value = inv.getArgument(1);
+ buf.append("DATE '").append(value).append("'");
+ return null;
+ }).when(dialect).quoteDateLiteral(any(StringBuilder.class), anyString());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String value = inv.getArgument(1);
+ buf.append("TIME '").append(value).append("'");
+ return null;
+ }).when(dialect).quoteTimeLiteral(any(StringBuilder.class), anyString());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String value = inv.getArgument(1);
+ buf.append("TIMESTAMP '").append(value).append("'");
+ return null;
+ }).when(dialect).quoteTimestampLiteral(any(StringBuilder.class), anyString());
+
+ doAnswer(inv -> {
+ StringBuilder buf = inv.getArgument(0);
+ String value = inv.getArgument(1);
+ buf.append(value);
+ return null;
+ }).when(dialect).quoteNumericLiteral(any(StringBuilder.class), anyString());
+
+ when(dialect.allowsAs()).thenReturn(true);
+ when(dialect.allowsFieldAs()).thenReturn(true);
+ when(dialect.needsExponent(any(), anyString())).thenReturn(false);
+ when(dialect.getDialectName()).thenReturn("mock");
+
+ return dialect;
+ }
+
+ public static Dialect createDialectWithoutAs() {
+ Dialect dialect = createAnsiDialect();
+ when(dialect.allowsAs()).thenReturn(false);
+ when(dialect.allowsFieldAs()).thenReturn(false);
+ return dialect;
+ }
+}
diff --git a/deparser/pom.xml b/deparser/pom.xml
new file mode 100644
index 0000000..be1dd43
--- /dev/null
+++ b/deparser/pom.xml
@@ -0,0 +1,33 @@
+
+
+ StringBuilder visit(Column tableColumn, S context) {
- final Table table = tableColumn.getTable();
- String tableName = null;
- if (table != null) {
- if (table.getAlias() != null) {
- tableName = table.getAlias().getName();
- } else {
- tableName = table.getFullyQualifiedName();
- }
- }
- if (tableName != null && !tableName.isEmpty()) {
- dialect.quoteIdentifier(builder, tableName, tableColumn.getColumnName());
- } else {
- dialect.quoteIdentifier(builder, tableColumn.getColumnName());
- }
-
- if (tableColumn.getArrayConstructor() != null) {
- tableColumn.getArrayConstructor().accept(this, context);
- }
-
- if (tableColumn.getCommentText() != null) {
- builder.append(" /* ").append(tableColumn.getCommentText()).append("*/ ");
- }
-
- return builder;
- }
-
-}
diff --git a/guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DaanseStatementDeParser.java b/guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DaanseStatementDeParser.java
deleted file mode 100644
index 62bdf39..0000000
--- a/guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DaanseStatementDeParser.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2024 Contributors to the Eclipse Foundation.
- *
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * SmartCity Jena - initial
- * Stefan Bischof (bipolis.org) - initial
- */
-package org.eclipse.daanse.sql.guard.jsqltranspiler;
-
-import org.eclipse.daanse.jdbc.db.dialect.api.Dialect;
-
-import net.sf.jsqlparser.util.deparser.SelectDeParser;
-import net.sf.jsqlparser.util.deparser.StatementDeParser;
-
-public class DaanseStatementDeParser extends StatementDeParser {
-
- public DaanseStatementDeParser(StringBuilder buffer, Dialect dialect) {
- super(new DaanseExpressionDeParser(dialect), new SelectDeParser(), buffer);
- }
-}
diff --git a/guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DaanseJSQLColumResolver.java b/guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DeparserColumResolver.java
similarity index 77%
rename from guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DaanseJSQLColumResolver.java
rename to guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DeparserColumResolver.java
index 8fe7402..64bea82 100644
--- a/guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DaanseJSQLColumResolver.java
+++ b/guard/jsqltranspiler/src/main/java/org/eclipse/daanse/sql/guard/jsqltranspiler/DeparserColumResolver.java
@@ -14,6 +14,7 @@
package org.eclipse.daanse.sql.guard.jsqltranspiler;
import org.eclipse.daanse.jdbc.db.dialect.api.Dialect;
+import org.eclipse.daanse.sql.deparser.api.DialectDeparser;
import ai.starlake.transpiler.JSQLColumResolver;
import ai.starlake.transpiler.schema.JdbcMetaData;
@@ -23,30 +24,29 @@
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectVisitor;
-import net.sf.jsqlparser.util.deparser.StatementDeParser;
-public class DaanseJSQLColumResolver extends JSQLColumResolver {
+public class DeparserColumResolver extends JSQLColumResolver {
final JdbcMetaData metaData;
private Dialect dialect;
+ private DialectDeparser dialectDeparser;
- public DaanseJSQLColumResolver(JdbcMetaData metaData, Dialect dialect) {
+ public DeparserColumResolver(JdbcMetaData metaData, Dialect dialect, DialectDeparser dialectDeparser) {
super(metaData);
this.metaData = metaData;
this.dialect = dialect;
+ this.dialectDeparser = dialectDeparser;
}
public String getResolvedStatementText(String sqlStr) throws JSQLParserException {
- StringBuilder builder = new StringBuilder();
- StatementDeParser deParser = new DaanseStatementDeParser(builder, this.dialect);
Statement st = CCJSqlParserUtil.parse(sqlStr);
if (st instanceof Select) {
Select select = (Select) st;
select.accept((SelectVisitor