Search in sources :

Example 1 with ColumnItem

use of com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem in project canal by alibaba.

the class ESSyncService method wholeSqlOperation.

/**
 * 关联(子查询), 主表复杂字段operation, 全sql执行
 *
 * @param config es配置
 * @param dml dml信息
 * @param data 单行dml数据
 * @param tableItem 当前表配置
 */
private void wholeSqlOperation(ESSyncConfig config, Dml dml, Map<String, Object> data, Map<String, Object> old, TableItem tableItem) {
    ESMapping mapping = config.getEsMapping();
    // 防止最后出现groupby 导致sql解析异常
    String[] sqlSplit = mapping.getSql().split("GROUP\\ BY(?!(.*)ON)");
    String sqlNoWhere = sqlSplit[0];
    String sqlGroupBy = "";
    if (sqlSplit.length > 1) {
        sqlGroupBy = "GROUP BY " + sqlSplit[1];
    }
    StringBuilder sql = new StringBuilder(sqlNoWhere + " WHERE ");
    for (FieldItem fkFieldItem : tableItem.getRelationTableFields().keySet()) {
        String columnName = fkFieldItem.getColumn().getColumnName();
        Object value = esTemplate.getValFromData(mapping, data, fkFieldItem.getFieldName(), columnName);
        ESSyncUtil.appendCondition(sql, value, tableItem.getAlias(), columnName);
    }
    int len = sql.length();
    sql.delete(len - 5, len);
    sql.append(sqlGroupBy);
    DataSource ds = DatasourceConfig.DATA_SOURCES.get(config.getDataSourceKey());
    if (logger.isTraceEnabled()) {
        logger.trace("Join table update es index by query whole sql, destination:{}, table: {}, index: {}, sql: {}", config.getDestination(), dml.getTable(), mapping.get_index(), sql.toString().replace("\n", " "));
    }
    Util.sqlRS(ds, sql.toString(), rs -> {
        try {
            while (rs.next()) {
                Map<String, Object> esFieldData = new LinkedHashMap<>();
                for (FieldItem fieldItem : tableItem.getRelationSelectFieldItems()) {
                    if (old != null) {
                        // 从表子查询
                        out: for (FieldItem fieldItem1 : tableItem.getSubQueryFields()) {
                            for (ColumnItem columnItem0 : fieldItem.getColumnItems()) {
                                if (fieldItem1.getFieldName().equals(columnItem0.getColumnName()))
                                    for (ColumnItem columnItem : fieldItem1.getColumnItems()) {
                                        if (old.containsKey(columnItem.getColumnName())) {
                                            Object val = esTemplate.getValFromRS(mapping, rs, fieldItem.getFieldName(), fieldItem.getFieldName());
                                            esFieldData.put(fieldItem.getFieldName(), val);
                                            break out;
                                        }
                                    }
                            }
                        }
                        // 从表非子查询
                        for (FieldItem fieldItem1 : tableItem.getRelationSelectFieldItems()) {
                            if (fieldItem1.equals(fieldItem)) {
                                for (ColumnItem columnItem : fieldItem1.getColumnItems()) {
                                    if (old.containsKey(columnItem.getColumnName())) {
                                        Object val = esTemplate.getValFromRS(mapping, rs, fieldItem.getFieldName(), fieldItem.getFieldName());
                                        esFieldData.put(Util.cleanColumn(fieldItem.getFieldName()), val);
                                        break;
                                    }
                                }
                            }
                        }
                    } else {
                        Object val = esTemplate.getValFromRS(mapping, rs, fieldItem.getFieldName(), fieldItem.getFieldName());
                        esFieldData.put(Util.cleanColumn(fieldItem.getFieldName()), val);
                    }
                }
                Map<String, Object> paramsTmp = new LinkedHashMap<>();
                for (Map.Entry<FieldItem, List<FieldItem>> entry : tableItem.getRelationTableFields().entrySet()) {
                    for (FieldItem fieldItem : entry.getValue()) {
                        Object value = esTemplate.getValFromRS(mapping, rs, fieldItem.getFieldName(), fieldItem.getFieldName());
                        String fieldName = fieldItem.getFieldName();
                        // 判断是否是主键
                        if (fieldName.equals(mapping.get_id())) {
                            fieldName = "_id";
                        }
                        paramsTmp.put(fieldName, value);
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.trace("Join table update es index by query whole sql, destination:{}, table: {}, index: {}", config.getDestination(), dml.getTable(), mapping.get_index());
                }
                esTemplate.updateByQuery(config, paramsTmp, esFieldData);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return 0;
    });
}
Also used : ColumnItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem) DataSource(javax.sql.DataSource) LinkedHashMap(java.util.LinkedHashMap) ESMapping(com.alibaba.otter.canal.client.adapter.es.core.config.ESSyncConfig.ESMapping) ArrayList(java.util.ArrayList) List(java.util.List) FieldItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.FieldItem) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 2 with ColumnItem

use of com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem in project canal by alibaba.

the class ESSyncService method update.

/**
 * 更新操作dml
 *
 * @param config es配置
 * @param dml dml数据
 */
private void update(ESSyncConfig config, Dml dml) {
    List<Map<String, Object>> dataList = dml.getData();
    List<Map<String, Object>> oldList = dml.getOld();
    if (dataList == null || dataList.isEmpty() || oldList == null || oldList.isEmpty()) {
        return;
    }
    SchemaItem schemaItem = config.getEsMapping().getSchemaItem();
    int i = 0;
    for (Map<String, Object> data : dataList) {
        Map<String, Object> old = oldList.get(i);
        if (data == null || data.isEmpty() || old == null || old.isEmpty()) {
            continue;
        }
        if (schemaItem.getAliasTableItems().size() == 1 && schemaItem.isAllFieldsSimple()) {
            // ------单表 & 所有字段都为简单字段------
            singleTableSimpleFiledUpdate(config, dml, data, old);
        } else {
            // ------主表 查询sql来更新------
            if (schemaItem.getMainTable().getTableName().equalsIgnoreCase(dml.getTable())) {
                ESMapping mapping = config.getEsMapping();
                String idFieldName = mapping.get_id() == null ? mapping.getPk() : mapping.get_id();
                FieldItem idFieldItem = schemaItem.getSelectFields().get(idFieldName);
                boolean idFieldSimple = true;
                if (idFieldItem.isMethod() || idFieldItem.isBinaryOp()) {
                    idFieldSimple = false;
                }
                boolean allUpdateFieldSimple = true;
                out: for (FieldItem fieldItem : schemaItem.getSelectFields().values()) {
                    for (ColumnItem columnItem : fieldItem.getColumnItems()) {
                        if (old.containsKey(columnItem.getColumnName())) {
                            if (fieldItem.isMethod() || fieldItem.isBinaryOp()) {
                                allUpdateFieldSimple = false;
                                break out;
                            }
                        }
                    }
                }
                // 不支持主键更新!!
                // 判断是否有外键更新
                boolean fkChanged = false;
                for (TableItem tableItem : schemaItem.getAliasTableItems().values()) {
                    if (tableItem.isMain()) {
                        continue;
                    }
                    boolean changed = false;
                    for (List<FieldItem> fieldItems : tableItem.getRelationTableFields().values()) {
                        for (FieldItem fieldItem : fieldItems) {
                            if (old.containsKey(fieldItem.getColumn().getColumnName())) {
                                fkChanged = true;
                                changed = true;
                                break;
                            }
                        }
                    }
                    // 如果外键有修改,则更新所对应该表的所有查询条件数据
                    if (changed) {
                        for (FieldItem fieldItem : tableItem.getRelationSelectFieldItems()) {
                            fieldItem.getColumnItems().forEach(columnItem -> old.put(columnItem.getColumnName(), null));
                        }
                    }
                }
                // 判断主键和所更新的字段是否全为简单字段
                if (idFieldSimple && allUpdateFieldSimple && !fkChanged) {
                    singleTableSimpleFiledUpdate(config, dml, data, old);
                } else {
                    mainTableUpdate(config, dml, data, old);
                }
            }
            // 从表的操作
            for (TableItem tableItem : schemaItem.getAliasTableItems().values()) {
                if (tableItem.isMain()) {
                    continue;
                }
                if (!tableItem.getTableName().equals(dml.getTable())) {
                    continue;
                }
                // 关联条件出现在主表查询条件是否为简单字段
                boolean allFieldsSimple = true;
                for (FieldItem fieldItem : tableItem.getRelationSelectFieldItems()) {
                    if (fieldItem.isMethod() || fieldItem.isBinaryOp()) {
                        allFieldsSimple = false;
                        break;
                    }
                }
                // 所有查询字段均为简单字段
                if (allFieldsSimple) {
                    // 不是子查询
                    if (!tableItem.isSubQuery()) {
                        // ------关联表简单字段更新------
                        Map<String, Object> esFieldData = new LinkedHashMap<>();
                        for (FieldItem fieldItem : tableItem.getRelationSelectFieldItems()) {
                            if (old.containsKey(fieldItem.getColumn().getColumnName())) {
                                Object value = esTemplate.getValFromData(config.getEsMapping(), data, fieldItem.getFieldName(), fieldItem.getColumn().getColumnName());
                                esFieldData.put(Util.cleanColumn(fieldItem.getFieldName()), value);
                            }
                        }
                        joinTableSimpleFieldOperation(config, dml, data, tableItem, esFieldData);
                    } else {
                        // ------关联子表简单字段更新------
                        subTableSimpleFieldOperation(config, dml, data, old, tableItem);
                    }
                } else {
                    // ------关联子表复杂字段更新 执行全sql更新es------
                    wholeSqlOperation(config, dml, data, old, tableItem);
                }
            }
        }
        i++;
    }
}
Also used : SchemaItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem) ColumnItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem) TableItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.TableItem) LinkedHashMap(java.util.LinkedHashMap) ESMapping(com.alibaba.otter.canal.client.adapter.es.core.config.ESSyncConfig.ESMapping) FieldItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.FieldItem) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 3 with ColumnItem

