}
public int update() {
tableFilter.startQuery(session);
tableFilter.reset();
RowList rows = new RowList(session);
try {
Table table = tableFilter.getTable();
session.getUser().checkRight(table, Right.UPDATE);
table.fire(session, Trigger.UPDATE, true);
table.lock(session, true, false);
int columnCount = table.getColumns().length;
// get the old rows, compute the new rows
setCurrentRowNumber(0);
int count = 0;
Column[] columns = table.getColumns();
int limitRows = -1;
if (limitExpr != null) {
Value v = limitExpr.getValue(session);
if (v != ValueNull.INSTANCE) {
limitRows = v.getInt();
}
}
while (tableFilter.next()) {
setCurrentRowNumber(count + 1);
if (limitRows >= 0 && count >= limitRows) {
break;
}
if (condition == null || Boolean.TRUE.equals(condition.getBooleanValue(session))) {
Row oldRow = tableFilter.get();
Row newRow = table.getTemplateRow();
newRow.setTransactionId(session.getTransaction().getTransactionId());
for (int i = 0; i < columnCount; i++) {
Expression newExpr = expressionMap.get(columns[i]);
Value newValue;
if (newExpr == null) {
newValue = oldRow.getValue(i);
} else if (newExpr == ValueExpression.getDefault()) {
Column column = table.getColumn(i);
newValue = table.getDefaultValue(session, column);
} else {
Column column = table.getColumn(i);
newValue = column.convert(newExpr.getValue(session));
}
newRow.setValue(i, newValue);
}
table.validateConvertUpdateSequence(session, newRow);
boolean done = false;
if (table.fireRow()) {
done = table.fireBeforeRow(session, oldRow, newRow);
}
if (!done) {
rows.add(oldRow);
rows.add(newRow);
}
count++;
}
}
// TODO self referencing referential integrity constraints
// don't work if update is multi-row and 'inversed' the condition!
// probably need multi-row triggers with 'deleted' and 'inserted'
// at the same time. anyway good for sql compatibility
// TODO update in-place (but if the key changes,
// we need to update all indexes) before row triggers
// the cached row is already updated - we need the old values
table.updateRows(this, session, rows);
if (table.fireRow()) {
rows.invalidateCache();
for (rows.reset(); rows.hasNext();) {
Row o = rows.next();
Row n = rows.next();
table.fireAfterRow(session, o, n, false);
}
}
table.fire(session, Trigger.UPDATE, false);
return count;
} finally {
rows.close();
}
}