This is an automated email from the ASF dual-hosted git repository.

Gabriel39 pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new c6db37c5bef [fix](flight-sql) Report actual server and Arrow versions 
on branch-4.1 (#68770)
c6db37c5bef is described below

commit c6db37c5bef0049c2076b2b6716e0478a1fad5fe
Author: Gabriel <[email protected]>
AuthorDate: Thu Oct 8 17:28:00 2026 +0800

    [fix](flight-sql) Report actual server and Arrow versions on branch-4.1 
(#68770)
    
    ### What problem does this PR solve?
    
    Flight SQL GetSqlInfo always reports server version `1.0` and Arrow
    version `18.2.0`, so ADBC clients receive stale metadata after upgrades.
    Report the running FE build version and short commit hash, using the
    same format as FE heartbeat metadata, and read the Arrow version from
    the loaded Flight SQL JAR.
    
    If the Arrow manifest has no implementation version, report `unknown`.
    Keep the info code registered because Arrow's SqlInfoBuilder rejects
    explicit requests for unregistered codes.
    
    ### Release note
    
    Fix stale server and Arrow library versions returned by Flight SQL
    GetSqlInfo.
    
    ### Validation
    
    - Added three Flight RPC tests covering all SQL info, the server version
    alone, and the Arrow version alone.
    - All three tests reproduce the stale version bug before the fix and
    pass after it.
    - All three also pass with the Flight SQL dependency loaded from an
    exploded directory without its manifest; Arrow allocator debug checks
    are enabled.
    - Compiled the changed producer and tests against the existing FE
    dependency classpath. No full FE/BE build or deployed-cluster test was
    run.
    - FE reactor Checkstyle validation passed with zero violations.
    
    ### Check List (For Author)
    
    - [x] Unit Test
    - Behavior changed:
    - [x] Yes. Version metadata follows the running server and Arrow
    library.
    - Does this need documentation?
      - [x] No.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 .../arrowflight/DorisFlightSqlProducer.java        |  11 ++-
 .../arrowflight/FlightSqlServerInfoTest.java       | 104 +++++++++++++++++++++
 2 files changed, 113 insertions(+), 2 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/service/arrowflight/DorisFlightSqlProducer.java
 
b/fe/fe-core/src/main/java/org/apache/doris/service/arrowflight/DorisFlightSqlProducer.java
index 153701dbd2d..2aae87d527b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/service/arrowflight/DorisFlightSqlProducer.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/service/arrowflight/DorisFlightSqlProducer.java
@@ -22,6 +22,7 @@ package org.apache.doris.service.arrowflight;
 
 import org.apache.doris.catalog.TableIf.TableType;
 import org.apache.doris.common.Status;
+import org.apache.doris.common.Version;
 import org.apache.doris.common.util.DebugUtil;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.mysql.MysqlCommand;
@@ -120,11 +121,17 @@ public class DorisFlightSqlProducer implements 
FlightSqlProducer, AutoCloseable
         this.location = location;
         this.flightSessionsManager = flightSessionsManager;
         sqlInfoBuilder = new SqlInfoBuilder();
-        
sqlInfoBuilder.withFlightSqlServerName("DorisFE").withFlightSqlServerVersion("1.0")
-                
.withFlightSqlServerArrowVersion("18.2.0").withFlightSqlServerReadOnly(false)
+        // Keep discovery metadata aligned with the running FE build and its 
loaded Arrow dependency.
+        sqlInfoBuilder.withFlightSqlServerName("DorisFE")
+                .withFlightSqlServerVersion(Version.DORIS_BUILD_VERSION + "-" 
+ Version.DORIS_BUILD_SHORT_HASH)
+                .withFlightSqlServerReadOnly(false)
                 
.withSqlIdentifierQuoteChar("`").withSqlDdlCatalog(true).withSqlDdlSchema(false).withSqlDdlTable(false)
                 
.withSqlIdentifierCase(SqlSupportedCaseSensitivity.SQL_CASE_SENSITIVITY_CASE_INSENSITIVE)
                 
.withSqlQuotedIdentifierCase(SqlSupportedCaseSensitivity.SQL_CASE_SENSITIVITY_CASE_INSENSITIVE);
+        String arrowVersion = 
SqlInfoBuilder.class.getPackage().getImplementationVersion();
+        // Keep the info code registered even without a manifest: 
SqlInfoBuilder rejects unknown codes.
+        sqlInfoBuilder.withFlightSqlServerArrowVersion(
+                arrowVersion == null || arrowVersion.isEmpty() ? "unknown" : 
arrowVersion);
     }
 
     private static ByteBuffer serializeMetadata(final Schema schema) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/service/arrowflight/FlightSqlServerInfoTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/service/arrowflight/FlightSqlServerInfoTest.java
new file mode 100644
index 00000000000..16f07211132
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/service/arrowflight/FlightSqlServerInfoTest.java
@@ -0,0 +1,104 @@
+// 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.doris.service.arrowflight;
+
+import org.apache.doris.common.Version;
+import org.apache.doris.service.arrowflight.sessions.FlightSessionsManager;
+
+import org.apache.arrow.flight.FlightClient;
+import org.apache.arrow.flight.FlightInfo;
+import org.apache.arrow.flight.FlightServer;
+import org.apache.arrow.flight.FlightStream;
+import org.apache.arrow.flight.Location;
+import org.apache.arrow.flight.sql.FlightSqlClient;
+import org.apache.arrow.flight.sql.FlightSqlProducer.Schemas;
+import org.apache.arrow.flight.sql.SqlInfoBuilder;
+import org.apache.arrow.flight.sql.impl.FlightSql.SqlInfo;
+import org.apache.arrow.memory.RootAllocator;
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FlightSqlServerInfoTest {
+    @Test
+    public void reportsBuildVersionsInAllSqlInfo() throws Exception {
+        Map<Integer, Object> info = readSqlInfo();
+        Assert.assertEquals("DorisFE", 
info.get(SqlInfo.FLIGHT_SQL_SERVER_NAME_VALUE));
+        Assert.assertEquals(Version.DORIS_BUILD_VERSION + "-" + 
Version.DORIS_BUILD_SHORT_HASH,
+                info.get(SqlInfo.FLIGHT_SQL_SERVER_VERSION_VALUE));
+        assertArrowVersion(info);
+        Assert.assertEquals(false, 
info.get(SqlInfo.FLIGHT_SQL_SERVER_READ_ONLY_VALUE));
+    }
+
+    @Test
+    public void reportsOnlyRequestedServerVersion() throws Exception {
+        Map<Integer, Object> info = 
readSqlInfo(SqlInfo.FLIGHT_SQL_SERVER_VERSION);
+        Assert.assertEquals(1, info.size());
+        Assert.assertEquals(Version.DORIS_BUILD_VERSION + "-" + 
Version.DORIS_BUILD_SHORT_HASH,
+                info.get(SqlInfo.FLIGHT_SQL_SERVER_VERSION_VALUE));
+    }
+
+    @Test
+    public void reportsOnlyRequestedArrowVersion() throws Exception {
+        Map<Integer, Object> info = 
readSqlInfo(SqlInfo.FLIGHT_SQL_SERVER_ARROW_VERSION);
+        assertArrowVersion(info);
+        Assert.assertEquals(1, info.size());
+    }
+
+    private static void assertArrowVersion(Map<Integer, Object> info) {
+        String version = 
SqlInfoBuilder.class.getPackage().getImplementationVersion();
+        if (version == null || version.isEmpty()) {
+            // Exploded dependencies may omit the manifest; unknown metadata 
must not be fabricated.
+            Assert.assertEquals("unknown", 
info.get(SqlInfo.FLIGHT_SQL_SERVER_ARROW_VERSION_VALUE));
+        } else {
+            Assert.assertEquals(version, 
info.get(SqlInfo.FLIGHT_SQL_SERVER_ARROW_VERSION_VALUE));
+        }
+    }
+
+    private static Map<Integer, Object> readSqlInfo(SqlInfo... requestedInfo) 
throws Exception {
+        Location location = Location.forGrpcInsecure("127.0.0.1", 0);
+        FlightSessionsManager sessions = 
Mockito.mock(FlightSessionsManager.class);
+        try (DorisFlightSqlProducer producer = new 
DorisFlightSqlProducer(location, sessions);
+                RootAllocator allocator = new RootAllocator();
+                FlightServer server = FlightServer.builder(allocator, 
location, producer).build().start();
+                FlightClient client = FlightClient.builder(allocator,
+                        Location.forGrpcInsecure("127.0.0.1", 
server.getPort())).build()) {
+            FlightSqlClient sql = new FlightSqlClient(client);
+            FlightInfo info = sql.getSqlInfo(requestedInfo);
+            Assert.assertEquals(Schemas.GET_SQL_INFO_SCHEMA, info.getSchema());
+            Assert.assertEquals(1, info.getEndpoints().size());
+            Map<Integer, Object> values = new HashMap<>();
+            try (FlightStream stream = 
client.getStream(info.getEndpoints().get(0).getTicket())) {
+                while (stream.next()) {
+                    VectorSchemaRoot root = stream.getRoot();
+                    for (int row = 0; row < root.getRowCount(); ++row) {
+                        int code = ((Number) 
root.getVector("info_name").getObject(row)).intValue();
+                        Object value = root.getVector("value").getObject(row);
+                        values.put(code, value instanceof Boolean ? value : 
value.toString());
+                    }
+                }
+            }
+            Mockito.verifyNoInteractions(sessions);
+            return values;
+        }
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to