Search in sources :

Example 1 with ColumnEditor

use of io.debezium.relational.ColumnEditor in project debezium by debezium.

the class JdbcConnection method columnsFor.

/**
 * Determine the column definitions for the supplied result set and add each column to the specified consumer.
 *
 * @param resultSet the query result set; may not be null
 * @param consumer the consumer of the definitions; may not be null
 * @throws SQLException if an error occurs while using the result set
 */
public static void columnsFor(ResultSet resultSet, Consumer<Column> consumer) throws SQLException {
    ResultSetMetaData metadata = resultSet.getMetaData();
    ColumnEditor column = Column.editor();
    for (int position = 1; position <= metadata.getColumnCount(); ++position) {
        String columnLabel = metadata.getColumnLabel(position);
        column.name(columnLabel != null ? columnLabel : metadata.getColumnName(position));
        column.type(metadata.getColumnTypeName(position));
        column.jdbcType(metadata.getColumnType(position));
        column.length(metadata.getPrecision(position));
        column.scale(metadata.getScale(position));
        column.optional(isNullable(metadata.isNullable(position)));
        column.autoIncremented(metadata.isAutoIncrement(position));
        column.generated(false);
        consumer.accept(column.create());
    }
}
Also used : ResultSetMetaData(java.sql.ResultSetMetaData) ColumnEditor(io.debezium.relational.ColumnEditor)

Example 2 with ColumnEditor

use of io.debezium.relational.ColumnEditor in project debezium by debezium.

the class JdbcConnection method readSchema.

/**
 * Create definitions for each tables in the database, given the catalog name, schema pattern, table filter, and
 * column filter.
 *
 * @param tables the set of table definitions to be modified; may not be null
 * @param databaseCatalog the name of the catalog, which is typically the database name; may be null if all accessible
 *            databases are to be processed
 * @param schemaNamePattern the pattern used to match database schema names, which may be "" to match only those tables with
 *            no schema or null to process all accessible tables regardless of database schema name
 * @param tableFilter used to determine for which tables are to be processed; may be null if all accessible tables are to be
 *            processed
 * @param columnFilter used to determine which columns should be included as fields in its table's definition; may
 *            be null if all columns for all tables are to be included
 * @param removeTablesNotFoundInJdbc {@code true} if this method should remove from {@code tables} any definitions for tables
 *            that are not found in the database metadata, or {@code false} if such tables should be left untouched
 * @throws SQLException if an error occurs while accessing the database metadata
 */
public void readSchema(Tables tables, String databaseCatalog, String schemaNamePattern, TableNameFilter tableFilter, ColumnNameFilter columnFilter, boolean removeTablesNotFoundInJdbc) throws SQLException {
    // Before we make any changes, get the copy of the set of table IDs ...
    Set<TableId> tableIdsBefore = new HashSet<>(tables.tableIds());
    // Read the metadata for the table columns ...
    DatabaseMetaData metadata = connection().getMetaData();
    // Find views as they cannot be snapshotted
    final Set<TableId> viewIds = new HashSet<>();
    try (final ResultSet rs = metadata.getTables(databaseCatalog, schemaNamePattern, null, new String[] { "VIEW" })) {
        while (rs.next()) {
            final String catalogName = rs.getString(1);
            final String schemaName = rs.getString(2);
            final String tableName = rs.getString(3);
            viewIds.add(new TableId(catalogName, schemaName, tableName));
        }
    }
    ConcurrentMap<TableId, List<Column>> columnsByTable = new ConcurrentHashMap<>();
    try (ResultSet rs = metadata.getColumns(databaseCatalog, schemaNamePattern, null, null)) {
        while (rs.next()) {
            String catalogName = rs.getString(1);
            String schemaName = rs.getString(2);
            String tableName = rs.getString(3);
            TableId tableId = new TableId(catalogName, schemaName, tableName);
            if (viewIds.contains(tableId)) {
                continue;
            }
            if (tableFilter == null || tableFilter.matches(catalogName, schemaName, tableName)) {
                List<Column> cols = columnsByTable.computeIfAbsent(tableId, name -> new ArrayList<>());
                String columnName = rs.getString(4);
                if (columnFilter == null || columnFilter.matches(catalogName, schemaName, tableName, columnName)) {
                    ColumnEditor column = Column.editor().name(columnName);
                    column.jdbcType(rs.getInt(5));
                    column.type(rs.getString(6));
                    column.length(rs.getInt(7));
                    column.scale(rs.getInt(9));
                    column.optional(isNullable(rs.getInt(11)));
                    column.position(rs.getInt(17));
                    column.autoIncremented("YES".equalsIgnoreCase(rs.getString(23)));
                    String autogenerated = null;
                    try {
                        autogenerated = rs.getString(24);
                    } catch (SQLException e) {
                    // ignore, some drivers don't have this index - e.g. Postgres
                    }
                    column.generated("YES".equalsIgnoreCase(autogenerated));
                    column.nativeType(resolveNativeType(column.typeName()));
                    cols.add(column.create());
                }
            }
        }
    }
    // Read the metadata for the primary keys ...
    for (TableId id : columnsByTable.keySet()) {
        // First get the primary key information, which must be done for *each* table ...
        List<String> pkColumnNames = null;
        try (ResultSet rs = metadata.getPrimaryKeys(id.catalog(), id.schema(), id.table())) {
            while (rs.next()) {
                if (pkColumnNames == null)
                    pkColumnNames = new ArrayList<>();
                String columnName = rs.getString(4);
                int columnIndex = rs.getInt(5);
                Collect.set(pkColumnNames, columnIndex - 1, columnName, null);
            }
        }
        // Then define the table ...
        List<Column> columns = columnsByTable.get(id);
        Collections.sort(columns);
        // JDBC does not expose character sets
        String defaultCharsetName = null;
        tables.overwriteTable(id, columns, pkColumnNames, defaultCharsetName);
    }
    if (removeTablesNotFoundInJdbc) {
        // Remove any definitions for tables that were not found in the database metadata ...
        tableIdsBefore.removeAll(columnsByTable.keySet());
        tableIdsBefore.forEach(tables::removeTable);
    }
}
Also used : TableId(io.debezium.relational.TableId) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) ColumnEditor(io.debezium.relational.ColumnEditor) DatabaseMetaData(java.sql.DatabaseMetaData) Column(io.debezium.relational.Column) ResultSet(java.sql.ResultSet) ArrayList(java.util.ArrayList) List(java.util.List) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashSet(java.util.HashSet)

