com.alibaba.otter.canal.parse.inbound.TableMeta.FieldMeta Java Examples

The following examples show how to use com.alibaba.otter.canal.parse.inbound.TableMeta.FieldMeta. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TableMetaCache.java    From canal-1.1.3 with Apache License 2.0 5 votes vote down vote up
public static List<FieldMeta> parseTableMeta(String schema, String table, ResultSetPacket packet) {
    if (packet.getFieldValues().size() > 1) {
        String createDDL = packet.getFieldValues().get(1);
        MemoryTableMeta memoryTableMeta = new MemoryTableMeta();
        memoryTableMeta.apply(DatabaseTableMeta.INIT_POSITION, schema, createDDL, null);
        TableMeta tableMeta = memoryTableMeta.find(schema, table);
        return tableMeta.getFields();
    } else {
        return new ArrayList<FieldMeta>();
    }
}
 
Example #2
Source File: TableMetaCache.java    From canal-1.1.3 with Apache License 2.0 5 votes vote down vote up
/**
 * 处理desc table的结果
 */
public static List<FieldMeta> parseTableMetaByDesc(ResultSetPacket packet) {
    Map<String, Integer> nameMaps = new HashMap<String, Integer>(6, 1f);
    int index = 0;
    for (FieldPacket fieldPacket : packet.getFieldDescriptors()) {
        nameMaps.put(fieldPacket.getOriginalName(), index++);
    }

    int size = packet.getFieldDescriptors().size();
    int count = packet.getFieldValues().size() / packet.getFieldDescriptors().size();
    List<FieldMeta> result = new ArrayList<FieldMeta>();
    for (int i = 0; i < count; i++) {
        FieldMeta meta = new FieldMeta();
        // 做一个优化,使用String.intern(),共享String对象,减少内存使用
        meta.setColumnName(packet.getFieldValues().get(nameMaps.get(COLUMN_NAME) + i * size).intern());
        meta.setColumnType(packet.getFieldValues().get(nameMaps.get(COLUMN_TYPE) + i * size));
        meta.setNullable(StringUtils.equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(IS_NULLABLE) + i
                                                                                  * size),
            "YES"));
        meta.setKey("PRI".equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(COLUMN_KEY) + i * size)));
        meta.setUnique("UNI".equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(COLUMN_KEY) + i * size)));
        // 特殊处理引号
        meta.setDefaultValue(DruidDdlParser.unescapeQuotaName(packet.getFieldValues()
            .get(nameMaps.get(COLUMN_DEFAULT) + i * size)));
        meta.setExtra(packet.getFieldValues().get(nameMaps.get(EXTRA) + i * size));

        result.add(meta);
    }

    return result;
}
 
Example #3
Source File: TableMetaCache.java    From canal with Apache License 2.0 5 votes vote down vote up
public static List<FieldMeta> parseTableMeta(String schema, String table, ResultSetPacket packet) {
    if (packet.getFieldValues().size() > 1) {
        String createDDL = packet.getFieldValues().get(1);
        MemoryTableMeta memoryTableMeta = new MemoryTableMeta();
        memoryTableMeta.apply(DatabaseTableMeta.INIT_POSITION, schema, createDDL, null);
        TableMeta tableMeta = memoryTableMeta.find(schema, table);
        return tableMeta.getFields();
    } else {
        return new ArrayList<FieldMeta>();
    }
}
 
Example #4
Source File: TableMetaCache.java    From canal with Apache License 2.0 5 votes vote down vote up
/**
 * 处理desc table的结果
 */