use of com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem in project canal by alibaba.

the class ES6xTemplate method getESDataFromRS.

@Override
public Object getESDataFromRS(ESSyncConfig.ESMapping mapping, ResultSet resultSet, Map<String, Object> dmlOld, Map<String, Object> esFieldData) throws SQLException {
    SchemaItem schemaItem = mapping.getSchemaItem();
    String idFieldName = mapping.get_id() == null ? mapping.getPk() : mapping.get_id();
    Object resultIdVal = null;
    for (FieldItem fieldItem : schemaItem.getSelectFields().values()) {
        if (fieldItem.getFieldName().equals(idFieldName)) {
            resultIdVal = getValFromRS(mapping, resultSet, fieldItem.getFieldName(), fieldItem.getFieldName());
        }
        for (ColumnItem columnItem : fieldItem.getColumnItems()) {
            if (dmlOld.containsKey(columnItem.getColumnName()) && !mapping.getSkips().contains(fieldItem.getFieldName())) {
                esFieldData.put(Util.cleanColumn(fieldItem.getFieldName()), getValFromRS(mapping, resultSet, fieldItem.getFieldName(), fieldItem.getFieldName()));
                break;
            }
        }
    }
    // 添加父子文档关联信息
    putRelationDataFromRS(mapping, schemaItem, resultSet, esFieldData);
    return resultIdVal;
}
Also used : SchemaItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem) ColumnItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem) FieldItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.FieldItem)

