1 30 31 32 33 package org.hsqldb.sample; 35 36 import java.io.PrintWriter ; 37 import java.sql.Connection ; 38 import java.sql.DriverManager ; 39 import java.sql.PreparedStatement ; 40 import java.sql.ResultSet ; 41 import java.sql.ResultSetMetaData ; 42 import java.sql.SQLException ; 43 import java.sql.Statement ; 44 45 import org.hsqldb.Trace; 46 import org.hsqldb.Trigger; 47 import org.hsqldb.lib.StringUtil; 48 49 53 126 public class TriggerSample implements Trigger { 127 128 static final PrintWriter out = new PrintWriter (System.out); 129 static final String drv = "org.hsqldb.jdbcDriver"; 130 static final String url = "jdbc:hsqldb:mem:trigger-sample"; 131 static final String usr = "sa"; 132 static final String pwd = ""; 133 static final String impl = TriggerSample.class.getName(); 134 static final String tn = "trig_test"; 135 static final String drop_test_table_stmt = "DROP TABLE " + tn 136 + " IF EXISTS"; 137 static final String create_test_table_stmt = "CREATE TABLE " + tn 138 + "(id INTEGER PRIMARY KEY, value VARCHAR(20))"; 139 static final String drop_audit_table_stmt = "DROP TABLE audit IF EXISTS"; 140 static final String create_audit_table_stmt = "CREATE TABLE audit(" 141 + "id INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1), " 142 + "op VARCHAR(6), " + "tn VARCHAR, " + "ors LONGVARCHAR, " 143 + "nrs LONGVARCHAR, " + "ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"; 144 static final String audit_insert_stmt = 145 "INSERT INTO audit(op, tn, ors, nrs) VALUES(?, ?, ?, ?)"; 146 147 163 public void fire(int typ, String trn, String tn, Object [] or, 164 Object [] nr) { 165 166 synchronized (TriggerSample.class) { 167 String ors = or == null ? "null" 168 : StringUtil.arrayToString(or); 169 String nrs = nr == null ? "null" 170 : StringUtil.arrayToString(nr); 171 172 out.println("----------------------------------------"); 173 out.println(getTriggerDescriptor(trn, typ, tn)); 174 out.println("old row : " + ors); 175 out.println("new row : " + nrs); 176 out.flush(); 177 178 if ("TRIG_TEST".equals(tn)) { 179 switch (typ) { 180 181 case INSERT_BEFORE_ROW : { 182 183 final int ID = ((Number ) nr[0]).intValue(); 188 189 doAssert(ID < 11, "ID < 11"); 190 191 break; 192 } 193 case UPDATE_BEFORE_ROW : { 194 195 if ("unchangable".equals(or[1])) { 197 nr[1] = or[1]; } 199 200 break; 206 } 207 } 208 } 209 210 doAuditStep(typ, tn, ors, nrs); 211 } 212 } 213 214 private static void doAssert(boolean b, 215 String msg) throws RuntimeException { 216 217 if (b) { 218 219 } else { 221 msg = Trace.getMessage(Trace.ASSERT_FAILED) + ": " + msg; 222 223 throw new RuntimeException (msg); 224 } 225 } 226 227 private static void doAuditStep(int typ, String tn, String ors, 228 String nrs) { 229 230 Connection conn; 231 PreparedStatement stmt; 232 233 switch (typ) { 234 235 case INSERT_AFTER_ROW : 236 case UPDATE_AFTER_ROW : 237 case DELETE_AFTER_ROW : { 238 try { 239 conn = getConnection(); 240 stmt = conn.prepareStatement(audit_insert_stmt); 241 242 stmt.setString(1, getOperationSpec(typ)); 243 stmt.setString(2, tn); 244 stmt.setString(3, ors); 245 stmt.setString(4, nrs); 246 stmt.executeUpdate(); 247 conn.close(); 248 } catch (SQLException se) { 249 se.printStackTrace(); 250 } 251 } 252 } 253 } 254 255 public static String getWhenSpec(int type) { 256 257 switch (type) { 258 259 case INSERT_BEFORE : 260 case INSERT_BEFORE_ROW : 261 case UPDATE_BEFORE : 262 case UPDATE_BEFORE_ROW : 263 case DELETE_BEFORE : 264 case DELETE_BEFORE_ROW : { 265 return "BEFORE"; 266 } 267 case INSERT_AFTER : 268 case INSERT_AFTER_ROW : 269 case UPDATE_AFTER : 270 case UPDATE_AFTER_ROW : 271 case DELETE_AFTER : 272 case DELETE_AFTER_ROW : { 273 return "AFTER"; 274 } 275 default : { 276 return ""; 277 } 278 } 279 } 280 281 public static String getOperationSpec(int type) { 282 283 switch (type) { 284 285 case INSERT_AFTER : 286 case INSERT_AFTER_ROW : 287 case INSERT_BEFORE : 288 case INSERT_BEFORE_ROW : { 289 return "INSERT"; 290 } 291 case UPDATE_AFTER : 292 case UPDATE_AFTER_ROW : 293 case UPDATE_BEFORE : 294 case UPDATE_BEFORE_ROW : { 295 return "UPDATE"; 296 } 297 case DELETE_AFTER : 298 case DELETE_AFTER_ROW : 299 case DELETE_BEFORE : 300 case DELETE_BEFORE_ROW : { 301 return "DELETE"; 302 } 303 default : { 304 return ""; 305 } 306 } 307 } 308 309 public static String getQueueSpec(int qs) { 310 return (qs < 0) ? "" 311 : ("QUEUE " + qs); 312 } 313 314 public static String getForEachSpec(int type) { 315 316 switch (type) { 317 318 case INSERT_BEFORE_ROW : 319 case INSERT_AFTER_ROW : 320 case UPDATE_BEFORE_ROW : 321 case UPDATE_AFTER_ROW : 322 case DELETE_AFTER_ROW : 323 case DELETE_BEFORE_ROW : { 324 return "FOR EACH ROW"; 325 } 326 default : { 327 return ""; 328 } 329 } 330 } 331 332 public static String getTriggerDDL(String trn, int typ, String tab, 333 int qs, 334 String impl) throws SQLException { 335 336 StringBuffer sb = new StringBuffer (); 337 338 sb.append("CREATE TRIGGER "); 339 sb.append(trn); 340 sb.append(' '); 341 sb.append(getWhenSpec(typ)); 342 sb.append(' '); 343 sb.append(getOperationSpec(typ)); 344 sb.append(" ON "); 345 sb.append(tab); 346 sb.append(' '); 347 sb.append(getForEachSpec(typ)); 348 sb.append(' '); 349 sb.append(getQueueSpec(qs)); 350 sb.append(" CALL \""); 351 sb.append(impl); 352 sb.append("\""); 353 354 return sb.toString(); 355 } 356 357 public static String getTriggerDescriptor(String trn, int typ, 358 String tab) { 359 360 StringBuffer sb = new StringBuffer (); 361 362 sb.append("TRIGGER : "); 363 sb.append(trn); 364 sb.append(' '); 365 sb.append(getWhenSpec(typ)); 366 sb.append(' '); 367 sb.append(getOperationSpec(typ)); 368 sb.append(" ON "); 369 sb.append(tab); 370 sb.append(' '); 371 sb.append(getForEachSpec(typ)); 372 373 return sb.toString(); 374 } 375 376 private static Connection getConnection() throws SQLException { 377 378 try { 379 Class.forName(drv).newInstance(); 380 381 return DriverManager.getConnection(url, usr, pwd); 382 } catch (SQLException se) { 383 throw se; 384 } catch (Exception e) { 385 throw new SQLException (e.toString()); 386 } 387 } 388 389 private static void createTrigger(Statement stmt, String trn, 390 int typ) throws SQLException { 391 stmt.execute(getTriggerDDL(trn, typ, tn, 0, impl)); 392 } 393 394 private static void setup() throws SQLException { 395 396 Connection conn = getConnection(); 397 Statement stmt = conn.createStatement(); 398 399 stmt.execute(drop_test_table_stmt); 400 stmt.execute(create_test_table_stmt); 401 stmt.execute(drop_audit_table_stmt); 402 stmt.execute(create_audit_table_stmt); 403 createTrigger(stmt, "tib_" + tn, INSERT_BEFORE); 404 createTrigger(stmt, "tibr_" + tn, INSERT_BEFORE_ROW); 405 createTrigger(stmt, "tia_" + tn, INSERT_AFTER); 406 createTrigger(stmt, "tiar_" + tn, INSERT_AFTER_ROW); 407 createTrigger(stmt, "tub_" + tn, UPDATE_BEFORE); 408 createTrigger(stmt, "tubr_" + tn, UPDATE_BEFORE_ROW); 409 createTrigger(stmt, "tua_" + tn, UPDATE_AFTER); 410 createTrigger(stmt, "tuar_" + tn, UPDATE_AFTER_ROW); 411 createTrigger(stmt, "tdb_" + tn, DELETE_BEFORE); 412 createTrigger(stmt, "tdbr_" + tn, DELETE_BEFORE_ROW); 413 createTrigger(stmt, "tda_" + tn, DELETE_AFTER); 414 createTrigger(stmt, "tdar_" + tn, DELETE_AFTER_ROW); 415 stmt.close(); 416 conn.close(); 417 } 418 419 private static void doSomeWork() throws SQLException { 420 421 Connection conn = getConnection(); 422 Statement stmt = conn.createStatement(); 423 424 conn.setAutoCommit(false); 425 stmt.execute("INSERT INTO trig_test VALUES (1, 'hello')"); 426 stmt.execute("INSERT INTO trig_test VALUES (2, 'now what?')"); 427 stmt.execute("INSERT INTO trig_test VALUES (3, 'unchangable')"); 428 stmt.execute("INSERT INTO trig_test VALUES (4, 'goodbye')"); 429 conn.commit(); 430 dumpTable("trig_test"); 431 stmt.execute("UPDATE trig_test SET value = 'all done'"); 432 conn.commit(); 433 dumpTable("trig_test"); 434 stmt.execute("DELETE FROM trig_test"); 435 conn.rollback(); 436 dumpTable("trig_test"); 437 438 try { 439 stmt.execute("INSERT INTO trig_test VALUES(11, 'whatever')"); 440 } catch (SQLException se) { 441 se.printStackTrace(); 442 } 443 444 stmt.execute("INSERT INTO trig_test VALUES(10, 'whatever')"); 445 conn.commit(); 446 dumpTable("trig_test"); 447 stmt.close(); 448 conn.close(); 449 } 450 451 private static void dumpTable(String tn) throws SQLException { 452 453 Connection conn = getConnection(); 454 Statement stmt = conn.createStatement(); 455 ResultSet rs = stmt.executeQuery("select * from " + tn); 456 ResultSetMetaData rsmd = rs.getMetaData(); 457 int count = rsmd.getColumnCount(); 458 459 out.println(); 460 out.println("****************************************"); 461 out.println("DUMP FOR TABLE: " + tn); 462 out.println("****************************************"); 463 out.flush(); 464 465 while (rs.next()) { 466 out.print("["); 467 468 for (int i = 1; i <= count; i++) { 469 out.print(rs.getString(i)); 470 471 if (i < count) { 472 out.print(" : "); 473 } 474 } 475 476 out.println("]"); 477 } 478 479 out.println(); 480 out.flush(); 481 rs.close(); 482 stmt.close(); 483 conn.close(); 484 } 485 486 private static void runSample() throws SQLException { 487 488 setup(); 489 doSomeWork(); 490 dumpTable("audit"); 491 } 492 493 public static void main(String [] args) throws SQLException { 494 runSample(); 495 } 496 } 497 516 | Popular Tags |