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 f43db5795ee Fix firebird select string literal (#40173)
f43db5795ee is described below
commit f43db5795ee92e2d64f544ad6a5f6e19c27309bd
Author: Maxim Igoshin <[email protected]>
AuthorDate: Sun Oct 18 07:03:07 2026 +0300
Fix firebird select string literal (#40173)
* Parse and describe string literals in Firebird select lists
* Retrigger CI
* Retrigger CI
* Fix CODE_OF_CONDUCT violations in Firebird select string literal describe
* Fix CODE_OF_CONDUCT violations in Firebird select string literal describe
---
.../src/main/antlr4/imports/firebird/BaseRule.g4 | 3 +-
.../FirebirdPrepareStatementCommandExecutor.java | 20 ++++++++++++-
...irebirdPrepareStatementCommandExecutorTest.java | 33 ++++++++++++++++++++++
.../parser/src/main/resources/case/dml/select.xml | 14 +++++++++
.../main/resources/sql/supported/dml/select.xml | 1 +
5 files changed, 68 insertions(+), 3 deletions(-)
diff --git
a/parser/sql/engine/dialect/firebird/src/main/antlr4/imports/firebird/BaseRule.g4
b/parser/sql/engine/dialect/firebird/src/main/antlr4/imports/firebird/BaseRule.g4
index 8901ee0789f..ae1d3b57f45 100644
---
a/parser/sql/engine/dialect/firebird/src/main/antlr4/imports/firebird/BaseRule.g4
+++
b/parser/sql/engine/dialect/firebird/src/main/antlr4/imports/firebird/BaseRule.g4
@@ -244,8 +244,7 @@ comparisonOperator
;
predicate
- :
- | bitExpr NOT? IN subquery
+ : bitExpr NOT? IN subquery
| bitExpr NOT? IN LP_ expr (COMMA_ expr)* RP_
| bitExpr NOT? BETWEEN bitExpr AND predicate
| bitExpr NOT? LIKE simpleExpr (ESCAPE simpleExpr)?
diff --git
a/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
b/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
index 697066b8e60..443c9494b02 100644
---
a/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
+++
b/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
@@ -89,6 +89,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.tcl.Co
import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.tcl.RollbackStatement;
import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.tcl.SavepointStatement;
import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
+import org.jspecify.annotations.Nullable;
import java.sql.SQLException;
import java.sql.Types;
@@ -106,6 +107,8 @@ import java.util.OptionalInt;
@RequiredArgsConstructor
public final class FirebirdPrepareStatementCommandExecutor implements
CommandExecutor {
+ private static final ShardingSphereTable LITERAL_TABLE = new
ShardingSphereTable(null, Collections.emptyList(), Collections.emptyList(),
Collections.emptyList());
+
private final FirebirdPrepareStatementPacket packet;
private final ConnectionSession connectionSession;
@@ -430,7 +433,7 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
} else if (value instanceof Number) {
type = Types.NUMERIC;
}
- processCustomColumn(null, null, expr.getAlias().orElse(null),
type, describeColumns, requestedItems, columnCount);
+ processLiteralColumn(value, expr.getAlias().orElse(null), type,
describeColumns, requestedItems, columnCount);
}
}
@@ -470,6 +473,21 @@ public final class FirebirdPrepareStatementCommandExecutor
implements CommandExe
}
}
+ @HighFrequencyInvocation
+ private void processLiteralColumn(@Nullable final Object value, @Nullable
final IdentifierValue columnAlias, final int dataType, final
Collection<FirebirdReturnColumnPacket> describeColumns,
+ final
Collection<FirebirdSQLInfoPacketType> requestedItems, final int columnCount) {
+ ShardingSphereColumn column = new ShardingSphereColumn("CONSTANT",
dataType, false, false, true, true, false, false);
+ String columnAliasString = null == columnAlias ? column.getName() :
columnAlias.getValue();
+ String owner =
connectionSession.getConnectionContext().getGrantee().getUsername();
+ Integer columnLength = value instanceof String ?
getStringLiteralLength((String) value) : null;
+ describeColumns.add(new FirebirdReturnColumnPacket(requestedItems,
columnCount, LITERAL_TABLE, column, null, columnAliasString, owner,
columnLength, false, null));
+ }
+
+ private int getStringLiteralLength(final String value) {
+ String text = value.replace("''", "'");
+ return text.codePointCount(0, text.length());
+ }
+
private void processCustomColumn(final String tableName, final String
columnName, final IdentifierValue columnAlias, final int dataType,
final
Collection<FirebirdReturnColumnPacket> describeColumns, final
Collection<FirebirdSQLInfoPacketType> requestedItems, final int columnCount) {
ShardingSphereTable table = new ShardingSphereTable(tableName,
Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
diff --git
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
index 45829f65c58..8f3249ff0cb 100644
---
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
+++
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
@@ -70,6 +70,7 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
+import java.nio.charset.StandardCharsets;
import java.sql.Types;
import java.util.Arrays;
import java.util.Collection;
@@ -85,6 +86,7 @@ import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -289,6 +291,37 @@ class FirebirdPrepareStatementCommandExecutorTest {
return returnPacket.getDescribeSelect().get(0);
}
+ @Test
+ void assertDescribeLiterals() throws Exception {
+ when(packet.getSQL()).thenReturn("SELECT 'it''s', 1 AS one FROM
foo_tbl");
+ when(packet.nextItem()).thenReturn(true, true, true, true, true, true,
true, false);
+ when(packet.getCurrentItem()).thenReturn(
+ FirebirdSQLInfoPacketType.STMT_TYPE,
+ FirebirdSQLInfoPacketType.SELECT,
+ FirebirdSQLInfoPacketType.FIELD,
+ FirebirdSQLInfoPacketType.FIELD,
+ FirebirdSQLInfoPacketType.ALIAS,
+ FirebirdSQLInfoPacketType.ALIAS,
+ FirebirdSQLInfoPacketType.LENGTH,
+ FirebirdSQLInfoPacketType.LENGTH,
+ FirebirdSQLInfoPacketType.DESCRIBE_END,
+ FirebirdSQLInfoPacketType.DESCRIBE_END);
+ FirebirdPrepareStatementCommandExecutor executor = new
FirebirdPrepareStatementCommandExecutor(packet, connectionSession);
+ Collection<DatabasePacket> actual = executor.execute();
+ FirebirdPrepareStatementReturnPacket actualReturnPacket =
(FirebirdPrepareStatementReturnPacket) ((FirebirdGenericResponsePacket)
actual.iterator().next()).getData();
+ assertThat(actualReturnPacket.getDescribeSelect().size(), is(2));
+ FirebirdPacketPayload stringPayload =
mock(FirebirdPacketPayload.class);
+ when(stringPayload.getCharset()).thenReturn(StandardCharsets.UTF_8);
+ actualReturnPacket.getDescribeSelect().get(0).write(stringPayload);
+ verify(stringPayload,
times(2)).writeBytes("CONSTANT".getBytes(StandardCharsets.UTF_8));
+ verify(stringPayload).writeInt4LE(4);
+ FirebirdPacketPayload numberPayload =
mock(FirebirdPacketPayload.class);
+ when(numberPayload.getCharset()).thenReturn(StandardCharsets.UTF_8);
+ actualReturnPacket.getDescribeSelect().get(1).write(numberPayload);
+
verify(numberPayload).writeBytes("CONSTANT".getBytes(StandardCharsets.UTF_8));
+
verify(numberPayload).writeBytes("one".getBytes(StandardCharsets.UTF_8));
+ }
+
@Test
void
assertExecuteWithValidStatementHandleCleansPreviousPreparedStatementResources()
throws Exception {
connectionSession.getServerPreparedStatementRegistry().addPreparedStatement(1,
new FirebirdServerPreparedStatement("SELECT 0",
mock(SelectStatementContext.class), new HintValueContext()));
diff --git a/test/it/parser/src/main/resources/case/dml/select.xml
b/test/it/parser/src/main/resources/case/dml/select.xml
index 2f76b6ba954..c27acb878f2 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -13403,6 +13403,20 @@
</from>
</select>
+ <select sql-case-id="select_string_literal_projection_firebird">
+ <projections start-index="7" stop-index="19">
+ <expression-projection text="x" start-index="7" stop-index="9">
+ <expr>
+ <literal-expression value="x" start-index="7"
stop-index="9" />
+ </expr>
+ </expression-projection>
+ <column-projection name="order_id" start-index="12"
stop-index="19" />
+ </projections>
+ <from>
+ <simple-table name="t_order" start-index="26" stop-index="32" />
+ </from>
+ </select>
+
<select sql-case-id="select_gen_id_with_identifier_firebird">
<projections start-index="7" stop-index="20">
<expression-projection text="GEN_ID(seq, 1)" start-index="7"
stop-index="20">
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/select.xml
b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
index a2d82b48af1..fc3bafd6f2a 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/select.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
@@ -449,6 +449,7 @@
<sql-case id="select_having_firebird" value="SELECT user_id, COUNT(*) AS
cnt FROM t_order GROUP BY user_id HAVING COUNT(*) > 1" db-types="Firebird"/>
<sql-case id="select_function_table_firebird" value="SELECT * FROM foo(1)"
db-types="Firebird"/>
<sql-case id="select_cast_int_firebird" value="SELECT CAST(user_id AS INT)
FROM t_order" db-types="Firebird"/>
+ <sql-case id="select_string_literal_projection_firebird" value="SELECT
'x', order_id FROM t_order" db-types="Firebird"/>
<sql-case id="select_gen_id_with_identifier_firebird" value="SELECT
GEN_ID(seq, 1) FROM t_order" db-types="Firebird"/>
<sql-case id="select_gen_id_with_parameters_firebird" value="SELECT
GEN_ID(?, ?) FROM t_order" db-types="Firebird" case-types="Placeholder"/>
<sql-case id="select_variable_default_firebird" value="SELECT DEFAULT FROM
t_order" db-types="Firebird"/>