You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by li...@apache.org on 2023/04/28 02:26:33 UTC

[arrow-adbc] branch main updated: feat(java/driver/jdbc): support catalogPattern in getObjects (#613)

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-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new 09c6896  feat(java/driver/jdbc): support catalogPattern in getObjects (#613)
09c6896 is described below

commit 09c68960473760c096f9d7238d1efa533b03923b
Author: David Li <li...@gmail.com>
AuthorDate: Fri Apr 28 11:26:28 2023 +0900

    feat(java/driver/jdbc): support catalogPattern in getObjects (#613)
    
    Fixes #611.
---
 .../flightsql/FlightSqlConnectionMetadataTest.java |  4 +++
 .../adbc/driver/flightsql/FlightSqlQuirks.java     |  5 +++
 .../arrow/adbc/driver/jdbc/derby/DerbyQuirks.java  |  5 +++
 .../driver/jdbc/postgresql/PostgresqlQuirks.java   |  6 ++++
 .../adbc/driver/jdbc/ObjectMetadataBuilder.java    | 42 +++++++++++++++++-----
 .../testsuite/AbstractConnectionMetadataTest.java  | 26 ++++++++++++++
 .../adbc/driver/testsuite/SqlValidationQuirks.java |  3 ++
 7 files changed, 83 insertions(+), 8 deletions(-)

diff --git a/java/driver/flight-sql-validation/src/test/java/org/apache/arrow/adbc/driver/flightsql/FlightSqlConnectionMetadataTest.java b/java/driver/flight-sql-validation/src/test/java/org/apache/arrow/adbc/driver/flightsql/FlightSqlConnectionMetadataTest.java
index 7441317..a2ad20a 100644
--- a/java/driver/flight-sql-validation/src/test/java/org/apache/arrow/adbc/driver/flightsql/FlightSqlConnectionMetadataTest.java
+++ b/java/driver/flight-sql-validation/src/test/java/org/apache/arrow/adbc/driver/flightsql/FlightSqlConnectionMetadataTest.java
@@ -39,6 +39,10 @@ public class FlightSqlConnectionMetadataTest extends AbstractConnectionMetadataT
   @Disabled("Not yet implemented")
   public void getObjectsCatalogs() throws Exception {}
 
+  @Override
+  @Disabled("Not yet implemented")
+  public void getObjectsCatalogsPattern() throws Exception {}
+
   @Override
   @Disabled("Not yet implemented")
   public void getObjectsDbSchemas() throws Exception {
diff --git a/java/driver/flight-sql-validation/src/test/java/org/apache/arrow/adbc/driver/flightsql/FlightSqlQuirks.java b/java/driver/flight-sql-validation/src/test/java/org/apache/arrow/adbc/driver/flightsql/FlightSqlQuirks.java
index 477781d..43a6df9 100644
--- a/java/driver/flight-sql-validation/src/test/java/org/apache/arrow/adbc/driver/flightsql/FlightSqlQuirks.java
+++ b/java/driver/flight-sql-validation/src/test/java/org/apache/arrow/adbc/driver/flightsql/FlightSqlQuirks.java
@@ -63,6 +63,11 @@ public class FlightSqlQuirks extends SqlValidationQuirks {
     }
   }
 
+  @Override
+  public String defaultCatalog() {
+    return "main";
+  }
+
   @Override
   public String caseFoldTableName(String name) {
     return name.toUpperCase();
diff --git a/java/driver/jdbc-validation-derby/src/test/java/org/apache/arrow/adbc/driver/jdbc/derby/DerbyQuirks.java b/java/driver/jdbc-validation-derby/src/test/java/org/apache/arrow/adbc/driver/jdbc/derby/DerbyQuirks.java
index 1df0398..d0fb2dc 100644
--- a/java/driver/jdbc-validation-derby/src/test/java/org/apache/arrow/adbc/driver/jdbc/derby/DerbyQuirks.java
+++ b/java/driver/jdbc-validation-derby/src/test/java/org/apache/arrow/adbc/driver/jdbc/derby/DerbyQuirks.java
@@ -55,6 +55,11 @@ public class DerbyQuirks extends SqlValidationQuirks {
     }
   }
 
+  @Override
+  public String defaultCatalog() {
+    return "";
+  }
+
   @Override
   public String caseFoldTableName(String name) {
     return name.toUpperCase();
diff --git a/java/driver/jdbc-validation-postgresql/src/test/java/org/apache/arrow/adbc/driver/jdbc/postgresql/PostgresqlQuirks.java b/java/driver/jdbc-validation-postgresql/src/test/java/org/apache/arrow/adbc/driver/jdbc/postgresql/PostgresqlQuirks.java
index 7018d75..0cc6b87 100644
--- a/java/driver/jdbc-validation-postgresql/src/test/java/org/apache/arrow/adbc/driver/jdbc/postgresql/PostgresqlQuirks.java
+++ b/java/driver/jdbc-validation-postgresql/src/test/java/org/apache/arrow/adbc/driver/jdbc/postgresql/PostgresqlQuirks.java
@@ -79,6 +79,12 @@ public class PostgresqlQuirks extends SqlValidationQuirks {
     }
   }
 
+  @Override
+  public String defaultCatalog() {
+    // XXX: this should really come from configuration
+    return "postgres";
+  }
+
   @Override
   public String caseFoldTableName(String name) {
     return name.toLowerCase();
diff --git a/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/ObjectMetadataBuilder.java b/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/ObjectMetadataBuilder.java
index 93c1133..909aec5 100644
--- a/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/ObjectMetadataBuilder.java
+++ b/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/ObjectMetadataBuilder.java
@@ -26,6 +26,8 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
 import org.apache.arrow.adbc.core.AdbcConnection;
 import org.apache.arrow.adbc.core.StandardSchemas;
 import org.apache.arrow.memory.ArrowBuf;
@@ -45,7 +47,7 @@ import org.apache.arrow.vector.complex.writer.VarCharWriter;
 /** Helper class to track state needed to build up the object metadata structure. */
 final class ObjectMetadataBuilder implements AutoCloseable {
   private final AdbcConnection.GetObjectsDepth depth;
-  private final String catalogPattern;
+  private final Predicate<String> catalogPattern;
   private final String dbSchemaPattern;
   private final String tableNamePattern;
   private final String[] tableTypesFilter;
@@ -93,7 +95,12 @@ final class ObjectMetadataBuilder implements AutoCloseable {
       throws SQLException {
     this.allocator = allocator;
     this.depth = depth;
-    this.catalogPattern = catalogPattern;
+    if (catalogPattern == null) {
+      this.catalogPattern = (ignored) -> true;
+    } else {
+      Pattern pattern = Pattern.compile(translatePattern(catalogPattern));
+      this.catalogPattern = (catalog) -> pattern.matcher(catalog).matches();
+    }
     this.dbSchemaPattern = dbSchemaPattern;
     this.tableNamePattern = tableNamePattern;
     this.tableTypesFilter = tableTypesFilter;
@@ -133,17 +140,19 @@ final class ObjectMetadataBuilder implements AutoCloseable {
   }
 
   VectorSchemaRoot build() throws SQLException {
-    // TODO: need to turn catalogPattern into a catalog filter since JDBC doesn't support this
     try (final ResultSet rs = dbmd.getCatalogs()) {
       int catalogCount = 0;
       while (rs.next()) {
         final String catalogName = rs.getString(1);
+        if (!catalogPattern.test(catalogName)) continue;
         addCatalogRow(catalogCount, catalogName);
         catalogCount++;
       }
-      // TODO: only include this if matches filter
-      addCatalogRow(catalogCount, /*catalogName*/ "");
-      catalogCount++;
+      // Some databases have an anonymous catalog
+      if (catalogPattern.test("") && catalogCount == 0) {
+        addCatalogRow(catalogCount, /*catalogName*/ "");
+        catalogCount++;
+      }
       root.setRowCount(catalogCount);
     }
     VectorSchemaRoot result = root;
@@ -278,10 +287,10 @@ final class ObjectMetadataBuilder implements AutoCloseable {
         if (depth == AdbcConnection.GetObjectsDepth.TABLES) {
           tableColumns.setNull(rowIndex + tableCount);
         } else {
-          int columnBaseIndex = tableColumns.startNewValue(rowIndex);
+          int columnBaseIndex = tableColumns.startNewValue(rowIndex + tableCount);
           final int columnCount =
               buildColumns(columnBaseIndex, catalogName, dbSchemaName, tableName);
-          tableColumns.endValue(rowIndex, columnCount);
+          tableColumns.endValue(rowIndex + tableCount, columnCount);
         }
         tableCount++;
       }
@@ -360,6 +369,23 @@ final class ObjectMetadataBuilder implements AutoCloseable {
     AutoCloseables.close(root);
   }
 
+  /** Turn a SQL-style pattern (%, _) to a regex. */
+  String translatePattern(String filter) {
+    StringBuilder builder = new StringBuilder(filter.length());
+    builder.append("^");
+    for (char c : filter.toCharArray()) {
+      if (c == '%') {
+        builder.append(".*");
+      } else if (c == '_') {
+        builder.append(".");
+      } else {
+        builder.append(Pattern.quote(String.valueOf(c)));
+      }
+    }
+    builder.append("$");
+    return builder.toString();
+  }
+
   static class ReferencedColumn {
     String catalog;
     String dbSchema;
diff --git a/java/driver/validation/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractConnectionMetadataTest.java b/java/driver/validation/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractConnectionMetadataTest.java
index 925737b..6a5fc90 100644
--- a/java/driver/validation/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractConnectionMetadataTest.java
+++ b/java/driver/validation/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractConnectionMetadataTest.java
@@ -78,6 +78,10 @@ public abstract class AbstractConnectionMetadataTest {
     tableName = quirks.caseFoldTableName("foo");
     mainTable = quirks.caseFoldTableName("product");
     dependentTable = quirks.caseFoldTableName("sale");
+
+    quirks.cleanupTable(tableName);
+    quirks.cleanupTable(mainTable);
+    quirks.cleanupTable(dependentTable);
   }
 
   @AfterEach
@@ -259,6 +263,28 @@ public abstract class AbstractConnectionMetadataTest {
     }
   }
 
+  @Test
+  public void getObjectsCatalogsPattern() throws Exception {
+    util.ingestTableIntsStrs(allocator, connection, tableName);
+    try (final ArrowReader reader =
+        connection.getObjects(
+            AdbcConnection.GetObjectsDepth.CATALOGS,
+            quirks.defaultCatalog(),
+            null,
+            null,
+            null,
+            null)) {
+      assertThat(reader.getVectorSchemaRoot().getSchema())
+          .isEqualTo(StandardSchemas.GET_OBJECTS_SCHEMA);
+      assertThat(reader.loadNextBatch()).isTrue();
+      assertThat(reader.getVectorSchemaRoot().getRowCount()).isEqualTo(1);
+      final FieldVector dbSchemas = reader.getVectorSchemaRoot().getVector(1);
+      // We requested depth == CATALOGS, so the db_schemas field should be all null
+      assertThat(dbSchemas.getNullCount()).isEqualTo(dbSchemas.getValueCount());
+      assertThat(reader.loadNextBatch()).isFalse();
+    }
+  }
+
   @Test
   public void getObjectsDbSchemas() throws Exception {
     util.ingestTableIntsStrs(allocator, connection, tableName);
diff --git a/java/driver/validation/src/main/java/org/apache/arrow/adbc/driver/testsuite/SqlValidationQuirks.java b/java/driver/validation/src/main/java/org/apache/arrow/adbc/driver/testsuite/SqlValidationQuirks.java
index 6126972..895c3a0 100644
--- a/java/driver/validation/src/main/java/org/apache/arrow/adbc/driver/testsuite/SqlValidationQuirks.java
+++ b/java/driver/validation/src/main/java/org/apache/arrow/adbc/driver/testsuite/SqlValidationQuirks.java
@@ -29,6 +29,9 @@ public abstract class SqlValidationQuirks {
 
   public void cleanupTable(String name) throws Exception {}
 
+  /** Get the name of the default catalog. */
+  public abstract String defaultCatalog();
+
   /** Normalize a table name. */
   public String caseFoldTableName(String name) {
     return name;