001: /**
002: * com.mckoi.database.interpret.Delete 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 java.util.*;
026: import com.mckoi.database.*;
027:
028: /**
029: * Logic for the DELETE FROM SQL statement.
030: *
031: * @author Tobias Downer
032: */
033:
034: public class Delete extends Statement {
035:
036: /**
037: * The name the table that we are to delete from.
038: */
039: String table_name;
040:
041: /**
042: * If the delete statement has a 'where' clause, then this is set here. If
043: * it has no 'where' clause then we apply to the entire table.
044: */
045: SearchExpression where_condition;
046:
047: /**
048: * The limit of the number of rows that are updated by this statement. A
049: * limit of < 0 means there is no limit.
050: */
051: int limit = -1;
052:
053: // -----
054:
055: /**
056: * The DataTable we are deleting from .
057: */
058: private DataTable update_table;
059:
060: /**
061: * The TableName object of the table being created.
062: */
063: private TableName tname;
064:
065: /**
066: * Tables that are relationally linked to the table being inserted into, set
067: * after 'prepare'. This is used to determine the tables we need to read
068: * lock because we need to validate relational constraints on the tables.
069: */
070: private ArrayList relationally_linked_tables;
071:
072: /**
073: * The plan for the set of records we are deleting in this query.
074: */
075: private QueryPlanNode plan;
076:
077: // ---------- Implemented from Statement ----------
078:
079: public void prepare() throws DatabaseException {
080:
081: // Get variables from the model.
082: table_name = (String) cmd.getObject("table_name");
083: where_condition = (SearchExpression) cmd
084: .getObject("where_clause");
085: limit = cmd.getInt("limit");
086:
087: // ---
088:
089: // Resolve the TableName object.
090: tname = resolveTableName(table_name, database);
091: // Does the table exist?
092: if (!database.tableExists(tname)) {
093: throw new DatabaseException("Table '" + tname
094: + "' does not exist.");
095: }
096: // Get the table we are updating
097: update_table = database.getTable(tname);
098:
099: // Form a TableSelectExpression that represents the select on the table
100: TableSelectExpression select_expression = new TableSelectExpression();
101: // Create the FROM clause
102: select_expression.from_clause.addTable(table_name);
103: // Set the WHERE clause
104: select_expression.where_clause = where_condition;
105:
106: // Generate the TableExpressionFromSet hierarchy for the expression,
107: TableExpressionFromSet from_set = Planner.generateFromSet(
108: select_expression, database);
109: // Form the plan
110: plan = Planner.formQueryPlan(database, select_expression,
111: from_set, null);
112:
113: // Resolve all tables linked to this
114: TableName[] linked_tables = database
115: .queryTablesRelationallyLinkedTo(tname);
116: relationally_linked_tables = new ArrayList(linked_tables.length);
117: for (int i = 0; i < linked_tables.length; ++i) {
118: relationally_linked_tables.add(database
119: .getTable(linked_tables[i]));
120: }
121:
122: }
123:
124: public Table evaluate() throws DatabaseException {
125:
126: DatabaseQueryContext context = new DatabaseQueryContext(
127: database);
128:
129: // Check that this user has privs to delete from the table.
130: if (!database.getDatabase().canUserDeleteFromTableObject(
131: context, user, tname)) {
132: throw new UserAccessException(
133: "User not permitted to delete from table: "
134: + table_name);
135: }
136:
137: // Check the user has select permissions on the tables in the plan.
138: Select.checkUserSelectPermissions(context, user, plan);
139:
140: // Evaluates the delete statement...
141:
142: // Evaluate the plan to find the update set.
143: Table delete_set = plan.evaluate(context);
144:
145: // Delete from the data table.
146: int delete_count = update_table.delete(delete_set, limit);
147:
148: // Notify TriggerManager that we've just done an update.
149: if (delete_count > 0) {
150: database
151: .notifyTriggerEvent(new TriggerEvent(
152: TriggerEvent.DELETE, tname.toString(),
153: delete_count));
154: }
155:
156: // Return the number of columns we deleted.
157: return FunctionTable.resultTable(context, delete_count);
158:
159: }
160:
161: }
|