/*
* Copyright (C) 2010-2101 Alibaba Group Holding Limited.
*
* 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.alibaba.otter.node.etl.load.loader.db.interceptor.sql;
import java.util.List;
import org.springframework.util.CollectionUtils;
import com.alibaba.otter.node.etl.common.db.dialect.DbDialect;
import com.alibaba.otter.node.etl.common.db.dialect.DbDialectFactory;
import com.alibaba.otter.node.etl.common.db.dialect.SqlTemplate;
import com.alibaba.otter.node.etl.load.loader.db.context.DbLoadContext;
import com.alibaba.otter.node.etl.load.loader.interceptor.AbstractLoadInterceptor;
import com.alibaba.otter.shared.common.model.config.data.db.DbMediaSource;
import com.alibaba.otter.shared.etl.model.EventColumn;
import com.alibaba.otter.shared.etl.model.EventData;
import com.alibaba.otter.shared.etl.model.EventType;
/**
* 计算下最新的sql语句
*
* @author jianghang 2011-12-26 下午12:09:20
* @version 4.0.0
*/
public class SqlBuilderLoadInterceptor extends AbstractLoadInterceptor<DbLoadContext, EventData> {
private DbDialectFactory dbDialectFactory;
public boolean before(DbLoadContext context, EventData currentData) {
// 初步构建sql
DbDialect dbDialect = dbDialectFactory.getDbDialect(context.getIdentity().getPipelineId(),
(DbMediaSource) context.getDataMediaSource());
SqlTemplate sqlTemplate = dbDialect.getSqlTemplate();
EventType type = currentData.getEventType();
String sql = null;
// 注意insert/update语句对应的字段数序都是将主键排在后面
if (type.isInsert()) {
if (CollectionUtils.isEmpty(currentData.getColumns())) { // 如果表为全主键,直接进行insert sql
sql = sqlTemplate.getInsertSql(currentData.getSchemaName(), currentData.getTableName(),
buildColumnNames(currentData.getKeys()),
buildColumnNames(currentData.getColumns()));
} else {
sql = sqlTemplate.getMergeSql(currentData.getSchemaName(), currentData.getTableName(),
buildColumnNames(currentData.getKeys()),
buildColumnNames(currentData.getColumns()), new String[] {});
}
} else if (type.isUpdate()) {
// String[] keyColumns = buildColumnNames(currentData.getKeys());
// String[] otherColumns = buildColumnNames(currentData.getUpdatedColumns());
// boolean existOldKeys = false;
// for (String key : keyColumns) {
// // 找一下otherColumns是否有主键,存在就代表有主键变更
// if (ArrayUtils.contains(otherColumns, key)) {
// existOldKeys = true;
// break;
// }
// }
boolean existOldKeys = !CollectionUtils.isEmpty(currentData.getOldKeys());
boolean rowMode = context.getPipeline().getParameters().getSyncMode().isRow();
String[] keyColumns = null;
String[] otherColumns = null;
if (existOldKeys) {
// 需要考虑主键变更的场景
// 构造sql如下:update table xxx set pk = newPK where pk = oldPk
keyColumns = buildColumnNames(currentData.getOldKeys());
otherColumns = buildColumnNames(currentData.getUpdatedColumns(), currentData.getKeys());
} else {
keyColumns = buildColumnNames(currentData.getKeys());
otherColumns = buildColumnNames(currentData.getUpdatedColumns());
}
if (rowMode && !existOldKeys) {// 如果是行记录,并且不存在主键变更,考虑merge sql
sql = sqlTemplate.getMergeSql(currentData.getSchemaName(), currentData.getTableName(), keyColumns,
otherColumns, new String[] {});
} else {// 否则进行update sql
sql = sqlTemplate.getUpdateSql(currentData.getSchemaName(), currentData.getTableName(), keyColumns,
otherColumns);
}
} else if (type.isDelete()) {
sql = sqlTemplate.getDeleteSql(currentData.getSchemaName(), currentData.getTableName(),
buildColumnNames(currentData.getKeys()));
}
currentData.setSql(sql);
return false;
}
private String[] buildColumnNames(List<EventColumn> columns) {
String[] result = new String[columns.size()];
for (int i = 0; i < columns.size(); i++) {
EventColumn column = columns.get(i);
result[i] = column.getColumnName();
}
return result;
}
private String[] buildColumnNames(List<EventColumn> columns1, List<EventColumn> columns2) {
String[] result = new String[columns1.size() + columns2.size()];
int i = 0;
for (i = 0; i < columns1.size(); i++) {
EventColumn column = columns1.get(i);
result[i] = column.getColumnName();
}
for (; i < columns1.size() + columns2.size(); i++) {
EventColumn column = columns2.get(i - columns1.size());
result[i] = column.getColumnName();
}
return result;
}
// =============== setter / getter =============
public void setDbDialectFactory(DbDialectFactory dbDialectFactory) {
this.dbDialectFactory = dbDialectFactory;
}
}