001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2002-2004 French National Institute For Research In Computer
004: * Science And Control (INRIA).
005: * Copyright (C) 2005-2006 Continuent, Inc.
006: * Contact: sequoia@continuent.org
007: *
008: * Licensed under the Apache License, Version 2.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: * Initial developer(s): Nicolas Modrzyk.
021: * Contributor(s): ______________________.
022: */package org.continuent.sequoia.controller.requests;
023:
024: import java.sql.SQLException;
025: import java.util.ArrayList;
026: import java.util.TreeSet;
027:
028: import org.continuent.sequoia.common.i18n.Translate;
029: import org.continuent.sequoia.common.sql.schema.DatabaseColumn;
030: import org.continuent.sequoia.common.sql.schema.DatabaseSchema;
031: import org.continuent.sequoia.common.sql.schema.DatabaseTable;
032: import org.continuent.sequoia.common.sql.schema.TableColumn;
033:
034: /**
035: * This class defines a AlterRequest
036: *
037: * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
038: * @version 1.0
039: */
040: public class AlterRequest extends AbstractWriteRequest {
041: private static final long serialVersionUID = 8386732943389593826L;
042:
043: /** The table to alter. */
044: protected transient DatabaseTable table = null;
045:
046: /** The column altered */
047: protected transient DatabaseColumn column = null;
048:
049: protected transient boolean isDrop = false;
050: protected transient boolean isAdd = false;
051:
052: // Be conservative, if we cannot parse the query, assumes it invalidates
053: // everything
054: protected boolean altersAggregateList = true;
055: protected boolean altersDatabaseCatalog = true;
056: protected boolean altersDatabaseSchema = true;
057: protected boolean altersMetadataCache = true;
058: protected boolean altersQueryResultCache = true;
059: protected boolean altersSomething = true;
060: protected boolean altersStoredProcedureList = true;
061: protected boolean altersUserDefinedTypes = true;
062: protected boolean altersUsers = true;
063:
064: /**
065: * Creates a new <code>AlterRequest</code> instance. The caller must give an
066: * SQL request, without any leading or trailing spaces and beginning with
067: * 'alter table '
068: * <p>
069: * The request is not parsed but it can be done later by a call to
070: * {@link #parse(DatabaseSchema, int, boolean)}.
071: *
072: * @param sqlQuery the SQL request
073: * @param escapeProcessing should the driver to escape processing before
074: * sending to the database ?
075: * @param timeout an <code>int</code> value
076: * @param lineSeparator the line separator used in the query
077: * @see #parse
078: */
079: public AlterRequest(String sqlQuery, boolean escapeProcessing,
080: int timeout, String lineSeparator) {
081: super (sqlQuery, escapeProcessing, timeout, lineSeparator,
082: RequestType.ALTER);
083: setMacrosAreProcessed(true); // no macro processing needed
084: }
085:
086: /**
087: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersAggregateList()
088: */
089: public boolean altersAggregateList() {
090: return altersAggregateList;
091: }
092:
093: /**
094: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersDatabaseCatalog()
095: */
096: public boolean altersDatabaseCatalog() {
097: return altersDatabaseCatalog;
098: }
099:
100: /**
101: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersDatabaseSchema()
102: */
103: public boolean altersDatabaseSchema() {
104: return altersDatabaseSchema;
105: }
106:
107: /**
108: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersMetadataCache()
109: */
110: public boolean altersMetadataCache() {
111: return altersMetadataCache;
112: }
113:
114: /**
115: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersQueryResultCache()
116: */
117: public boolean altersQueryResultCache() {
118: return altersQueryResultCache;
119: }
120:
121: /**
122: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersSomething()
123: */
124: public boolean altersSomething() {
125: return altersSomething;
126: }
127:
128: /**
129: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersStoredProcedureList()
130: */
131: public boolean altersStoredProcedureList() {
132: return altersStoredProcedureList;
133: }
134:
135: /**
136: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersUserDefinedTypes()
137: */
138: public boolean altersUserDefinedTypes() {
139: return altersUserDefinedTypes;
140: }
141:
142: /**
143: * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersUsers()
144: */
145: public boolean altersUsers() {
146: return altersUsers;
147: }
148:
149: /**
150: * @see org.continuent.sequoia.controller.requests.AbstractRequest#cloneParsing(org.continuent.sequoia.controller.requests.AbstractRequest)
151: */
152: public void cloneParsing(AbstractRequest request) {
153: if (!request.isParsed())
154: return;
155: AlterRequest alterRequest = (AlterRequest) request;
156: cloneTableNameAndColumns((AbstractWriteRequest) request);
157: table = alterRequest.getDatabaseTable();
158: column = alterRequest.getColumn();
159: isParsed = true;
160: }
161:
162: /**
163: * Returns the column value.
164: *
165: * @return Returns the column.
166: */
167: public DatabaseColumn getColumn() {
168: return column;
169: }
170:
171: /**
172: * Returns the table value.
173: *
174: * @return Returns the table.
175: */
176: public DatabaseTable getDatabaseTable() {
177: return table;
178: }
179:
180: /**
181: * Returns the isAdd value.
182: *
183: * @return Returns the isAdd.
184: */
185: public boolean isAdd() {
186: return isAdd;
187: }
188:
189: /**
190: * @see org.continuent.sequoia.controller.requests.AbstractRequest#needsMacroProcessing()
191: */
192: public boolean needsMacroProcessing() {
193: return false;
194: }
195:
196: /**
197: * @see org.continuent.sequoia.controller.requests.AbstractRequest#parse(org.continuent.sequoia.common.sql.schema.DatabaseSchema,
198: * int, boolean)
199: */
200: public void parse(DatabaseSchema schema, int granularity,
201: boolean isCaseSensitive) throws SQLException {
202: /*
203: * Example Alter statement: ALTER TABLE table_name ADD column_name datatype
204: * ALTER TABLE table_name DROP COLUMN column_name
205: */
206:
207: if (granularity == ParsingGranularities.NO_PARSING) {
208: isParsed = true;
209: return;
210: }
211:
212: String originalSQL = this .trimCarriageReturnAndTabs();
213: String sql = originalSQL.toLowerCase();
214:
215: // Strip 'alter table '
216: int tableIdx = sql.indexOf("table");
217: if (tableIdx == -1)
218: throw new SQLException(
219: "Malformed Alter Request. Should start with [ALTER TABLE]");
220: sql = sql.substring(tableIdx + 5).trim();
221:
222: // Does the query contain a add?
223: int addIdx = sql.indexOf(" add ");
224:
225: // Does the query contain a drop?
226: int dropIdx = sql.indexOf(" drop ");
227:
228: if (addIdx != -1)
229: isAdd = true;
230: if (dropIdx != -1)
231: isDrop = true;
232:
233: if (!isAdd && !isDrop)
234: throw new SQLException(
235: "Malformed Alter Request. No drop or add condition");
236:
237: if (isCaseSensitive) // Reverse to the original case
238: sql = originalSQL.substring(originalSQL.length()
239: - sql.length());
240:
241: int index = (isAdd) ? addIdx : dropIdx;
242:
243: tableName = sql.substring(0, index).trim();
244: table = new DatabaseTable(tableName);
245: writeLockedTables = new TreeSet();
246: writeLockedTables.add(tableName);
247: addDependingTables(schema, writeLockedTables);
248:
249: if ((schema != null)
250: && (granularity > ParsingGranularities.TABLE)) {
251: int subsIndex = index + 6 + 2; // index +
252: // column.length()
253: // + space
254: if (isAdd)
255: subsIndex += 3;
256: else
257: // Drop
258: subsIndex += 4;
259:
260: columns = new ArrayList();
261: sql = sql.substring(subsIndex).trim();
262:
263: if (isAdd) {
264: int colIndex = sql.indexOf(' ');
265: String colName = sql.substring(0, colIndex);
266:
267: int uniqueIndex = sql.toLowerCase().indexOf("unique");
268: int primary = sql.toLowerCase().indexOf("primary");
269: if (uniqueIndex != -1 || primary != -1)
270: column = new DatabaseColumn(colName, true);
271: else
272: column = new DatabaseColumn(colName, false);
273: columns.add(new TableColumn(tableName, colName));
274: } else if (isDrop) {
275: String colName = sql.trim();
276: column = schema.getTable(tableName).getColumn(colName);
277: columns.add(new TableColumn(tableName, colName));
278: }
279: }
280: isParsed = true;
281: }
282:
283: /**
284: * Does this request returns a ResultSet?
285: *
286: * @return false
287: */
288: public boolean returnsResultSet() {
289: return false;
290: }
291:
292: /**
293: * @see org.continuent.sequoia.controller.requests.AbstractRequest#getParsingResultsAsString()
294: */
295: public String getParsingResultsAsString() {
296: StringBuffer sb = new StringBuffer(super
297: .getParsingResultsAsString());
298: sb.append(Translate.get("request.alter.table", table));
299: sb.append(Translate.get("request.alter.column", column));
300: sb.append(Translate.get("request.alter.is.drop", isDrop));
301: sb.append(Translate.get("request.alter.is.add", isAdd));
302: sb.append(Translate.get("request.alters", new String[] {
303: String.valueOf(altersAggregateList()),
304: String.valueOf(altersDatabaseCatalog()),
305: String.valueOf(altersDatabaseSchema()),
306: String.valueOf(altersMetadataCache()),
307: String.valueOf(altersQueryResultCache()),
308: String.valueOf(altersSomething()),
309: String.valueOf(altersStoredProcedureList()),
310: String.valueOf(altersUserDefinedTypes()),
311: String.valueOf(altersUsers()) }));
312:
313: return sb.toString();
314: }
315: }
|