Example 4 with ColumnItem

use of com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem in project canal by alibaba.

the class ES7xTemplate method getESDataFromRS.

@Override
public Object getESDataFromRS(ESMapping mapping, ResultSet resultSet, Map<String, Object> dmlOld, Map<String, Object> esFieldData) throws SQLException {
    SchemaItem schemaItem = mapping.getSchemaItem();
    String idFieldName = mapping.get_id() == null ? mapping.getPk() : mapping.get_id();
    Object resultIdVal = null;
    for (FieldItem fieldItem : schemaItem.getSelectFields().values()) {
        if (fieldItem.getFieldName().equals(idFieldName)) {
            resultIdVal = getValFromRS(mapping, resultSet, fieldItem.getFieldName(), fieldItem.getFieldName());
        }
        for (ColumnItem columnItem : fieldItem.getColumnItems()) {
            if (dmlOld.containsKey(columnItem.getColumnName()) && !mapping.getSkips().contains(fieldItem.getFieldName())) {
                esFieldData.put(Util.cleanColumn(fieldItem.getFieldName()), getValFromRS(mapping, resultSet, fieldItem.getFieldName(), fieldItem.getFieldName()));
                break;
            }
        }
    }
    // 添加父子文档关联信息
    putRelationDataFromRS(mapping, schemaItem, resultSet, esFieldData);
    return resultIdVal;
}
Also used : SchemaItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem) ColumnItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem) FieldItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.FieldItem)

Example 5 with ColumnItem

use of com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem in project canal by alibaba.

the class SqlParser method visitColumn.

/**
 * 解析字段
 *
 * @param expr sql expr
 * @param fieldItem 字段属性
 */
