Search in sources :

Example 56 with TableId

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

the class MySqlDdlParser method parseCreateView.

protected void parseCreateView(Marker start) {
    tokens.canConsume("OR", "REPLACE");
    if (tokens.canConsume("ALGORITHM")) {
        tokens.consume('=');
        tokens.consumeAnyOf("UNDEFINED", "MERGE", "TEMPTABLE");
    }
    parseDefiner(tokens.mark());
    if (tokens.canConsume("SQL", "SECURITY")) {
        tokens.consumeAnyOf("DEFINER", "INVOKER");
    }
    tokens.consume("VIEW");
    TableId tableId = parseQualifiedTableName(start);
    if (skipViews) {
        // We don't care about the rest ...
        consumeRemainingStatement(start);
        signalCreateView(tableId, start);
        debugSkipped(start);
        return;
    }
    TableEditor table = databaseTables.editOrCreateTable(tableId);
    if (tokens.matches('(')) {
        List<String> columnNames = parseColumnNameList(start);
        // We know nothing other than the names ...
        columnNames.forEach(name -> {
            table.addColumn(Column.editor().name(name).create());
        });
    }
    tokens.canConsume("AS");
    // We should try to discover the types of the columns by looking at this select
    if (tokens.canConsume("SELECT")) {
        // If the SELECT clause is selecting qualified column names or columns names from a single table, then
        // we can look up the columns and use those to set the type and nullability of the view's columns ...
        Map<String, Column> selectedColumnsByAlias = parseColumnsInSelectClause(start);
        if (table.columns().isEmpty()) {
            selectedColumnsByAlias.forEach((columnName, fromTableColumn) -> {
                if (fromTableColumn != null && columnName != null)
                    table.addColumn(fromTableColumn.edit().name(columnName).create());
            });
        } else {
            List<Column> changedColumns = new ArrayList<>();
            table.columns().forEach(column -> {
                // Find the column from the SELECT statement defining the view ...
                Column selectedColumn = selectedColumnsByAlias.get(column.name());
                if (selectedColumn != null) {
                    changedColumns.add(column.edit().jdbcType(selectedColumn.jdbcType()).type(selectedColumn.typeName(), selectedColumn.typeExpression()).length(selectedColumn.length()).scale(selectedColumn.scale()).autoIncremented(selectedColumn.isAutoIncremented()).generated(selectedColumn.isGenerated()).optional(selectedColumn.isOptional()).create());
                }
            });
            changedColumns.forEach(table::addColumn);
        }
        // Parse the FROM clause to see if the view is only referencing a single table, and if so then update the view
        // with an equivalent primary key ...
        Map<String, Table> fromTables = parseSelectFromClause(start);
        if (fromTables.size() == 1) {
            Table fromTable = fromTables.values().stream().findFirst().get();
            List<String> fromTablePkColumnNames = fromTable.columnNames();
            List<String> viewPkColumnNames = new ArrayList<>();
            selectedColumnsByAlias.forEach((viewColumnName, fromTableColumn) -> {
                if (fromTablePkColumnNames.contains(fromTableColumn.name())) {
                    viewPkColumnNames.add(viewColumnName);
                }
            });
            if (viewPkColumnNames.size() == fromTablePkColumnNames.size()) {
                table.setPrimaryKeyNames(viewPkColumnNames);
            }
        }
    }
    // We don't care about the rest ...
    consumeRemainingStatement(start);
    // Update the table definition ...
    databaseTables.overwriteTable(table.create());
    signalCreateView(tableId, start);
    debugParsed(start);
}
Also used : TableId(io.debezium.relational.TableId) Table(io.debezium.relational.Table) Column(io.debezium.relational.Column) ArrayList(java.util.ArrayList) TableEditor(io.debezium.relational.TableEditor)

Example 57 with TableId

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

the class RecordMakers method regenerate.

/**
 * Clear all of the cached record makers and generate new ones. This should be done when the schema changes for reasons other
 * than reading DDL from the binlog.
 */
public void regenerate() {
    clear();
    AtomicInteger nextTableNumber = new AtomicInteger(0);
    Set<TableId> tableIds = schema.tables().tableIds();
    logger.debug("Regenerating converters for {} tables", tableIds.size());
    tableIds.forEach(id -> {
        assign(nextTableNumber.incrementAndGet(), id);
    });
}
Also used : TableId(io.debezium.relational.TableId) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Example 58 with TableId

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

the class DdlParserSql2003Test method shouldParseCreateTableStatementWithSingleGeneratedAndPrimaryKeyColumn.