public static List<FieldMeta> parseTableMetaByDesc(ResultSetPacket packet) {
    Map<String, Integer> nameMaps = new HashMap<String, Integer>(6, 1f);
    int index = 0;
    for (FieldPacket fieldPacket : packet.getFieldDescriptors()) {
        nameMaps.put(fieldPacket.getOriginalName(), index++);
    }

    int size = packet.getFieldDescriptors().size();
    int count = packet.getFieldValues().size() / packet.getFieldDescriptors().size();
    List<FieldMeta> result = new ArrayList<FieldMeta>();
    for (int i = 0; i < count; i++) {
        FieldMeta meta = new FieldMeta();
        // 做一个优化,使用String.intern(),共享String对象,减少内存使用
        meta.setColumnName(packet.getFieldValues().get(nameMaps.get(COLUMN_NAME) + i * size).intern());
        meta.setColumnType(packet.getFieldValues().get(nameMaps.get(COLUMN_TYPE) + i * size));
        meta.setNullable(StringUtils.equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(IS_NULLABLE) + i
                                                                                  * size),
            "YES"));
        meta.setKey("PRI".equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(COLUMN_KEY) + i * size)));
        meta.setUnique("UNI".equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(COLUMN_KEY) + i * size)));
        // 特殊处理引号
        meta.setDefaultValue(DruidDdlParser.unescapeQuotaName(packet.getFieldValues()
            .get(nameMaps.get(COLUMN_DEFAULT) + i * size)));
        meta.setExtra(packet.getFieldValues().get(nameMaps.get(EXTRA) + i * size));

        result.add(meta);
    }

    return result;
}
 
Example #5
Source File: DatabaseTableMeta.java    From canal-1.1.3 with Apache License 2.0 4 votes vote down vote up
private boolean compareTableMeta(TableMeta source, TableMeta target) {
    if (!StringUtils.equalsIgnoreCase(source.getSchema(), target.getSchema())) {
        return false;
    }

    if (!StringUtils.equalsIgnoreCase(source.getTable(), target.getTable())) {
        return false;
    }

    List<FieldMeta> sourceFields = source.getFields();
    List<FieldMeta> targetFields = target.getFields();
    if (sourceFields.size() != targetFields.size()) {
        return false;
    }

    for (int i = 0; i < sourceFields.size(); i++) {
        FieldMeta sourceField = sourceFields.get(i);
        FieldMeta targetField = targetFields.get(i);
        if (!StringUtils.equalsIgnoreCase(sourceField.getColumnName(), targetField.getColumnName())) {
            return false;
        }

        // if (!StringUtils.equalsIgnoreCase(sourceField.getColumnType(),
        // targetField.getColumnType())) {
        // return false;
        // }

        // https://github.com/alibaba/canal/issues/1100
        // 支持一下 int vs int(10)
        if ((sourceField.isUnsigned() && !targetField.isUnsigned())
            || (!sourceField.isUnsigned() && targetField.isUnsigned())) {
            return false;
        }

        String sign = sourceField.isUnsigned() ? "unsigned" : "signed";
        String sourceColumnType = StringUtils.removeEndIgnoreCase(sourceField.getColumnType(), sign).trim();
        String targetColumnType = StringUtils.removeEndIgnoreCase(targetField.getColumnType(), sign).trim();

        boolean columnTypeCompare = false;
        columnTypeCompare |= StringUtils.containsIgnoreCase(sourceColumnType, targetColumnType);
        columnTypeCompare |= StringUtils.containsIgnoreCase(targetColumnType, sourceColumnType);
        if (!columnTypeCompare) {
            return false;
        }

        // if (!StringUtils.equalsIgnoreCase(sourceField.getDefaultValue(),
        // targetField.getDefaultValue())) {
        // return false;
        // }

        if (sourceField.isNullable() != targetField.isNullable()) {
            return false;
        }

        // mysql会有一种处理,针对show create只有uk没有pk时,会在desc默认将uk当做pk
        boolean isSourcePkOrUk = sourceField.isKey() || sourceField.isUnique();
        boolean isTargetPkOrUk = targetField.isKey() || targetField.isUnique();
        if (isSourcePkOrUk != isTargetPkOrUk) {
            return false;
        }
    }

    return true;
}
 