Example 3 with ColumnEditor

use of io.debezium.relational.ColumnEditor in project debezium by debezium.

the class DdlParser method createColumnFromConstant.

protected Column createColumnFromConstant(String columnName, String constantValue) {
    ColumnEditor column = Column.editor().name(columnName);
    try {
        if (constantValue.startsWith("'") || constantValue.startsWith("\"")) {
            column.type("CHAR");
            column.jdbcType(Types.CHAR);
            column.length(constantValue.length() - 2);
        } else if (constantValue.equalsIgnoreCase("TRUE") || constantValue.equalsIgnoreCase("FALSE")) {
            column.type("BOOLEAN");
            column.jdbcType(Types.BOOLEAN);
        } else {
            setTypeInfoForConstant(constantValue, column);
        }
    } catch (Throwable t) {
        logger.debug("Unable to create an artificial column for the constant: " + constantValue);
    }
    return column.create();
}
Also used : ColumnEditor(io.debezium.relational.ColumnEditor)

Example 4 with ColumnEditor

use of io.debezium.relational.ColumnEditor in project debezium by debezium.

the class RecordsStreamProducer method tableFromFromMessage.

private Table tableFromFromMessage(List<ReplicationMessage.Column> columns, Table table) {
    return table.edit().setColumns(columns.stream().map(column -> {
        final PostgresType type = column.getType();
        final ColumnEditor columnEditor = Column.editor().name(column.getName()).jdbcType(type.getJdbcId()).type(type.getName()).optional(column.isOptional()).nativeType(type.getOid());
        columnEditor.length(column.getTypeMetadata().getLength());
        columnEditor.scale(column.getTypeMetadata().getScale());
        return columnEditor.create();
    }).collect(Collectors.toList())).setPrimaryKeyNames(table.filterColumnNames(c -> table.isPrimaryKeyColumn(c.name()))).create();
}
Also used : ColumnEditor(io.debezium.relational.ColumnEditor)

Example 5 with ColumnEditor

use of io.debezium.relational.ColumnEditor in project debezium by debezium.

the class MySqlDdlParser method parseCreateColumn.

protected Column parseCreateColumn(Marker start, TableEditor table, String columnName, String newColumnName) {
    // Obtain the column editor ...
    Column existingColumn = table.columnWithName(columnName);
    ColumnEditor column = existingColumn != null ? existingColumn.edit() : Column.editor().name(columnName);
    AtomicBoolean isPrimaryKey = new AtomicBoolean(false);
    parseColumnDefinition(start, columnName, tokens, table, column, isPrimaryKey);
    // Update the table ...
    Column newColumnDefn = column.create();
    table.addColumns(newColumnDefn);
    if (isPrimaryKey.get()) {
        table.setPrimaryKeyNames(newColumnDefn.name());
    }
    if (newColumnName != null && !newColumnName.equalsIgnoreCase(columnName)) {
        table.renameColumn(columnName, newColumnName);
        columnName = newColumnName;
    }
    // ALTER TABLE allows reordering the columns after the definition ...
    if (tokens.canConsume("FIRST")) {
        table.reorderColumn(columnName, null);
    } else if (tokens.canConsume("AFTER")) {
        table.reorderColumn(columnName, tokens.consume());
    }
    return table.columnWithName(newColumnDefn.name());
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Column(io.debezium.relational.Column) ColumnEditor(io.debezium.relational.ColumnEditor)

Aggregations

ColumnEditor (io.debezium.relational.ColumnEditor)7 Column (io.debezium.relational.Column)4 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)3 TableId (io.debezium.relational.TableId)2 TableEditor (io.debezium.relational.TableEditor)1 DatabaseMetaData (java.sql.DatabaseMetaData)1 ResultSet (java.sql.ResultSet)1 ResultSetMetaData (java.sql.ResultSetMetaData)1 SQLException (java.sql.SQLException)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 List (java.util.List)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1