|
12 | 12 | import java.sql.SQLException; |
13 | 13 | import java.sql.Statement; |
14 | 14 | import java.time.Duration; |
15 | | -import java.util.Objects; |
16 | | -import java.util.Optional; |
| 15 | +import java.util.*; |
17 | 16 | import java.util.concurrent.atomic.AtomicLong; |
18 | 17 |
|
| 18 | +import io.debezium.relational.*; |
19 | 19 | import org.apache.kafka.connect.errors.ConnectException; |
20 | 20 | import org.postgresql.core.BaseConnection; |
21 | 21 | import org.postgresql.replication.LogSequenceNumber; |
|
32 | 32 | import io.debezium.connector.postgresql.spi.SlotState; |
33 | 33 | import io.debezium.jdbc.JdbcConfiguration; |
34 | 34 | import io.debezium.jdbc.JdbcConnection; |
35 | | -import io.debezium.relational.Column; |
36 | | -import io.debezium.relational.ColumnEditor; |
37 | | -import io.debezium.relational.TableId; |
38 | | -import io.debezium.relational.Tables; |
39 | 35 | import io.debezium.util.Clock; |
40 | 36 | import io.debezium.util.Metronome; |
41 | 37 |
|
@@ -509,4 +505,70 @@ public TypeRegistry getTypeRegistry() { |
509 | 505 | Objects.requireNonNull(typeRegistry, "Connection does not provide type registry"); |
510 | 506 | return typeRegistry; |
511 | 507 | } |
| 508 | + |
| 509 | + public void readSchema(Tables tables, String databaseCatalog, String schemaNamePattern, |
| 510 | + Tables.TableFilter tableFilter, Tables.ColumnNameFilter columnFilter, boolean removeTablesNotFoundInJdbc) |
| 511 | + throws SQLException { |
| 512 | + // Before we make any changes, get the copy of the set of table IDs ... |
| 513 | + Set<TableId> tableIdsBefore = new HashSet<>(tables.tableIds()); |
| 514 | + |
| 515 | + // Read the metadata for the table columns ... |
| 516 | + DatabaseMetaData metadata = connection().getMetaData(); |
| 517 | + |
| 518 | + // Find regular and materialized views as they cannot be snapshotted |
| 519 | + final Set<TableId> viewIds = new HashSet<>(); |
| 520 | + final Set<TableId> tableIds = new HashSet<>(); |
| 521 | + |
| 522 | + int totalTables = 0; |
| 523 | + try (final ResultSet rs = metadata.getTables(databaseCatalog, schemaNamePattern, null, |
| 524 | + new String[]{ "VIEW", "MATERIALIZED VIEW", "TABLE" })) { |
| 525 | + while (rs.next()) { |
| 526 | + final String schemaName = rs.getString(2); |
| 527 | + final String tableName = rs.getString(3); |
| 528 | + final String tableType = rs.getString(4); |
| 529 | + if ("TABLE".equals(tableType)) { |
| 530 | + totalTables++; |
| 531 | + TableId tableId = new TableId(null, schemaName, tableName); |
| 532 | + if (tableFilter == null || tableFilter.isIncluded(tableId)) { |
| 533 | + tableIds.add(tableId); |
| 534 | + } |
| 535 | + } |
| 536 | + else { |
| 537 | + TableId tableId = new TableId(null, schemaName, tableName); |
| 538 | + viewIds.add(tableId); |
| 539 | + } |
| 540 | + } |
| 541 | + } |
| 542 | + |
| 543 | + Map<TableId, List<Column>> columnsByTable = new HashMap<>(); |
| 544 | + |
| 545 | + if (totalTables == tableIds.size() || config.getBoolean(RelationalDatabaseConnectorConfig.SNAPSHOT_FULL_COLUMN_SCAN_FORCE)) { |
| 546 | + columnsByTable = getColumnsDetails(databaseCatalog, schemaNamePattern, null, tableFilter, columnFilter, metadata, viewIds); |
| 547 | + } |
| 548 | + else { |
| 549 | + for (TableId includeTable : tableIds) { |
| 550 | + Map<TableId, List<Column>> cols = getColumnsDetails(databaseCatalog, schemaNamePattern, includeTable.table(), tableFilter, |
| 551 | + columnFilter, metadata, viewIds); |
| 552 | + columnsByTable.putAll(cols); |
| 553 | + } |
| 554 | + } |
| 555 | + |
| 556 | + // Read the metadata for the primary keys ... |
| 557 | + for (Map.Entry<TableId, List<Column>> tableEntry : columnsByTable.entrySet()) { |
| 558 | + // First get the primary key information, which must be done for *each* table ... |
| 559 | + List<String> pkColumnNames = readPrimaryKeyOrUniqueIndexNames(metadata, tableEntry.getKey()); |
| 560 | + |
| 561 | + // Then define the table ... |
| 562 | + List<Column> columns = tableEntry.getValue(); |
| 563 | + Collections.sort(columns); |
| 564 | + String defaultCharsetName = null; // JDBC does not expose character sets |
| 565 | + tables.overwriteTable(tableEntry.getKey(), columns, pkColumnNames, defaultCharsetName); |
| 566 | + } |
| 567 | + |
| 568 | + if (removeTablesNotFoundInJdbc) { |
| 569 | + // Remove any definitions for tables that were not found in the database metadata ... |
| 570 | + tableIdsBefore.removeAll(columnsByTable.keySet()); |
| 571 | + tableIdsBefore.forEach(tables::removeTable); |
| 572 | + } |
| 573 | + } |
512 | 574 | } |
0 commit comments