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

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 8314c191 GH-737: [FlightSQL] Allow returning column remarks in 
FlightSQL's CommandGetTables (#727)
8314c191 is described below

commit 8314c1912ed501171a2085feb1909b07892a6a25
Author: Mateusz Rzeszutek <[email protected]>
AuthorDate: Sat May 3 11:01:23 2025 +0200

    GH-737: [FlightSQL] Allow returning column remarks in FlightSQL's 
CommandGetTables (#727)
    
    Resolves #737
    
    ## What's Changed
    
    This is an implementation of
    https://github.com/apache/arrow/pull/46110 for Java
---
 arrow-format/FlightSql.proto                       |  4 ++
 .../tests/FlightSqlScenarioProducer.java           |  2 +
 .../arrow/driver/jdbc/ArrowDatabaseMetadata.java   |  6 +++
 .../arrow/driver/jdbc/utils/ConvertUtils.java      |  4 ++
 .../driver/jdbc/ArrowDatabaseMetadataTest.java     | 53 +++++++++++++++++-----
 .../arrow/driver/jdbc/utils/ConvertUtilsTest.java  |  2 +
 .../arrow/flight/sql/FlightSqlColumnMetadata.java  | 21 +++++++++
 7 files changed, 80 insertions(+), 12 deletions(-)

diff --git a/arrow-format/FlightSql.proto b/arrow-format/FlightSql.proto
index 3568d851..566230c2 100644
--- a/arrow-format/FlightSql.proto
+++ b/arrow-format/FlightSql.proto
@@ -1212,6 +1212,7 @@ message CommandGetDbSchemas {
  *  - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is 
case-sensitive, "0" otherwise.
  *  - ARROW:FLIGHT:SQL:IS_READ_ONLY      - "1" indicates if the column is read 
only, "0" otherwise.
  *  - ARROW:FLIGHT:SQL:IS_SEARCHABLE     - "1" indicates if the column is 
searchable via WHERE clause, "0" otherwise.
+ *  - ARROW:FLIGHT:SQL:REMARKS           - A comment describing the column.
  * The returned data should be ordered by catalog_name, db_schema_name, 
table_name, then table_type, followed by table_schema if requested.
  */
 message CommandGetTables {
@@ -1678,6 +1679,7 @@ message ActionEndSavepointRequest {
  *    - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is 
case-sensitive, "0" otherwise.
  *    - ARROW:FLIGHT:SQL:IS_READ_ONLY      - "1" indicates if the column is 
read only, "0" otherwise.
  *    - ARROW:FLIGHT:SQL:IS_SEARCHABLE     - "1" indicates if the column is 
searchable via WHERE clause, "0" otherwise.
+ *    - ARROW:FLIGHT:SQL:REMARKS           - A comment describing the column.
  *  - GetFlightInfo: execute the query.
  */
 message CommandStatementQuery {
@@ -1703,6 +1705,7 @@ message CommandStatementQuery {
  *    - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is 
case-sensitive, "0" otherwise.
  *    - ARROW:FLIGHT:SQL:IS_READ_ONLY      - "1" indicates if the column is 
read only, "0" otherwise.
  *    - ARROW:FLIGHT:SQL:IS_SEARCHABLE     - "1" indicates if the column is 
searchable via WHERE clause, "0" otherwise.
+ *    - ARROW:FLIGHT:SQL:REMARKS           - A comment describing the column.
  *  - GetFlightInfo: execute the query.
  *  - DoPut: execute the query.
  */
@@ -1739,6 +1742,7 @@ message TicketStatementQuery {
  *    - ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE - "1" indicates if the column is 
case-sensitive, "0" otherwise.
  *    - ARROW:FLIGHT:SQL:IS_READ_ONLY      - "1" indicates if the column is 
read only, "0" otherwise.
  *    - ARROW:FLIGHT:SQL:IS_SEARCHABLE     - "1" indicates if the column is 
searchable via WHERE clause, "0" otherwise.
+ *    - ARROW:FLIGHT:SQL:REMARKS           - A comment describing the column.
  *
  *    If the schema is retrieved after parameter values have been bound with 
DoPut, then the server should account
  *    for the parameters when determining the schema.
diff --git 
a/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/FlightSqlScenarioProducer.java
 
b/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/FlightSqlScenarioProducer.java
index be746b57..e400c031 100644
--- 
a/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/FlightSqlScenarioProducer.java
+++ 
b/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/FlightSqlScenarioProducer.java
@@ -98,6 +98,7 @@ public class FlightSqlScenarioProducer implements 
FlightSqlProducer {
                         .isSearchable(true)
                         .catalogName("catalog_test")
                         .precision(100)
+                        .remarks("test column")
                         .build()
                         .getMetadataMap()),
                 null)));
@@ -126,6 +127,7 @@ public class FlightSqlScenarioProducer implements 
FlightSqlProducer {
                         .isSearchable(true)
                         .catalogName("catalog_test")
                         .precision(100)
+                        .remarks("test column")
                         .build()
                         .getMetadataMap()),
                 null)));
diff --git 
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java
 
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java
index 3f072d07..7185ddfe 100644
--- 
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java
+++ 
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java
@@ -1066,6 +1066,7 @@ public class ArrowDatabaseMetadata extends 
AvaticaDatabaseMetaData {
         (VarCharVector) currentRoot.getVector("IS_AUTOINCREMENT");
     final VarCharVector isGeneratedColumnVector =
         (VarCharVector) currentRoot.getVector("IS_GENERATEDCOLUMN");
+    final VarCharVector remarksVector = (VarCharVector) 
currentRoot.getVector("REMARKS");
 
     for (int i = 0; i < tableColumnsSize; i++, ordinalIndex++) {
       final Field field = tableColumns.get(i);
@@ -1139,6 +1140,11 @@ public class ArrowDatabaseMetadata extends 
AvaticaDatabaseMetaData {
         isAutoincrementVector.setSafe(insertIndex, EMPTY_BYTE_ARRAY);
       }
 
+      String remarks = columnMetadata.getRemarks();
+      if (remarks != null) {
+        remarksVector.setSafe(insertIndex, remarks.getBytes(CHARSET));
+      }
+
       // Fields also don't hold information about IS_AUTOINCREMENT and 
IS_GENERATEDCOLUMN,
       // so we're setting an empty string (as bytes), which means it couldn't 
be determined.
       isGeneratedColumnVector.setSafe(insertIndex, EMPTY_BYTE_ARRAY);
diff --git 
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ConvertUtils.java
 
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ConvertUtils.java
index 17b0f42d..5dd4c69c 100644
--- 
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ConvertUtils.java
+++ 
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ConvertUtils.java
@@ -136,6 +136,10 @@ public final class ConvertUtils {
     if (searchable != null) {
       builder.setSearchable(searchable);
     }
+    final String remarks = columnMetadata.getRemarks();
+    if (remarks != null) {
+      builder.setLabel(remarks);
+    }
   }
 
   /**
diff --git 
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java
 
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java
index 70d3bcbd..81579cc3 100644
--- 
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java
+++ 
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java
@@ -26,7 +26,6 @@ import static java.util.Collections.singletonList;
 import static java.util.stream.Collectors.toList;
 import static java.util.stream.IntStream.range;
 import static 
org.apache.arrow.driver.jdbc.utils.MockFlightSqlProducer.serializeSchema;
-import static 
org.apache.arrow.flight.sql.impl.FlightSql.CommandGetCrossReference;
 import static 
org.apache.arrow.flight.sql.impl.FlightSql.SqlSupportsConvert.SQL_CONVERT_BIGINT_VALUE;
 import static 
org.apache.arrow.flight.sql.impl.FlightSql.SqlSupportsConvert.SQL_CONVERT_BIT_VALUE;
 import static 
org.apache.arrow.flight.sql.impl.FlightSql.SqlSupportsConvert.SQL_CONVERT_INTEGER_VALUE;
@@ -55,9 +54,11 @@ import 
org.apache.arrow.driver.jdbc.utils.MockFlightSqlProducer;
 import org.apache.arrow.driver.jdbc.utils.ResultSetTestUtils;
 import org.apache.arrow.driver.jdbc.utils.ThrowableAssertionUtils;
 import org.apache.arrow.flight.FlightProducer.ServerStreamListener;
+import org.apache.arrow.flight.sql.FlightSqlColumnMetadata;
 import org.apache.arrow.flight.sql.FlightSqlProducer.Schemas;
 import org.apache.arrow.flight.sql.impl.FlightSql;
 import org.apache.arrow.flight.sql.impl.FlightSql.CommandGetCatalogs;
+import org.apache.arrow.flight.sql.impl.FlightSql.CommandGetCrossReference;
 import org.apache.arrow.flight.sql.impl.FlightSql.CommandGetDbSchemas;
 import org.apache.arrow.flight.sql.impl.FlightSql.CommandGetExportedKeys;
 import org.apache.arrow.flight.sql.impl.FlightSql.CommandGetImportedKeys;
@@ -79,6 +80,7 @@ import org.apache.arrow.vector.types.TimeUnit;
 import org.apache.arrow.vector.types.Types;
 import org.apache.arrow.vector.types.pojo.ArrowType;
 import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
 import org.apache.arrow.vector.types.pojo.Schema;
 import org.apache.arrow.vector.util.Text;
 import org.junit.jupiter.api.AfterAll;
@@ -322,7 +324,7 @@ public class ArrowDatabaseMetadataTest {
                       expectedGetColumnsDecimalDigits.get(i % 3),
                       expectedGetColumnsRadix.get(i % 3),
                       !Objects.equals(expectedGetColumnsIsNullable.get(i % 3), 
"NO") ? 1 : 0,
-                      null,
+                      format("column description #%d", (i % 3) + 1),
                       null,
                       null,
                       null,
@@ -419,17 +421,44 @@ public class ArrowDatabaseMetadataTest {
           try (final BufferAllocator allocator = new RootAllocator();
               final VectorSchemaRoot root =
                   VectorSchemaRoot.create(Schemas.GET_TABLES_SCHEMA, 
allocator)) {
+            final Field field1 =
+                new Field(
+                    "column_1",
+                    new FieldType(
+                        true,
+                        ArrowType.Decimal.createDecimal(5, 2, 128),
+                        null,
+                        new FlightSqlColumnMetadata.Builder()
+                            .remarks("column description #1")
+                            .build()
+                            .getMetadataMap()),
+                    null);
+            final Field field2 =
+                new Field(
+                    "column_2",
+                    new FieldType(
+                        true,
+                        new ArrowType.Timestamp(TimeUnit.NANOSECOND, "UTC"),
+                        null,
+                        new FlightSqlColumnMetadata.Builder()
+                            .remarks("column description #2")
+                            .build()
+                            .getMetadataMap()),
+                    null);
+            final Field field3 =
+                new Field(
+                    "column_3",
+                    new FieldType(
+                        false,
+                        Types.MinorType.INT.getType(),
+                        null,
+                        new FlightSqlColumnMetadata.Builder()
+                            .remarks("column description #3")
+                            .build()
+                            .getMetadataMap()),
+                    null);
             final byte[] filledTableSchemaBytes =
-                copyFrom(
-                        serializeSchema(
-                            new Schema(
-                                Arrays.asList(
-                                    Field.nullable(
-                                        "column_1", 
ArrowType.Decimal.createDecimal(5, 2, 128)),
-                                    Field.nullable(
-                                        "column_2",
-                                        new 
ArrowType.Timestamp(TimeUnit.NANOSECOND, "UTC")),
-                                    Field.notNullable("column_3", 
Types.MinorType.INT.getType())))))
+                copyFrom(serializeSchema(new Schema(Arrays.asList(field1, 
field2, field3))))
                     .toByteArray();
             final VarCharVector catalogName = (VarCharVector) 
root.getVector("catalog_name");
             final VarCharVector schemaName = (VarCharVector) 
root.getVector("db_schema_name");
diff --git 
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ConvertUtilsTest.java
 
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ConvertUtilsTest.java
index f6f549b5..b6fdc996 100644
--- 
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ConvertUtilsTest.java
+++ 
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ConvertUtilsTest.java
@@ -46,6 +46,7 @@ public class ConvertUtilsTest {
             .isSearchable(true)
             .precision(20)
             .scale(10)
+            .remarks("test column")
             .build();
     ConvertUtils.setOnColumnMetaDataBuilder(builder, 
expectedColumnMetaData.getMetadataMap());
     assertBuilder(builder, expectedColumnMetaData);
@@ -119,5 +120,6 @@ public class ConvertUtilsTest {
     assertThat(flightSqlColumnMetaData.isReadOnly(), 
equalTo(builder.getReadOnly()));
     assertThat(precision == null ? 0 : precision, 
equalTo(builder.getPrecision()));
     assertThat(scale == null ? 0 : scale, equalTo(builder.getScale()));
+    assertThat(flightSqlColumnMetaData.getRemarks(), 
equalTo(builder.getLabel()));
   }
 }
diff --git 
a/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlColumnMetadata.java
 
b/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlColumnMetadata.java
index 1bcc55a6..3a969e10 100644
--- 
a/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlColumnMetadata.java
+++ 
b/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlColumnMetadata.java
@@ -53,6 +53,7 @@ public class FlightSqlColumnMetadata {
   private static final String IS_CASE_SENSITIVE = 
"ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE";
   private static final String IS_READ_ONLY = "ARROW:FLIGHT:SQL:IS_READ_ONLY";
   private static final String IS_SEARCHABLE = "ARROW:FLIGHT:SQL:IS_SEARCHABLE";
+  private static final String REMARKS = "ARROW:FLIGHT:SQL:REMARKS";
 
   private static final String BOOLEAN_TRUE_STR = "1";
   private static final String BOOLEAN_FALSE_STR = "0";
@@ -193,6 +194,15 @@ public class FlightSqlColumnMetadata {
     return stringToBoolean(value);
   }
 
+  /**
+   * Returns the comment describing the column.
+   *
+   * @return The comment describing the column.
+   */
+  public String getRemarks() {
+    return metadataMap.get(REMARKS);
+  }
+
   /** Builder of FlightSqlColumnMetadata, used on FlightSqlProducer 
implementations. */
   public static class Builder {
     private final Map<String, String> metadataMap;
@@ -312,6 +322,17 @@ public class FlightSqlColumnMetadata {
       return this;
     }
 
+    /**
+     * Sets the comment describing the column.
+     *
+     * @param remarks The comment describing the column.
+     * @return This builder.
+     */
+    public Builder remarks(String remarks) {
+      metadataMap.put(REMARKS, remarks);
+      return this;
+    }
+
     /**
      * Builds a new instance of FlightSqlColumnMetadata.
      *

Reply via email to