Example #6
Source File: DatabaseTableMeta.java    From canal with Apache License 2.0 4 votes vote down vote up
public static boolean compareTableMeta(TableMeta source, TableMeta target) {
    if (!StringUtils.equalsIgnoreCase(source.getSchema(), target.getSchema())) {
        return false;
    }

    if (!StringUtils.equalsIgnoreCase(source.getTable(), target.getTable())) {
        return false;
    }

    List<FieldMeta> sourceFields = source.getFields();
    List<FieldMeta> targetFields = target.getFields();
    if (sourceFields.size() != targetFields.size()) {
        return false;
    }

    /**
     * MySQL DDL的一些默认行为:
     * 
     * <pre>
     * 1. Timestamp类型的列在第一次添加时,未指定默认值会默认为CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
     * 2. Timestamp类型的列在第二次时,必须指定默认值
     * 3. BLOB和TEXT类型不存在NULL、NOT NULL属性
     * 4. 部分数据类型是synonyms,实际show create table时会转成对应类型
     * 5. 非BLOB和TEXT类型在默认未指定NULL、NOT NULL时,默认default null
     * 6. 在列变更时,不仅变更列名数据类型,同时各个约束中列名也会变更,同时如果约束中包含key length,则变更后的数据类型不应违背key length的约束(有长度的应大于key length;BLOB、TEXT应有key length;可以在存在key length情况下变更为无key length的数据类型,约束中key length忽略;等等)
     * 7. 字符集每列(char类、eumn、set)默认保存,指定使用指定的,未指定使用表默认的,不受修改表默认字符集而改变,同表默认时,字符集显示省略
     * 8. 新建表默认innodb引擎,latin1字符集
     * 9. BLOB、TEXT会根据给定长度自动转换为对应的TINY、MEDIUM,LONG类型,长度和字符集也有关
     * 10. unique约束在没有指定索引名是非幂等的,会自动以约束索引第一个列名称命名,同时以_2,_3这种形式添加后缀
     * </pre>
     */

    for (int i = 0; i < sourceFields.size(); i++) {
        FieldMeta sourceField = sourceFields.get(i);
        FieldMeta targetField = targetFields.get(i);
        if (!StringUtils.equalsIgnoreCase(sourceField.getColumnName(), targetField.getColumnName())) {
            return false;
        }

        // if (!StringUtils.equalsIgnoreCase(sourceField.getColumnType(),
        // targetField.getColumnType())) {
        // return false;
        // }

        // https://github.com/alibaba/canal/issues/1100
        // 支持一下 int vs int(10)
        if ((sourceField.isUnsigned() && !targetField.isUnsigned())
            || (!sourceField.isUnsigned() && targetField.isUnsigned())) {
            return false;
        }

        String sourceColumnType = StringUtils.removeEndIgnoreCase(sourceField.getColumnType(), "zerofill").trim();
        String targetColumnType = StringUtils.removeEndIgnoreCase(targetField.getColumnType(), "zerofill").trim();

        String sign = sourceField.isUnsigned() ? "unsigned" : "signed";
        sourceColumnType = StringUtils.removeEndIgnoreCase(sourceColumnType, sign).trim();
        targetColumnType = StringUtils.removeEndIgnoreCase(targetColumnType, sign).trim();

        boolean columnTypeCompare = false;
        columnTypeCompare |= StringUtils.containsIgnoreCase(sourceColumnType, targetColumnType);
        columnTypeCompare |= StringUtils.containsIgnoreCase(targetColumnType, sourceColumnType);
        if (!columnTypeCompare) {
            // 去掉精度参数再对比一次
            sourceColumnType = synonymsType(StringUtils.substringBefore(sourceColumnType, "(")).trim();
            targetColumnType = synonymsType(StringUtils.substringBefore(targetColumnType, "(")).trim();
            columnTypeCompare |= StringUtils.containsIgnoreCase(sourceColumnType, targetColumnType);
            columnTypeCompare |= StringUtils.containsIgnoreCase(targetColumnType, sourceColumnType);
            if (!columnTypeCompare) {
                return false;
            }
        }

        // if (!StringUtils.equalsIgnoreCase(sourceField.getDefaultValue(),
        // targetField.getDefaultValue())) {
        // return false;
        // }

        // BLOB, TEXT, GEOMETRY or JSON默认都是nullable,可以忽略比较,但比较了也是对齐
        if (StringUtils.containsIgnoreCase(sourceColumnType, "timestamp")
            || StringUtils.containsIgnoreCase(targetColumnType, "timestamp")) {
            // timestamp可能会加default current_timestamp默认值,忽略对比nullable
        } else {
            if (sourceField.isNullable() != targetField.isNullable()) {
                return false;
            }
        }

        // mysql会有一种处理,针对show create只有uk没有pk时,会在desc默认将uk当做pk
        boolean isSourcePkOrUk = sourceField.isKey() || sourceField.isUnique();
        boolean isTargetPkOrUk = targetField.isKey() || targetField.isUnique();
        if (isSourcePkOrUk != isTargetPkOrUk) {
            return false;
        }
    }

    return true;
}