private int buildTables()

in java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/ObjectMetadataBuilder.java [223:349]


  private int buildTables(int rowIndex, String catalogName, String dbSchemaName)
      throws AdbcException, SQLException {
    int tableCount = 0;
    try (final ResultSet rs =
        dbmd.getTables(catalogName, dbSchemaName, tableNamePattern, tableTypesFilter)) {

      while (rs.next()) {
        final @Nullable String tableName = rs.getString(3);
        final @Nullable String tableType = rs.getString(4);
        if (tableName == null || tableType == null) {
          throw new AdbcException(
              JdbcDriverUtil.prefixExceptionMessage("JDBC driver returned null table name/type"),
              null,
              AdbcStatusCode.INTERNAL,
              null,
              0);
        }

        tables.setIndexDefined(rowIndex + tableCount);
        tableNames.setSafe(rowIndex + tableCount, tableName.getBytes(StandardCharsets.UTF_8));
        tableTypes.setSafe(rowIndex + tableCount, tableType.getBytes(StandardCharsets.UTF_8));
        tableConstraintsWriter.setPosition(rowIndex + tableCount);
        tableConstraintsWriter.startList();

        // JDBC doesn't directly expose constraints. Merge various info methods:
        // 1. Primary keys
        try (final ResultSet pk = dbmd.getPrimaryKeys(catalogName, dbSchemaName, tableName)) {
          String constraintName = null;
          List<@Nullable String> constraintColumns = new ArrayList<>();
          while (pk.next()) {
            constraintName = pk.getString(6);
            String columnName = pk.getString(4);
            int columnIndex = pk.getInt(5);
            while (constraintColumns.size() < columnIndex) constraintColumns.add(null);
            constraintColumns.set(columnIndex - 1, columnName);
          }
          if (!constraintColumns.isEmpty()) {
            addConstraint(
                constraintName, "PRIMARY KEY", constraintColumns, Collections.emptyList());
          }
        }

        // 2. Foreign keys ("imported" keys)
        try (final ResultSet fk = dbmd.getImportedKeys(catalogName, dbSchemaName, tableName)) {
          List<@Nullable String> names = new ArrayList<>();
          List<List<@Nullable String>> columns = new ArrayList<>();
          List<List<ReferencedColumn>> references = new ArrayList<>();
          while (fk.next()) {
            String keyName = fk.getString(12);
            String keyColumn = fk.getString(8);
            int keySeq = fk.getInt(9);
            if (keySeq == 1) {
              names.add(keyName);
              columns.add(new ArrayList<>());
              references.add(new ArrayList<>());
            }
            columns.get(columns.size() - 1).add(keyColumn);
            final @Nullable String fkTableName = fk.getString(3);
            final @Nullable String fkColumnName = fk.getString(4);
            if (fkTableName == null || fkColumnName == null) {
              throw new AdbcException(
                  JdbcDriverUtil.prefixExceptionMessage(
                      "JDBC driver returned null table/column name"),
                  null,
                  AdbcStatusCode.INTERNAL,
                  null,
                  0);
            }
            final ReferencedColumn reference =
                new ReferencedColumn(fk.getString(1), fk.getString(2), fkTableName, fkColumnName);
            references.get(references.size() - 1).add(reference);
          }

          for (int i = 0; i < names.size(); i++) {
            addConstraint(names.get(i), "FOREIGN KEY", columns.get(i), references.get(i));
          }
        }

        // 3. UNIQUE constraints
        try (final ResultSet uq =
            dbmd.getIndexInfo(catalogName, dbSchemaName, tableName, true, false)) {
          Map<String, ArrayList<@Nullable String>> uniqueConstraints = new HashMap<>();
          while (uq.next()) {
            @Nullable String constraintName = uq.getString(6);
            @Nullable String columnName = uq.getString(9);
            int columnIndex = uq.getInt(8);

            if (constraintName == null || columnName == null) {
              throw new AdbcException(
                  JdbcDriverUtil.prefixExceptionMessage(
                      "JDBC driver returned null constraint/column name"),
                  null,
                  AdbcStatusCode.INTERNAL,
                  null,
                  0);
            }

            if (!uniqueConstraints.containsKey(constraintName)) {
              uniqueConstraints.put(constraintName, new ArrayList<>());
            }
            ArrayList<@Nullable String> uniqueColumns = uniqueConstraints.get(constraintName);
            while (uniqueColumns.size() < columnIndex) uniqueColumns.add(null);
            uniqueColumns.set(columnIndex - 1, columnName);
          }

          uniqueConstraints.forEach(
              (name, columns) -> {
                addConstraint(name, "UNIQUE", columns, Collections.emptyList());
              });
        }

        // TODO: how to get CHECK constraints?
        tableConstraintsWriter.endList();

        if (depth == AdbcConnection.GetObjectsDepth.TABLES) {
          tableColumns.setNull(rowIndex + tableCount);
        } else {
          int columnBaseIndex = tableColumns.startNewValue(rowIndex + tableCount);
          final int columnCount =
              buildColumns(columnBaseIndex, catalogName, dbSchemaName, tableName);
          tableColumns.endValue(rowIndex + tableCount, columnCount);
        }
        tableCount++;
      }
    }
    return tableCount;
  }