Search in sources :

Example 1 with TableEditor

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

the class MySqlDdlParser method parseAlterTable.

protected void parseAlterTable(Marker start) {
    tokens.canConsume("IGNORE");
    tokens.consume("TABLE");
    TableId tableId = parseQualifiedTableName(start);
    TableEditor table = databaseTables.editTable(tableId);
    TableId oldTableId = null;
    if (table != null) {
        AtomicReference<TableId> newTableName = new AtomicReference<>(null);
        if (!tokens.matches(terminator()) && !tokens.matches("PARTITION")) {
            parseAlterSpecificationList(start, table, newTableName::set);
        }
        if (tokens.matches("PARTITION")) {
            parsePartitionOptions(start, table);
        }
        databaseTables.overwriteTable(table.create());
        if (newTableName.get() != null) {
            // the table was renamed ...
            Table renamed = databaseTables.renameTable(tableId, newTableName.get());
            if (renamed != null) {
                oldTableId = tableId;
                tableId = renamed.id();
            }
        }
    } else {
        Marker marker = tokens.mark();
        try {
            // We don't know about this table but we still have to parse the statement ...
            table = TableEditor.noOp(tableId);
            if (!tokens.matches(terminator()) && !tokens.matches("PARTITION")) {
                parseAlterSpecificationList(start, table, str -> {
                });
            }
            if (tokens.matches("PARTITION")) {
                parsePartitionOptions(start, table);
            }
            parseTableOptions(start, table);
        // do nothing with this
        } catch (ParsingException e) {
            tokens.rewind(marker);
            consumeRemainingStatement(start);
        }
    }
    signalAlterTable(tableId, oldTableId, start);
}
Also used : TableId(io.debezium.relational.TableId) Table(io.debezium.relational.Table) ParsingException(io.debezium.text.ParsingException) AtomicReference(java.util.concurrent.atomic.AtomicReference) Marker(io.debezium.text.TokenStream.Marker) TableEditor(io.debezium.relational.TableEditor)

Example 2 with TableEditor

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

the class MySqlDdlParser method parseCreateIndex.

protected void parseCreateIndex(Marker start) {
    boolean unique = tokens.canConsume("UNIQUE");
    tokens.canConsumeAnyOf("FULLTEXT", "SPATIAL");
    tokens.consume("INDEX");
    // index name
    String indexName = tokens.consume();
    if (tokens.matches("USING")) {
        parseIndexType(start);
    }
    TableId tableId = null;
    if (tokens.canConsume("ON")) {
        // Usually this is required, but in some cases ON is not required
        tableId = parseQualifiedTableName(start);
    }
    if (unique && tableId != null) {
        // This is a unique index, and we can mark the index's columns as the primary key iff there is not already
        // a primary key on the table. (Should a PK be created later via an alter, then it will overwrite this.)
        TableEditor table = databaseTables.editTable(tableId);
        if (table != null && !table.hasPrimaryKey()) {
            List<String> names = parseIndexColumnNames(start);
            if (table.columns().stream().allMatch(Column::isRequired)) {
                databaseTables.overwriteTable(table.setPrimaryKeyNames(names).create());
            }
        }
    }
    // We don't care about any other statements or the rest of this statement ...
    consumeRemainingStatement(start);
    signalCreateIndex(indexName, tableId, start);
    debugParsed(start);
}
Also used : TableId(io.debezium.relational.TableId) Column(io.debezium.relational.Column) TableEditor(io.debezium.relational.TableEditor)

Example 3 with TableEditor

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

the class MySqlDdlParser method parseCreateTable.

protected void parseCreateTable(Marker start) {
    tokens.canConsume("TEMPORARY");
    tokens.consume("TABLE");
    boolean onlyIfNotExists = tokens.canConsume("IF", "NOT", "EXISTS");
    TableId tableId = parseQualifiedTableName(start);
    if (tokens.canConsume("LIKE")) {
        TableId originalId = parseQualifiedTableName(start);
        Table original = databaseTables.forTable(originalId);
        if (original != null) {
            databaseTables.overwriteTable(tableId, original.columns(), original.primaryKeyColumnNames(), original.defaultCharsetName());
        }
        consumeRemainingStatement(start);
        signalCreateTable(tableId, start);
        debugParsed(start);
        return;
    }
    if (onlyIfNotExists && databaseTables.forTable(tableId) != null) {
        // The table does exist, so we should do nothing ...
        consumeRemainingStatement(start);
        signalCreateTable(tableId, start);
        debugParsed(start);
        return;
    }
    TableEditor table = databaseTables.editOrCreateTable(tableId);
    // create_definition ...
    if (tokens.matches('('))
        parseCreateDefinitionList(start, table);
    // table_options ...
    parseTableOptions(start, table);
    // partition_options ...
    if (tokens.matches("PARTITION")) {
        parsePartitionOptions(start, table);
    }
    // select_statement
    if (tokens.canConsume("AS") || tokens.canConsume("IGNORE", "AS") || tokens.canConsume("REPLACE", "AS")) {
        parseAsSelectStatement(start, table);
    }
    // Make sure that the table's character set has been set ...
    if (!table.hasDefaultCharsetName()) {
        table.setDefaultCharsetName(currentDatabaseCharset());
    }
    // Update the table definition ...
    databaseTables.overwriteTable(table.create());
    signalCreateTable(tableId, start);
    debugParsed(start);
}
Also used : TableId(io.debezium.relational.TableId) Table(io.debezium.relational.Table) TableEditor(io.debezium.relational.TableEditor)

Example 4 with TableEditor

use of io.debezium.relational.TableEditor 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 5 with TableEditor

use of io.debezium.relational.TableEditor 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

TableEditor (io.debezium.relational.TableEditor)7 TableId (io.debezium.relational.TableId)7 Column (io.debezium.relational.Column)3 Table (io.debezium.relational.Table)3 ParsingException (io.debezium.text.ParsingException)2 Marker (io.debezium.text.TokenStream.Marker)2 ColumnEditor (io.debezium.relational.ColumnEditor)1 ArrayList (java.util.ArrayList)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1