private static void visitColumn(SQLExpr expr, FieldItem fieldItem) {
    if (expr instanceof SQLIdentifierExpr) {
        // 无owner
        SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;
        if (fieldItem.getFieldName() == null) {
            fieldItem.setFieldName(identifierExpr.getName());
            fieldItem.setExpr(identifierExpr.toString());
        }
        ColumnItem columnItem = new ColumnItem();
        columnItem.setColumnName(identifierExpr.getName());
        fieldItem.getOwners().add(null);
        fieldItem.addColumn(columnItem);
    } else if (expr instanceof SQLPropertyExpr) {
        // 有owner
        SQLPropertyExpr sqlPropertyExpr = (SQLPropertyExpr) expr;
        if (fieldItem.getFieldName() == null) {
            fieldItem.setFieldName(sqlPropertyExpr.getName());
            fieldItem.setExpr(sqlPropertyExpr.toString());
        }
        fieldItem.getOwners().add(sqlPropertyExpr.getOwnernName());
        ColumnItem columnItem = new ColumnItem();
        columnItem.setColumnName(sqlPropertyExpr.getName());
        columnItem.setOwner(sqlPropertyExpr.getOwnernName());
        fieldItem.addColumn(columnItem);
    } else if (expr instanceof SQLMethodInvokeExpr) {
        SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) expr;
        fieldItem.setMethod(true);
        for (SQLExpr sqlExpr : methodInvokeExpr.getArguments()) {
            visitColumn(sqlExpr, fieldItem);
        }
    } else if (expr instanceof SQLBinaryOpExpr) {
        SQLBinaryOpExpr sqlBinaryOpExpr = (SQLBinaryOpExpr) expr;
        fieldItem.setBinaryOp(true);
        visitColumn(sqlBinaryOpExpr.getLeft(), fieldItem);
        visitColumn(sqlBinaryOpExpr.getRight(), fieldItem);
    } else if (expr instanceof SQLCaseExpr) {
        SQLCaseExpr sqlCaseExpr = (SQLCaseExpr) expr;
        fieldItem.setMethod(true);
        sqlCaseExpr.getItems().forEach(item -> visitColumn(item.getConditionExpr(), fieldItem));
    } else if (expr instanceof SQLCharExpr) {
        SQLCharExpr sqlCharExpr = (SQLCharExpr) expr;
        String owner = null;
        String columnName = null;
        if (sqlCharExpr.getParent() instanceof SQLCaseExpr.Item) {
            owner = ((SQLPropertyExpr) ((SQLCaseExpr.Item) sqlCharExpr.getParent()).getValueExpr()).getOwnernName();
            columnName = ((SQLPropertyExpr) ((SQLCaseExpr.Item) sqlCharExpr.getParent()).getValueExpr()).getName();
        }
        if (fieldItem.getFieldName() == null) {
            fieldItem.setFieldName(columnName);
            fieldItem.setExpr(sqlCharExpr.toString());
        }
        ColumnItem columnItem = new ColumnItem();
        columnItem.setColumnName(columnName);
        columnItem.setOwner(owner);
        fieldItem.getOwners().add(owner);
        fieldItem.addColumn(columnItem);
    }
}
Also used : SQLCharExpr(com.alibaba.druid.sql.ast.expr.SQLCharExpr) SQLMethodInvokeExpr(com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr) ColumnItem(com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem) SQLIdentifierExpr(com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr) SQLBinaryOpExpr(com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr) SQLPropertyExpr(com.alibaba.druid.sql.ast.expr.SQLPropertyExpr) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr) SQLCaseExpr(com.alibaba.druid.sql.ast.expr.SQLCaseExpr)

Aggregations

ColumnItem (com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.ColumnItem)7 FieldItem (com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.FieldItem)5 SchemaItem (com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem)4 ESMapping (com.alibaba.otter.canal.client.adapter.es.core.config.ESSyncConfig.ESMapping)3 LinkedHashMap (java.util.LinkedHashMap)3 Map (java.util.Map)3 TableItem (com.alibaba.otter.canal.client.adapter.es.core.config.SchemaItem.TableItem)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 DataSource (javax.sql.DataSource)2 SQLExpr (com.alibaba.druid.sql.ast.SQLExpr)1 SQLBinaryOpExpr (com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr)1 SQLCaseExpr (com.alibaba.druid.sql.ast.expr.SQLCaseExpr)1 SQLCharExpr (com.alibaba.druid.sql.ast.expr.SQLCharExpr)1 SQLIdentifierExpr (com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr)1 SQLMethodInvokeExpr (com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr)1 SQLPropertyExpr (com.alibaba.druid.sql.ast.expr.SQLPropertyExpr)1 MySqlSelectQueryBlock (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock)1 LinkedHashSet (java.util.LinkedHashSet)1