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());
}
}
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);
}
}
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();
}
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();
}
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());
}
Aggregations