
org.lealone.sql.dml.UpDel Maven / Gradle / Ivy
/*
* Copyright Lealone Database Group.
* Licensed under the Server Side Public License, v 1.
* Initial Developer: zhh
*/
package org.lealone.sql.dml;
import org.lealone.common.util.StatementBuilder;
import org.lealone.common.util.StringUtils;
import org.lealone.db.DataHandler;
import org.lealone.db.async.AsyncHandler;
import org.lealone.db.async.AsyncResult;
import org.lealone.db.lock.DbObjectLock;
import org.lealone.db.result.Row;
import org.lealone.db.session.ServerSession;
import org.lealone.db.table.Table;
import org.lealone.db.value.Value;
import org.lealone.db.value.ValueNull;
import org.lealone.sql.StatementBase;
import org.lealone.sql.executor.YieldableLoopUpdateBase;
import org.lealone.sql.expression.Expression;
import org.lealone.sql.expression.evaluator.AlwaysTrueEvaluator;
import org.lealone.sql.expression.evaluator.ExpressionEvaluator;
import org.lealone.sql.expression.evaluator.ExpressionInterpreter;
import org.lealone.sql.optimizer.TableFilter;
import org.lealone.sql.optimizer.TableIterator;
// update和delete的基类
public abstract class UpDel extends ManipulationStatement {
protected TableFilter tableFilter;
protected Expression condition;
/**
* The limit expression as specified in the LIMIT or TOP clause.
*/
protected Expression limitExpr;
public UpDel(ServerSession session) {
super(session);
}
@Override
public boolean isCacheable() {
return true;
}
public void setTableFilter(TableFilter tableFilter) {
this.tableFilter = tableFilter;
}
public void setCondition(Expression condition) {
this.condition = condition;
}
public void setLimit(Expression limit) {
this.limitExpr = limit;
}
@Override
public int getPriority() {
if (getCurrentRowNumber() > 0)
return priority;
priority = NORM_PRIORITY - 1;
return priority;
}
@Override
public int update() {
return syncExecute(createYieldableUpdate(null));
}
protected void appendPlanSQL(StatementBuilder buff) {
if (condition != null) {
buff.append("\nWHERE ").append(StringUtils.unEnclose(condition.getSQL()));
}
if (limitExpr != null) {
buff.append("\nLIMIT (").append(StringUtils.unEnclose(limitExpr.getSQL())).append(')');
}
}
protected static abstract class YieldableUpDel extends YieldableLoopUpdateBase {
protected final Table table;
private final int limitRows; // 如果是0,表示不删除任何记录;如果小于0,表示没有限制
private final ExpressionEvaluator conditionEvaluator;
private final TableIterator tableIterator;
public YieldableUpDel(StatementBase statement, AsyncHandler> asyncHandler,
TableFilter tableFilter, Expression limitExpr, Expression condition) {
super(statement, asyncHandler);
table = tableFilter.getTable();
int limitRows = -1;
if (limitExpr != null) {
Value v = limitExpr.getValue(session);
if (v != ValueNull.INSTANCE) {
limitRows = v.getInt();
}
}
this.limitRows = limitRows;
if (limitRows == 0) {
tableIterator = new TableIterator(session, tableFilter) {
@Override
public boolean next() {
return false;
}
};
} else {
tableIterator = new TableIterator(session, tableFilter);
}
if (condition == null)
conditionEvaluator = new AlwaysTrueEvaluator();
else
conditionEvaluator = new ExpressionInterpreter(session, condition);
}
protected abstract int getRightMask();
protected abstract int getTriggerType();
protected abstract boolean upDelRow(Row oldRow);
@Override
protected boolean startInternal() {
if (!table.trySharedLock(session))
return true;
session.getUser().checkRight(table, getRightMask());
table.fire(session, getTriggerType(), true);
statement.setCurrentRowNumber(0);
tableIterator.start();
return false;
}
@Override
protected void stopInternal() {
table.fire(session, getTriggerType(), false);
}
protected int[] getUpdateColumnIndexes() {
return null;
}
@Override
protected void executeLoopUpdate() {
try {
if (table.containsLargeObject()) {
DataHandler dh = session.getDataHandler();
session.setDataHandler(table.getDataHandler()); // lob字段通过FILE_READ函数赋值时会用到
try {
executeLoopUpdate0();
} finally {
session.setDataHandler(dh);
}
} else {
executeLoopUpdate0();
}
} catch (RuntimeException e) {
if (DbObjectLock.LOCKED_EXCEPTION == e) {
tableIterator.onLockedException();
} else {
throw e;
}
}
}
private void executeLoopUpdate0() {
while (tableIterator.next() && pendingException == null) {
// 不能直接return,执行完一次后再return,否则执行next()得到的记录被跳过了,会产生严重的问题
boolean yield = yieldIfNeeded(++loopCount);
if (conditionEvaluator.getBooleanValue()) {
int ret = tableIterator.tryLockRow(getUpdateColumnIndexes());
if (ret < 0) {
continue;
} else if (ret == 0) { // 被其他事务锁住了
return;
}
Row row = tableIterator.getRow();
if (upDelRow(row)) {
if (limitRows > 0 && updateCount.get() >= limitRows) {
break;
}
}
}
if (yield)
return;
}
onLoopEnd();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy