提交 658332f0 authored 作者: Thomas Mueller's avatar Thomas Mueller

Triggers: INSTEAD OF triggers are now supported.

上级 ed7740d3
......@@ -35,6 +35,7 @@ public class TriggerObject extends SchemaObjectBase {
*/
public static final int DEFAULT_QUEUE_SIZE = 1024;
private boolean insteadOf;
private boolean before;
private int typeMask;
private boolean rowBased;
......@@ -56,6 +57,10 @@ public class TriggerObject extends SchemaObjectBase {
this.before = before;
}
public void setInsteadOf(boolean insteadOf) {
this.insteadOf = insteadOf;
}
private synchronized void load(Session session) throws SQLException {
if (triggerCallback != null) {
return;
......@@ -149,13 +154,14 @@ public class TriggerObject extends SchemaObjectBase {
* @param beforeAction true if this method is called before the operation is
* applied
* @param rollback when the operation occurred within a rollback
* @return true if no further action is required (for 'instead of' triggers)
*/
public void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction, boolean rollback) throws SQLException {
public boolean fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction, boolean rollback) throws SQLException {
if (!rowBased || before != beforeAction) {
return;
return false;
}
if (rollback && !onRollback) {
return;
return false;
}
load(session);
Object[] oldList;
......@@ -177,7 +183,7 @@ public class TriggerObject extends SchemaObjectBase {
}
}
if (!fire) {
return;
return false;
}
oldList = convertToObjectList(oldRow);
newList = convertToObjectList(newRow);
......@@ -217,6 +223,7 @@ public class TriggerObject extends SchemaObjectBase {
session.setCommitOrRollbackDisabled(oldDisabled);
session.setAutoCommit(old);
}
return insteadOf;
}
/**
......@@ -259,7 +266,9 @@ public class TriggerObject extends SchemaObjectBase {
public String getCreateSQLForCopy(Table targetTable, String quotedName) {
StringBuilder buff = new StringBuilder("CREATE FORCE TRIGGER ");
buff.append(quotedName);
if (before) {
if (insteadOf) {
buff.append(" INSTEAD OF ");
} else if (before) {
buff.append(" BEFORE ");
} else {
buff.append(" AFTER ");
......
......@@ -748,10 +748,12 @@ 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
* @return true if no further action is required (for 'instead of' triggers)
*/
public void fireBeforeRow(Session session, Row oldRow, Row newRow) throws SQLException {
fireRow(session, oldRow, newRow, true, false);
public boolean fireBeforeRow(Session session, Row oldRow, Row newRow) throws SQLException {
boolean done = fireRow(session, oldRow, newRow, true, false);
fireConstraints(session, oldRow, newRow, true);
return done;
}
private void fireConstraints(Session session, Row oldRow, Row newRow, boolean before) throws SQLException {
......@@ -779,13 +781,17 @@ public abstract class Table extends SchemaObjectBase {
}
}
private void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction, boolean rollback) throws SQLException {
private boolean 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, rollback);
boolean done = trigger.fireRow(session, oldRow, newRow, beforeAction, rollback);
if (done) {
return true;
}
}
}
return false;
}
public boolean isGlobalTemporary() {
return false;
......
......@@ -37,6 +37,7 @@ public class TestTriggersConstraints extends TestBase implements Trigger {
public void test() throws SQLException {
deleteDb("trigger");
testViewTrigger();
testTriggerBeforeSelect();
testTriggerAlterTable();
testTriggers();
......@@ -44,6 +45,49 @@ public class TestTriggersConstraints extends TestBase implements Trigger {
deleteDb("trigger");
}
private void testViewTrigger() throws SQLException {
Connection conn;
Statement stat;
conn = getConnection("trigger");
stat = conn.createStatement();
stat.execute("drop table if exists test");
stat.execute("create table test(id int)");
stat.execute("create view test_view as select * from test");
stat.execute("create trigger test_view_insert instead of insert on test_view for each row call \"" + TestView.class.getName() + "\"");
if (!config.memory) {
conn.close();
conn = getConnection("trigger");
stat = conn.createStatement();
}
stat.execute("insert into test_view values(1)");
ResultSet rs;
rs = stat.executeQuery("select * from test");
assertTrue(rs.next());
assertFalse(rs.next());
stat.execute("drop view test_view");
stat.execute("drop table test");
conn.close();
}
/**
* A test trigger implementation.
*/
public static class TestView implements Trigger {
PreparedStatement prepInsert;
public void init(Connection conn, String schemaName, String triggerName, String tableName, boolean before,
int type) throws SQLException {
prepInsert = conn.prepareStatement("insert into test values(?)");
}
public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException {
prepInsert.setInt(1, (Integer) newRow[0]);
prepInsert.execute();
}
}
private void testTriggerBeforeSelect() throws SQLException {
Connection conn;
Statement stat;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论