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

Non-row based triggers were called even if the action didn't match the declared action.

上级 5eca85f1
......@@ -7,6 +7,7 @@
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.api.Trigger;
import org.h2.command.Prepared;
import org.h2.engine.Right;
import org.h2.engine.Session;
......@@ -46,7 +47,7 @@ public class Delete extends Prepared {
tableFilter.reset();
Table table = tableFilter.getTable();
session.getUser().checkRight(table, Right.DELETE);
table.fireBefore(session);
table.fire(session, Trigger.DELETE, true);
table.lock(session, true, false);
RowList rows = new RowList(session);
try {
......@@ -76,7 +77,7 @@ public class Delete extends Prepared {
table.fireAfterRow(session, row, null);
}
}
table.fireAfter(session);
table.fire(session, Trigger.DELETE, false);
return rows.size();
} finally {
rows.close();
......
......@@ -7,6 +7,7 @@
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.api.Trigger;
import org.h2.command.Command;
import org.h2.command.Prepared;
import org.h2.constant.ErrorCode;
......@@ -90,6 +91,7 @@ public class Insert extends Prepared {
int count;
session.getUser().checkRight(table, Right.INSERT);
setCurrentRowNumber(0);
table.fire(session, Trigger.INSERT, true);
if (list.size() > 0) {
count = 0;
for (int x = 0; x < list.size(); x++) {
......@@ -111,20 +113,17 @@ public class Insert extends Prepared {
}
}
}
table.fireBefore(session);
table.validateConvertUpdateSequence(session, newRow);
table.fireBeforeRow(session, null, newRow);
table.lock(session, true, false);
table.addRow(session, newRow);
session.log(table, UndoLogRecord.INSERT, newRow);
table.fireAfter(session);
table.fireAfterRow(session, null, newRow);
count++;
}
} else {
ResultInterface rows = query.query(0);
count = 0;
table.fireBefore(session);
table.lock(session, true, false);
while (rows.next()) {
count++;
......@@ -148,8 +147,8 @@ public class Insert extends Prepared {
table.fireAfterRow(session, null, newRow);
}
rows.close();
table.fireAfter(session);
}
table.fire(session, Trigger.INSERT, false);
return count;
}
......
......@@ -7,6 +7,7 @@
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.api.Trigger;
import org.h2.command.Command;
import org.h2.command.Prepared;
import org.h2.constant.ErrorCode;
......@@ -128,7 +129,7 @@ public class Merge extends Prepared {
} else {
ResultInterface rows = query.query(0);
count = 0;
table.fireBefore(session);
table.fire(session, Trigger.UPDATE | Trigger.INSERT, true);
table.lock(session, true, false);
while (rows.next()) {
count++;
......@@ -148,7 +149,7 @@ public class Merge extends Prepared {
merge(newRow);
}
rows.close();
table.fireAfter(session);
table.fire(session, Trigger.UPDATE | Trigger.INSERT, false);
}
return count;
}
......@@ -173,13 +174,11 @@ public class Merge extends Prepared {
int count = update.update();
if (count == 0) {
try {
table.fireBefore(session);
table.validateConvertUpdateSequence(session, row);
table.fireBeforeRow(session, null, row);
table.lock(session, true, false);
table.addRow(session, row);
session.log(table, UndoLogRecord.INSERT, row);
table.fireAfter(session);
table.fireAfterRow(session, null, row);
} catch (SQLException e) {
if (e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) {
......
......@@ -7,6 +7,7 @@
package org.h2.command.dml;
import java.sql.SQLException;
import org.h2.api.Trigger;
import org.h2.command.Prepared;
import org.h2.constant.ErrorCode;
import org.h2.engine.Right;
......@@ -77,7 +78,7 @@ public class Update extends Prepared {
try {
Table table = tableFilter.getTable();
session.getUser().checkRight(table, Right.UPDATE);
table.fireBefore(session);
table.fire(session, Trigger.UPDATE, true);
table.lock(session, true, false);
int columnCount = table.getColumns().length;
// get the old rows, compute the new rows
......@@ -128,7 +129,7 @@ public class Update extends Prepared {
table.fireAfterRow(session, o, n);
}
}
table.fireAfter(session);
table.fire(session, Trigger.UPDATE, false);
return count;
} finally {
rows.close();
......
......@@ -718,29 +718,16 @@ public abstract class Table extends SchemaObjectBase {
}
/**
* Fire the before update triggers for this table.
* Fire the triggers for this table.
*
* @param session the session
* @param type the trigger type
* @param beforeAction whether 'before' triggers should be called
*/
public void fireBefore(Session session) throws SQLException {
// TODO trigger: for sql server compatibility,
// should send list of rows, not just 'the event'
fire(session, true);
}
/**
* Fire the after update triggers for this table.
*
* @param session the session
*/
public void fireAfter(Session session) throws SQLException {
fire(session, false);
}
private void fire(Session session, boolean beforeAction) throws SQLException {
public void fire(Session session, int type, boolean beforeAction) throws SQLException {
if (triggers != null) {
for (TriggerObject trigger : triggers) {
trigger.fire(session, beforeAction);
trigger.fire(session, type, beforeAction);
}
}
}
......
......@@ -7,6 +7,7 @@
package org.h2.test.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
......@@ -36,12 +37,65 @@ public class TestTriggersConstraints extends TestBase implements Trigger {
public void test() throws SQLException {
deleteDb("trigger");
testTriggerBeforeSelect();
testTriggerAlterTable();
testTriggers();
testConstraints();
deleteDb("trigger");
}
private void testTriggerBeforeSelect() throws SQLException {
Connection conn;
Statement stat;
conn = getConnection("trigger");
stat = conn.createStatement();
stat.execute("drop table if exists meta_tables");
stat.execute("create table meta_tables(name varchar)");
stat.execute("create trigger meta_tables_sel before select on meta_tables call \"" + TestSelect.class.getName() + "\"");
ResultSet rs;
rs = stat.executeQuery("select * from meta_tables");
assertTrue(rs.next());
assertFalse(rs.next());
stat.execute("create table test(id int)");
rs = stat.executeQuery("select * from meta_tables");
assertTrue(rs.next());
assertTrue(rs.next());
assertFalse(rs.next());
conn.close();
if (!config.memory) {
conn = getConnection("trigger");
stat = conn.createStatement();
stat.execute("create table test2(id int)");
rs = stat.executeQuery("select * from meta_tables");
assertTrue(rs.next());
assertTrue(rs.next());
assertTrue(rs.next());
assertFalse(rs.next());
conn.close();
}
}
/**
* A test trigger implementation.
*/
public static class TestSelect implements Trigger {
PreparedStatement prepMeta;
public void init(Connection conn, String schemaName, String triggerName, String tableName, boolean before,
int type) throws SQLException {
prepMeta = conn.prepareStatement("insert into meta_tables " +
"select table_name from information_schema.tables " +
"where table_schema='PUBLIC'");
}
public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException {
conn.createStatement().execute("delete from meta_tables");
prepMeta.execute();
}
}
/**
* A test trigger implementation.
*/
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论