package com.taobao.tddl.executor.handler;
import java.util.ArrayList;
import java.util.List;
import com.taobao.tddl.common.exception.TddlException;
import com.taobao.tddl.common.utils.GeneralUtil;
import com.taobao.tddl.executor.codec.CodecFactory;
import com.taobao.tddl.executor.common.ExecutionContext;
import com.taobao.tddl.executor.common.ExecutorContext;
import com.taobao.tddl.executor.cursor.ISchematicCursor;
import com.taobao.tddl.executor.function.ExtraFunction;
import com.taobao.tddl.executor.record.CloneableRecord;
import com.taobao.tddl.executor.rowset.IRowSet;
import com.taobao.tddl.executor.spi.ITable;
import com.taobao.tddl.executor.spi.ITransaction;
import com.taobao.tddl.executor.utils.ExecUtils;
import com.taobao.tddl.optimizer.config.table.ColumnMeta;
import com.taobao.tddl.optimizer.config.table.IndexMeta;
import com.taobao.tddl.optimizer.core.expression.IFunction;
import com.taobao.tddl.optimizer.core.plan.IPut;
import com.taobao.tddl.optimizer.core.plan.IPut.PUT_TYPE;
public class UpdateHandler extends PutHandlerCommon {
public UpdateHandler(){
super();
}
@SuppressWarnings("rawtypes")
@Override
protected int executePut(ExecutionContext executionContext, IPut put, ITable table, IndexMeta meta)
throws TddlException {
ITransaction transaction = executionContext.getTransaction();
int affect_rows = 0;
IPut update = put;
ISchematicCursor conditionCursor = null;
try {
conditionCursor = ExecutorContext.getContext()
.getTopologyExecutor()
.execByExecPlanNode(update.getQueryTree(), executionContext);
IRowSet kv = null;
IndexMeta primaryMeta = table.getSchema().getPrimaryIndex();
CloneableRecord key = CodecFactory.getInstance(CodecFactory.FIXED_LENGTH)
.getCodec(primaryMeta.getKeyColumns())
.newEmptyRecord();
CloneableRecord value = CodecFactory.getInstance(CodecFactory.FIXED_LENGTH)
.getCodec(primaryMeta.getValueColumns())
.newEmptyRecord();
while ((kv = conditionCursor.next()) != null) {
affect_rows++;
for (ColumnMeta cm : primaryMeta.getValueColumns()) {
Object val = getValByColumnMeta(kv, cm);
value.put(cm.getName(), val);
for (int i = 0; i < update.getUpdateColumns().size(); i++) {
String cname = ExecUtils.getColumn(update.getUpdateColumns().get(i)).getColumnName();
if (cm.getName().equals(cname)) {
Object v = update.getUpdateValues().get(i);
if (v instanceof IFunction) {
IFunction func = ((IFunction) v);
((ExtraFunction) func.getExtraFunction()).serverMap((IRowSet) null);
v = func.getExtraFunction().getResult();
}
value.put(cname, v);
}
}
}
for (ColumnMeta cm : primaryMeta.getKeyColumns()) {
Object val = getValByColumnMeta(kv, cm);
key.put(cm.getName(), val);
for (int i = 0; i < update.getUpdateColumns().size(); i++) {
String cname = (ExecUtils.getColumn(update.getUpdateColumns().get(i))).getColumnName();
Object v = update.getUpdateValues().get(i);
if (cm.getName().equals(cname)) {
key.put(cname, v);
}
}
}
prepare(transaction, table, kv, key, value, PUT_TYPE.UPDATE);
table.put(executionContext, key, value, meta, put.getTableName());
}
} catch (TddlException ex) {
throw ex;
} finally {
if (conditionCursor != null) {
List<TddlException> exs = new ArrayList();
exs = conditionCursor.close(exs);
if (!exs.isEmpty()) {
throw GeneralUtil.mergeException(exs);
}
}
}
return affect_rows;
}
private Object getValByColumnMeta(IRowSet kv, ColumnMeta cm) {
Object val = ExecUtils.getValueByTableAndName(kv, cm.getTableName(), cm.getName());
return val;
}
}