1 5 package org.h2.schema; 6 7 import java.sql.Connection ; 8 import java.sql.SQLException ; 9 10 import org.h2.api.Trigger; 11 import org.h2.command.Parser; 12 import org.h2.engine.DbObject; 13 import org.h2.engine.Session; 14 import org.h2.message.Message; 15 import org.h2.message.Trace; 16 import org.h2.result.Row; 17 import org.h2.table.Table; 18 import org.h2.value.DataType; 19 import org.h2.value.Value; 20 21 24 25 public class TriggerObject extends SchemaObject { 26 27 public static final int INSERT=1, UPDATE=2, DELETE=4; 28 public static final int DEFAULT_QUEUE_SIZE = 1024; 29 30 private boolean before; 31 private int typeMask; 32 private boolean rowBased; 33 private int queueSize = DEFAULT_QUEUE_SIZE; 35 private boolean noWait; 36 private Table table; 37 private String triggerClassName; 38 private Trigger triggerCallback; 39 40 public TriggerObject(Schema schema, int id, String name, Table table) { 41 super(schema, id, name, Trace.TRIGGER); 42 this.table = table; 43 setTemporary(table.getTemporary()); 44 } 45 46 public void setBefore(boolean before) { 47 this.before = before; 48 } 49 50 public void setTriggerClassName(Session session, String triggerClassName) throws SQLException { 51 this.triggerClassName = triggerClassName; 52 try { 53 Connection c2 = session.createConnection(false); 54 Object obj = session.getDatabase().loadClass(triggerClassName).newInstance(); 55 triggerCallback = (Trigger)obj; 56 triggerCallback.init(c2, getSchema().getName(), getName(), table.getName()); 57 } catch(Throwable e) { 58 throw Message.getSQLException(Message.ERROR_CREATING_TRIGGER_OBJECT_2, new String []{getName(), triggerClassName}, e); 59 } 60 } 61 62 public void fire(Session session, boolean beforeAction) throws SQLException { 63 if(rowBased || before != beforeAction) { 64 return; 65 } 66 Connection c2 = session.createConnection(false); 67 try { 68 triggerCallback.fire(c2, null, null); 69 } catch(Throwable e) { 70 throw Message.getSQLException(Message.ERROR_EXECUTING_TRIGGER_2, new String []{getName(), triggerClassName}, e); 71 } 72 } 73 74 private Object [] convertToObjectList(Row row) throws SQLException { 75 if(row == null) { 76 return null; 77 } 78 int len = row.getColumnCount(); 79 Object [] list = new Object [len]; 80 for(int i=0; i<len; i++) { 81 list[i] = row.getValue(i).getObject(); 82 } 83 return list; 84 } 85 86 public void fireRow(Session session, Row oldRow, Row newRow, boolean beforeAction) throws SQLException { 87 if(!rowBased || before != beforeAction) { 88 return; 89 } 90 Object [] oldList; 91 Object [] newList; 92 boolean fire = false; 93 if((typeMask & INSERT) != 0) { 94 if(oldRow == null && newRow != null) { 95 fire = true; 96 } 97 } 98 if((typeMask & UPDATE) != 0) { 99 if(oldRow != null && newRow != null) { 100 fire = true; 101 } 102 } 103 if((typeMask & DELETE) != 0) { 104 if(oldRow != null && newRow == null) { 105 fire = true; 106 } 107 } 108 if(!fire) { 109 return; 110 } 111 oldList = convertToObjectList(oldRow); 112 newList = convertToObjectList(newRow); 113 Object [] newListBackup; 114 if(before && newList != null) { 115 newListBackup = new Object [newList.length]; 116 for(int i=0; i<newList.length; i++) { 117 newListBackup[i] = newList[i]; 118 } 119 } else { 120 newListBackup = null; 121 } 122 Connection c2 = session.createConnection(false); 123 boolean old = session.getAutoCommit(); 124 try { 125 session.setAutoCommit(false); 126 triggerCallback.fire(c2, oldList, newList); 127 if(newListBackup != null) { 128 for(int i=0; i<newList.length; i++) { 129 Object o = newList[i]; 130 if(o != newListBackup[i]) { 131 Value v = DataType.convertToValue(session, o, Value.UNKNOWN); 132 newRow.setValue(i, v); 133 } 134 } 135 } 136 } finally { 137 session.setAutoCommit(old); 138 } 139 } 140 141 public void setTypeMask(int typeMask) { 142 this.typeMask = typeMask; 143 } 144 145 public void setRowBased(boolean rowBased) { 146 this.rowBased = rowBased; 147 } 148 149 public void setQueueSize(int size) { 150 this.queueSize = size; 151 } 152 153 public int getQueueSize() { 154 return queueSize; 155 } 156 157 public void setNoWait(boolean noWait) { 158 this.noWait = noWait; 159 } 160 161 public boolean getNoWait() { 162 return noWait; 163 } 164 165 public String getCreateSQLForCopy(Table table, String quotedName) { 166 StringBuffer buff = new StringBuffer (); 167 buff.append("CREATE TRIGGER "); 168 buff.append(quotedName); 169 if(before) { 170 buff.append(" BEFORE "); 171 } else { 172 buff.append(" AFTER "); 173 } 174 buff.append(getTypeNameList()); 175 buff.append(" ON "); 176 buff.append(table.getSQL()); 177 if(rowBased) { 178 buff.append(" FOR EACH ROW"); 179 } 180 if(noWait) { 181 buff.append(" NOWAIT"); 182 } else { 183 buff.append(" QUEUE "); 184 buff.append(queueSize); 185 } 186 buff.append(" CALL "); 187 buff.append(Parser.quoteIdentifier(triggerClassName)); 188 return buff.toString(); 189 } 190 191 public String getTypeNameList() { 192 StringBuffer buff = new StringBuffer (); 193 if((typeMask & INSERT) != 0) { 194 buff.append("INSERT"); 195 } 196 if((typeMask & UPDATE) != 0) { 197 if(buff.length()>0) { 198 buff.append(", "); 199 } 200 buff.append("UPDATE"); 201 } 202 if((typeMask & DELETE) != 0) { 203 if(buff.length()>0) { 204 buff.append(", "); 205 } 206 buff.append("DELETE"); 207 } 208 return buff.toString(); 209 } 210 211 public String getCreateSQL() { 212 return getCreateSQLForCopy(table, getSQL()); 213 } 214 215 public int getType() { 216 return DbObject.TRIGGER; 217 } 218 219 public void removeChildrenAndResources(Session session) { 220 table.removeTrigger(session, this); 221 table = null; 222 triggerClassName = null; 223 triggerCallback = null; 224 invalidate(); 225 } 226 227 public void checkRename() { 228 } 230 231 public Table getTable() { 232 return table; 233 } 234 235 public boolean getBefore() { 236 return before; 237 } 238 239 public String getTriggerClassName() { 240 return triggerClassName; 241 } 242 243 } 244 | Popular Tags |