001: /**
002: * com.mckoi.database.interpret.CreateTrigger 14 Sep 2001
003: *
004: * Mckoi SQL Database ( http://www.mckoi.com/database )
005: * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * Version 2 as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License Version 2 for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * Version 2 along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: * Change Log:
021: *
022: *
023: */package com.mckoi.database.interpret;
024:
025: import com.mckoi.database.*;
026: import com.mckoi.util.IntegerVector;
027: import java.util.ArrayList;
028: import java.util.List;
029:
030: /**
031: * A parsed state container for the 'CREATE TRIGGER' statement.
032: *
033: * @author Tobias Downer
034: */
035:
036: public class CreateTrigger extends Statement {
037:
038: // ---------- Implemented from Statement ----------
039:
040: public void prepare() throws DatabaseException {
041: }
042:
043: public Table evaluate() throws DatabaseException {
044:
045: String trigger_name = (String) cmd.getObject("trigger_name");
046: String type = (String) cmd.getObject("type");
047: String table_name = (String) cmd.getObject("table_name");
048: List types = (List) cmd.getObject("trigger_types");
049:
050: DatabaseQueryContext context = new DatabaseQueryContext(
051: database);
052:
053: TableName tname = TableName.resolve(
054: database.getCurrentSchema(), table_name);
055:
056: if (type.equals("callback_trigger")) {
057: // Callback trigger - notifies the client when an event on a table
058: // occurs.
059: if (types.size() > 1) {
060: throw new DatabaseException(
061: "Multiple triggered types not allowed for callback triggers.");
062: }
063:
064: String trig_type = ((String) types.get(0)).toUpperCase();
065: int int_type;
066: if (trig_type.equals("INSERT")) {
067: int_type = TriggerEvent.INSERT;
068: } else if (trig_type.equals("DELETE")) {
069: int_type = TriggerEvent.DELETE;
070: } else if (trig_type.equals("UPDATE")) {
071: int_type = TriggerEvent.UPDATE;
072: } else {
073: throw new DatabaseException("Unknown trigger type: "
074: + trig_type);
075: }
076:
077: database.createTrigger(trigger_name, tname.toString(),
078: int_type);
079:
080: } else if (type.equals("procedure_trigger")) {
081:
082: // Get the procedure manager
083: ProcedureManager proc_manager = database
084: .getProcedureManager();
085:
086: String before_after = (String) cmd
087: .getObject("before_after");
088: String procedure_name = (String) cmd
089: .getObject("procedure_name");
090: Expression[] procedure_args = (Expression[]) cmd
091: .getObject("procedure_args");
092:
093: // Convert the trigger into a table name,
094: String schema_name = database.getCurrentSchema();
095: TableName t_name = TableName.resolve(schema_name,
096: trigger_name);
097: t_name = database.tryResolveCase(t_name);
098:
099: // Resolve the procedure name into a TableName object.
100: TableName t_p_name = TableName.resolve(schema_name,
101: procedure_name);
102: t_p_name = database.tryResolveCase(t_p_name);
103:
104: // Does the procedure exist in the system schema?
105: ProcedureName p_name = new ProcedureName(t_p_name);
106:
107: // Check the trigger name doesn't clash with any existing database object.
108: if (database.tableExists(t_name)) {
109: throw new DatabaseException(
110: "A database object with name '" + t_name
111: + "' already exists.");
112: }
113:
114: // Check the procedure exists.
115: if (!proc_manager.procedureExists(p_name)) {
116: throw new DatabaseException("Procedure '" + p_name
117: + "' could not be found.");
118: }
119:
120: // Resolve the listening type
121: int listen_type = 0;
122: if (before_after.equals("before")) {
123: listen_type |= TableModificationEvent.BEFORE;
124: } else if (before_after.equals("after")) {
125: listen_type |= TableModificationEvent.AFTER;
126: } else {
127: throw new RuntimeException("Unknown before/after type.");
128: }
129:
130: for (int i = 0; i < types.size(); ++i) {
131: String trig_type = (String) types.get(i);
132: if (trig_type.equals("insert")) {
133: listen_type |= TableModificationEvent.INSERT;
134: } else if (trig_type.equals("delete")) {
135: listen_type |= TableModificationEvent.DELETE;
136: } else if (trig_type.equals("update")) {
137: listen_type |= TableModificationEvent.UPDATE;
138: }
139: }
140:
141: // Resolve the procedure arguments,
142: TObject[] vals = new TObject[procedure_args.length];
143: for (int i = 0; i < procedure_args.length; ++i) {
144: vals[i] = procedure_args[i].evaluate(null, null,
145: context);
146: }
147:
148: // Create the trigger,
149: ConnectionTriggerManager manager = database
150: .getConnectionTriggerManager();
151: manager.createTableTrigger(t_name.getSchema(), t_name
152: .getName(), listen_type, tname, p_name.toString(),
153: vals);
154:
155: // The initial grants for a trigger is to give the user who created it
156: // full access.
157: database.getGrantManager().addGrant(
158: Privileges.PROCEDURE_ALL_PRIVS, GrantManager.TABLE,
159: t_name.toString(), user.getUserName(), true,
160: Database.INTERNAL_SECURE_USERNAME);
161:
162: } else {
163: throw new RuntimeException("Unknown trigger type.");
164: }
165:
166: // Return success
167: return FunctionTable.resultTable(context, 0);
168: }
169:
170: }
|