提交 d6fdf1cf authored 作者: Thomas Mueller's avatar Thomas Mueller

Trigger can now be called on rollback.

上级 17dfbe4f
......@@ -3697,6 +3697,7 @@ public class Parser {
isBefore = false;
}
int typeMask = 0;
boolean onRollback = false;
do {
if (readIf("INSERT")) {
typeMask |= Trigger.INSERT;
......@@ -3706,6 +3707,8 @@ public class Parser {
typeMask |= Trigger.DELETE;
} else if (readIf("SELECT")) {
typeMask |= Trigger.SELECT;
} else if (readIf("ROLLBACK")) {
onRollback = true;
} else {
throw getSyntaxError();
}
......@@ -3718,6 +3721,7 @@ public class Parser {
command.setTriggerName(triggerName);
command.setIfNotExists(ifNotExists);
command.setBefore(isBefore);
command.setOnRollback(onRollback);
command.setTypeMask(typeMask);
command.setTableName(tableName);
if (readIf("FOR")) {
......
......@@ -33,6 +33,7 @@ public class CreateTrigger extends SchemaCommand {
private String tableName;
private String triggerClassName;
private boolean force;
private boolean onRollback;
public CreateTrigger(Session session, Schema schema) {
super(session, schema);
......@@ -91,6 +92,7 @@ public class CreateTrigger extends SchemaCommand {
trigger.setQueueSize(queueSize);
trigger.setRowBased(rowBased);
trigger.setTypeMask(typeMask);
trigger.setOnRollback(onRollback);
trigger.setTriggerClassName(session, triggerClassName, force);
db.addSchemaObject(session, trigger);
table.addTrigger(trigger);
......@@ -101,4 +103,8 @@ public class CreateTrigger extends SchemaCommand {
this.force = force;
}
public void setOnRollback(boolean onRollback) {
this.onRollback = onRollback;
}
}
......@@ -74,7 +74,7 @@ public class Delete extends Prepared {
if (table.fireRow()) {
for (rows.reset(); rows.hasNext();) {
Row row = rows.next();
table.fireAfterRow(session, row, null);
table.fireAfterRow(session, row, null, false);
}
}
table.fire(session, Trigger.DELETE, false);
......
......@@ -118,7 +118,7 @@ public class Insert extends Prepared {
table.lock(session, true, false);
table.addRow(session, newRow);
session.log(table, UndoLogRecord.INSERT, newRow);
table.fireAfterRow(session, null, newRow);
table.fireAfterRow(session, null, newRow, false);
count++;
}
} else {
......@@ -144,7 +144,7 @@ public class Insert extends Prepared {
table.fireBeforeRow(session, null, newRow);
table.addRow(session, newRow);
session.log(table, UndoLogRecord.INSERT, newRow);
table.fireAfterRow(session, null, newRow);
table.fireAfterRow(session, null, newRow, false);
}
rows.close();
}
......
......@@ -179,7 +179,7 @@ public class Merge extends Prepared {
table.lock(session, true, false);
table.addRow(session, row);
session.log(table, UndoLogRecord.INSERT, row);
table.fireAfterRow(session, null, row);
table.fireAfterRow(session, null, row, false);
} catch (SQLException e) {
if (e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) {
// concurrent merge or insert
......
......@@ -126,7 +126,7 @@ public class Update extends Prepared {
for (rows.reset(); rows.hasNext();) {
Row o = rows.next();
Row n = rows.next();
table.fireAfterRow(session, o, n);
table.fireAfterRow(session, o, n, false);
}
}
table.fire(session, Trigger.UPDATE, false);
......
......@@ -107,6 +107,7 @@ public class UndoLogRecord {
try {
row.setDeleted(false);
table.removeRow(session, row);
table.fireAfterRow(session, row, null, true);
} catch (SQLException e) {
if (session.getDatabase().getLockMode() == Constants.LOCK_MODE_OFF
&& e.getErrorCode() == ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1) {
......@@ -123,6 +124,7 @@ public class UndoLogRecord {
row.setKey(0);
}
table.addRow(session, row);
table.fireAfterRow(session, null, row, true);
// reset session id, otherwise other session think
// that this row was inserted by this session
row.commit();
......
......@@ -38,6 +38,7 @@ public class TriggerObject extends SchemaObjectBase {
private boolean before;
private int typeMask;
private boolean rowBased;
private boolean onRollback;
// TODO trigger: support queue and noWait = false as well
private int queueSize = DEFAULT_QUEUE_SIZE;
private boolean noWait;
......@@ -147,11 +148,15 @@ public class TriggerObject extends SchemaObjectBase {
* @param newRow the new row
* @param beforeAction true if this method is called before the operation is
* applied
* @param rollback when the operation occurred within a rollback
*/
public void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction) throws SQLException {
public void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction, boolean rollback) throws SQLException {
if (!rowBased || before != beforeAction) {
return;
}
if (rollback && !onRollback) {
return;
}
load(session);
Object[] oldList;
Object[] newList;
......@@ -201,6 +206,12 @@ public class TriggerObject extends SchemaObjectBase {
}
}
}
} catch (SQLException e) {
if (onRollback) {
// ignore
} else {
throw e;
}
} finally {
session.setScopeIdentity(identity);
session.setCommitOrRollbackDisabled(oldDisabled);
......@@ -237,6 +248,10 @@ public class TriggerObject extends SchemaObjectBase {
return noWait;
}
public void setOnRollback(boolean onRollback) {
this.onRollback = onRollback;
}
public String getDropSQL() {
return null;
}
......@@ -249,7 +264,8 @@ public class TriggerObject extends SchemaObjectBase {
} else {
buff.append(" AFTER ");
}
buff.append(getTypeNameList()).append(" ON ").append(table.getSQL());
buff.append(getTypeNameList());
buff.append(" ON ").append(table.getSQL());
if (rowBased) {
buff.append(" FOR EACH ROW");
}
......@@ -280,6 +296,10 @@ public class TriggerObject extends SchemaObjectBase {
buff.appendExceptFirst(", ");
buff.append("SELECT");
}
if (onRollback) {
buff.appendExceptFirst(", ");
buff.append("ROLLBACK");
}
return buff.toString();
}
......
......@@ -750,7 +750,7 @@ public abstract class Table extends SchemaObjectBase {
* @param newRow the new data or null for a delete
*/
public void fireBeforeRow(Session session, Row oldRow, Row newRow) throws SQLException {
fireRow(session, oldRow, newRow, true);
fireRow(session, oldRow, newRow, true, false);
fireConstraints(session, oldRow, newRow, true);
}
......@@ -770,16 +770,19 @@ public abstract class Table extends SchemaObjectBase {
* @param session the session
* @param oldRow the old data or null for an insert
* @param newRow the new data or null for a delete
* @param rollback when the operation occurred within a rollback
*/
public void fireAfterRow(Session session, Row oldRow, Row newRow) throws SQLException {
fireRow(session, oldRow, newRow, false);
fireConstraints(session, oldRow, newRow, false);
public void fireAfterRow(Session session, Row oldRow, Row newRow, boolean rollback) throws SQLException {
fireRow(session, oldRow, newRow, false, rollback);
if (!rollback) {
fireConstraints(session, oldRow, newRow, false);
}
}
private void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction) throws SQLException {
private void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction, boolean rollback) throws SQLException {
if (triggers != null) {
for (TriggerObject trigger : triggers) {
trigger.fireRow(session, oldRow, newRow, beforeAction);
trigger.fireRow(session, oldRow, newRow, beforeAction, rollback);
}
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论