@Test
public void shouldParseCreateTableStatementWithSingleGeneratedAndPrimaryKeyColumn() {
    String ddl = "CREATE TABLE foo ( " + System.lineSeparator() + " c1 INTEGER GENERATED ALWAYS AS IDENTITY NOT NULL PRIMARY KEY, " + System.lineSeparator() + " c2 VARCHAR(22) " + System.lineSeparator() + "); " + System.lineSeparator();
    parser.parse(ddl, tables);
    assertThat(tables.size()).isEqualTo(1);
    Table foo = tables.forTable(new TableId(null, null, "foo"));
    assertThat(foo).isNotNull();
    assertThat(foo.columnNames()).containsExactly("c1", "c2");
    assertThat(foo.primaryKeyColumnNames()).containsExactly("c1");
    assertColumn(foo, "c1", "INTEGER", Types.INTEGER, -1, -1, false, true, true);
    assertColumn(foo, "c2", "VARCHAR", Types.VARCHAR, 22, -1, true, false, false);
}
Also used : TableId(io.debezium.relational.TableId) Table(io.debezium.relational.Table) Test(org.junit.Test)

Example 59 with TableId

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

the class DdlParserSql2003 method parseDropView.

protected void parseDropView(Marker start) {
    tokens.consume("VIEW");
    tokens.canConsume("IF", "EXISTS");
    TableId tableId = parseQualifiedTableName(start);
    databaseTables.removeTable(tableId);
    // ignore the rest ...
    consumeRemainingStatement(start);
    signalDropView(tableId, start);
}
Also used : TableId(io.debezium.relational.TableId)

Example 60 with TableId

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

the class DdlParserSql2003 method parseAlterTable.

protected void parseAlterTable(Marker start) {
    tokens.canConsume("IGNORE");
    tokens.consume("TABLE");
    TableId tableId = parseQualifiedTableName(start);
    TableEditor table = databaseTables.editOrCreateTable(tableId);
    if (tokens.matches("ADD", "CONSTRAINT") || tokens.matches("ADD", "UNIQUE") || tokens.matches("ADD", "PRIMARY") || tokens.matches("ADD", "FOREIGN") || tokens.matches("ADD", "CHECK")) {
        tokens.consume("ADD");
        parseTableConstraintDefinition(start, table);
    } else if (tokens.canConsume("ADD", "COLUMN") || tokens.canConsume("ADD")) {
        // Adding a column ...
        String columnName = tokens.consume();
        ColumnEditor column = Column.editor().name(columnName);
        AtomicBoolean isPrimaryKey = new AtomicBoolean(false);
        parseColumnDefinition(start, columnName, tokens, table, column, isPrimaryKey);
        // Update the table ...
        Column newColumnDefn = column.create();
        table.addColumn(newColumnDefn);
        if (isPrimaryKey.get()) {
            table.setPrimaryKeyNames(newColumnDefn.name());
        }
    } else if (tokens.canConsume("ALTER", "COLUMN") || tokens.canConsume("ALTER")) {
        // Altering a column ...
        String columnName = tokens.consume();
        Column existingColumn = table.columnWithName(columnName);
        ColumnEditor column = existingColumn != null ? existingColumn.edit() : Column.editor().name(columnName);
        parseAlterColumn(start, column);
        // Update the table ...
        Column newColumnDefn = column.create();
        table.setColumns(newColumnDefn);
    } else if (tokens.matches("DROP", "CONSTRAINT")) {
        parseDropTableConstraint(start, table);
    } else if (tokens.canConsume("DROP", "COLUMN") || tokens.canConsume("DROP")) {
        parseDropColumn(start, table);
    }
    databaseTables.overwriteTable(table.create());
    // rename is not supported
    signalAlterTable(tableId, null, start);
}
Also used : TableId(io.debezium.relational.TableId) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Column(io.debezium.relational.Column) ColumnEditor(io.debezium.relational.ColumnEditor) TableEditor(io.debezium.relational.TableEditor)

Aggregations

TableId (io.debezium.relational.TableId)63 Table (io.debezium.relational.Table)39 Test (org.junit.Test)34 FixFor (io.debezium.doc.FixFor)18 Column (io.debezium.relational.Column)7 TableEditor (io.debezium.relational.TableEditor)7 ArrayList (java.util.ArrayList)4 ConnectException (org.apache.kafka.connect.errors.ConnectException)4 TableSchema (io.debezium.relational.TableSchema)3 ParsingException (io.debezium.text.ParsingException)3 ResultSet (java.sql.ResultSet)3 SQLException (java.sql.SQLException)3 HashSet (java.util.HashSet)3 List (java.util.List)3 SourceRecord (org.apache.kafka.connect.source.SourceRecord)3 Predicates (io.debezium.function.Predicates)2 ColumnEditor (io.debezium.relational.ColumnEditor)2 Marker (io.debezium.text.TokenStream.Marker)2 Strings (io.debezium.util.Strings)2 Connection (java.sql.Connection)2