All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ververica.cdc.debezium.history.FlinkJsonTableChangeSerializer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2022 Ververica Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ververica.cdc.debezium.history;

import io.debezium.document.Array;
import io.debezium.document.Array.Entry;
import io.debezium.document.Document;
import io.debezium.document.Value;
import io.debezium.relational.Column;
import io.debezium.relational.ColumnEditor;
import io.debezium.relational.Table;
import io.debezium.relational.TableEditor;
import io.debezium.relational.TableId;
import io.debezium.relational.history.TableChanges;
import io.debezium.relational.history.TableChanges.TableChange;
import io.debezium.relational.history.TableChanges.TableChangeType;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * The serializer responsible for converting of {@link TableChanges} into a JSON format. Copied from
 * io.debezium.relational.history.JsonTableChangeSerializer, but add serialization/deserialization
 * for column's enumValues
 */
public class FlinkJsonTableChangeSerializer implements TableChanges.TableChangesSerializer {

    @Override
    public Array serialize(TableChanges tableChanges) {
        List values =
                StreamSupport.stream(tableChanges.spliterator(), false)
                        .map(this::toDocument)
                        .map(Value::create)
                        .collect(Collectors.toList());

        return Array.create(values);
    }

    public Document toDocument(TableChange tableChange) {
        Document document = Document.create();

        document.setString("type", tableChange.getType().name());
        document.setString("id", tableChange.getId().toDoubleQuotedString());
        document.setDocument("table", toDocument(tableChange.getTable()));
        return document;
    }

    private Document toDocument(Table table) {
        Document document = Document.create();

        document.set("defaultCharsetName", table.defaultCharsetName());
        document.set("primaryKeyColumnNames", Array.create(table.primaryKeyColumnNames()));

        List columns =
                table.columns().stream().map(this::toDocument).collect(Collectors.toList());

        document.setArray("columns", Array.create(columns));

        return document;
    }

    private Document toDocument(Column column) {
        Document document = Document.create();

        document.setString("name", column.name());
        document.setNumber("jdbcType", column.jdbcType());

        if (column.nativeType() != Column.UNSET_INT_VALUE) {
            document.setNumber("nativeType", column.nativeType());
        }

        document.setString("typeName", column.typeName());
        document.setString("typeExpression", column.typeExpression());
        document.setString("charsetName", column.charsetName());

        if (column.length() != Column.UNSET_INT_VALUE) {
            document.setNumber("length", column.length());
        }

        column.scale().ifPresent(s -> document.setNumber("scale", s));

        document.setNumber("position", column.position());
        document.setBoolean("optional", column.isOptional());
        document.setBoolean("autoIncremented", column.isAutoIncremented());
        document.setBoolean("generated", column.isGenerated());

        // BEGIN FLINK MODIFICATION
        document.setArray("enumValues", column.enumValues().toArray());
        // END FLINK MODIFICATION

        return document;
    }

    @Override
    public TableChanges deserialize(Array array, boolean useCatalogBeforeSchema) {
        TableChanges tableChanges = new TableChanges();

        for (Entry entry : array) {
            TableChange change =
                    fromDocument(entry.getValue().asDocument(), useCatalogBeforeSchema);

            if (change.getType() == TableChangeType.CREATE) {
                tableChanges.create(change.getTable());
            } else if (change.getType() == TableChangeType.ALTER) {
                tableChanges.alter(change.getTable());
            } else if (change.getType() == TableChangeType.DROP) {
                tableChanges.drop(change.getTable());
            }
        }

        return tableChanges;
    }

    private static Table fromDocument(TableId id, Document document) {
        TableEditor editor =
                Table.editor()
                        .tableId(id)
                        .setDefaultCharsetName(document.getString("defaultCharsetName"));

        document.getArray("columns")
                .streamValues()
                .map(Value::asDocument)
                .map(
                        v -> {
                            ColumnEditor columnEditor =
                                    Column.editor()
                                            .name(v.getString("name"))
                                            .jdbcType(v.getInteger("jdbcType"));

                            Integer nativeType = v.getInteger("nativeType");
                            if (nativeType != null) {
                                columnEditor.nativeType(nativeType);
                            }

                            columnEditor
                                    .type(v.getString("typeName"), v.getString("typeExpression"))
                                    .charsetName(v.getString("charsetName"));

                            Integer length = v.getInteger("length");
                            if (length != null) {
                                columnEditor.length(length);
                            }

                            Integer scale = v.getInteger("scale");
                            if (scale != null) {
                                columnEditor.scale(scale);
                            }

                            columnEditor
                                    .position(v.getInteger("position"))
                                    .optional(v.getBoolean("optional"))
                                    .autoIncremented(v.getBoolean("autoIncremented"))
                                    .generated(v.getBoolean("generated"));

                            // BEGIN FLINK MODIFICATION
                            Array enumValues = v.getArray("enumValues");
                            if (enumValues != null && !enumValues.isEmpty()) {
                                columnEditor.enumValues(
                                        enumValues
                                                .streamValues()
                                                .map(Value::asString)
                                                .collect(Collectors.toList()));
                            }
                            // END FLINK MODIFICATION

                            return columnEditor.create();
                        })
                .forEach(editor::addColumn);

        editor.setPrimaryKeyNames(
                document.getArray("primaryKeyColumnNames")
                        .streamValues()
                        .map(Value::asString)
                        .collect(Collectors.toList()));

        return editor.create();
    }

    public static TableChange fromDocument(Document document, boolean useCatalogBeforeSchema) {
        TableChangeType type = TableChangeType.valueOf(document.getString("type"));
        TableId id = TableId.parse(document.getString("id"), useCatalogBeforeSchema);
        Table table = null;

        if (type == TableChangeType.CREATE || type == TableChangeType.ALTER) {
            table = fromDocument(id, document.getDocument("table"));
        } else {
            table = Table.editor().tableId(id).create();
        }
        return new TableChange(type, table);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy