001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.WriteCursorConstantAction
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. 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: */
021:
022: package org.apache.derby.impl.sql.execute;
023:
024: import org.apache.derby.iapi.sql.execute.ExecutionContext;
025:
026: import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
027:
028: import org.apache.derby.iapi.services.io.ArrayUtil;
029: import org.apache.derby.iapi.services.io.Formatable;
030:
031: import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
032: import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;
033: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
034: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
035: import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
036: import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
037: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
038: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
039:
040: import org.apache.derby.iapi.sql.execute.ConstantAction;
041: import org.apache.derby.iapi.sql.execute.ExecRow;
042:
043: import org.apache.derby.iapi.sql.Activation;
044:
045: import org.apache.derby.iapi.error.StandardException;
046:
047: import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
048:
049: import org.apache.derby.iapi.services.sanity.SanityManager;
050:
051: import org.apache.derby.iapi.services.io.FormatableBitSet;
052:
053: import org.apache.derby.catalog.UUID;
054:
055: import java.io.ObjectOutput;
056: import java.io.ObjectInput;
057: import java.io.IOException;
058:
059: import java.util.Properties;
060:
061: /**
062: * This abstract class describes compiled constants that are passed into
063: * Delete, Insert, and Update ResultSets.
064: *
065: * @author Rick Hillegas
066: */
067:
068: abstract class WriteCursorConstantAction implements ConstantAction,
069: Formatable {
070:
071: /********************************************************
072: **
073: ** This class implements Formatable. But it is NOT used
074: ** across either major or minor releases. It is only
075: ** written persistently in stored prepared statements,
076: ** not in the replication stage. SO, IT IS OK TO CHANGE
077: ** ITS read/writeExternal.
078: **
079: ********************************************************/
080:
081: long conglomId;
082: StaticCompiledOpenConglomInfo heapSCOCI;
083: IndexRowGenerator[] irgs;
084: long[] indexCIDS;
085: StaticCompiledOpenConglomInfo[] indexSCOCIs;
086: String[] indexNames;
087: boolean deferred;
088: private Properties targetProperties;
089: UUID targetUUID;
090: int lockMode;
091: private FKInfo[] fkInfo;
092: private TriggerInfo triggerInfo;
093:
094: private ExecRow emptyHeapRow;
095: private FormatableBitSet baseRowReadList;
096: private int[] baseRowReadMap;
097: private int[] streamStorableHeapColIds;
098: boolean singleRowSource;
099:
100: // CONSTRUCTORS
101:
102: /**
103: * Public niladic constructor. Needed for Formatable interface to work.
104: *
105: */
106: public WriteCursorConstantAction() {
107: }
108:
109: /**
110: * Make the ConstantAction for a DELETE, INSERT, or UPDATE statement.
111: *
112: * @param conglomId Conglomerate ID of heap.
113: * @param heapSCOCI StaticCompiledOpenConglomInfo for heap.
114: * @param irgs Index descriptors
115: * @param indexCIDS Conglomerate IDs of indices
116: * @param indexSCOCIs StaticCompiledOpenConglomInfos for indexes.
117: * @param indexNames Names of indices on this table for error reporting.
118: * @param deferred True means process as a deferred update
119: * @param targetProperties Properties on the target table
120: * @param targetUUID UUID of target table
121: * @param lockMode The lock mode to use on the target table
122: * @param fkInfo Structure containing foreign key info, if any (may be null)
123: * @param triggerInfo Structure containing trigger info, if any (may be null)
124: * @param emptyHeapRow an empty heap row
125: * @param baseRowReadMap BaseRowReadMap[heapColId]->ReadRowColumnId. (0 based)
126: * @param streamStorableHeapColIds Null for non rep. (0 based)
127: * @param singleRowSource Whether or not source is a single row source
128: */
129: public WriteCursorConstantAction(long conglomId,
130: StaticCompiledOpenConglomInfo heapSCOCI,
131: IndexRowGenerator[] irgs, long[] indexCIDS,
132: StaticCompiledOpenConglomInfo[] indexSCOCIs,
133: String[] indexNames, boolean deferred,
134: Properties targetProperties, UUID targetUUID, int lockMode,
135: FKInfo[] fkInfo, TriggerInfo triggerInfo,
136: ExecRow emptyHeapRow, FormatableBitSet baseRowReadList,
137: int[] baseRowReadMap, int[] streamStorableHeapColIds,
138: boolean singleRowSource) {
139: this .conglomId = conglomId;
140: this .heapSCOCI = heapSCOCI;
141: this .irgs = irgs;
142: this .indexSCOCIs = indexSCOCIs;
143: this .indexCIDS = indexCIDS;
144: this .indexSCOCIs = indexSCOCIs;
145: this .deferred = deferred;
146: this .targetProperties = targetProperties;
147: this .targetUUID = targetUUID;
148: this .lockMode = lockMode;
149: this .emptyHeapRow = emptyHeapRow;
150: this .fkInfo = fkInfo;
151: this .triggerInfo = triggerInfo;
152: this .baseRowReadList = baseRowReadList;
153: this .baseRowReadMap = baseRowReadMap;
154: this .streamStorableHeapColIds = streamStorableHeapColIds;
155: this .singleRowSource = singleRowSource;
156: this .indexNames = indexNames;
157: if (SanityManager.DEBUG) {
158: if (fkInfo != null) {
159: SanityManager
160: .ASSERT(fkInfo.length != 0,
161: "fkinfo array has no elements, if there are no foreign keys, then pass in null");
162: }
163: }
164: }
165:
166: ///////////////////////////////////////////////////////////////////
167: //
168: // ACCESSORS
169: //
170: ///////////////////////////////////////////////////////////////////
171:
172: /**
173: * Gets the foreign key information for this constant action.
174: * A full list of foreign keys was compiled into this constant
175: * action. However, we prune this list at run time so that we
176: * enforce only the foreign keys that we absolutely must.
177: *
178: * What's going on here? Well, in certain contexts (REFRESH and
179: * when intially booting a Target), we don't have to enforce some
180: * foreign keys. We allow the ExecutionContext to rule on which
181: * foreign keys are relevant and which aren't.
182: *
183: * @param ec the ExecutionContext
184: *
185: * @return the list of foreign keys to enforce for this action
186: *
187: * @exception StandardException Thrown on failure
188: */
189: public FKInfo[] getFKInfo(ExecutionContext ec)
190: throws StandardException {
191: FKInfo[] siftedArray = (FKInfo[]) ec.siftForeignKeys(fkInfo);
192:
193: return siftedArray;
194: }
195:
196: /**
197: * Basically, the same as getFKInfo but for triggers.
198: *
199: * @return the triggers that should be fired
200: *
201: * @exception StandardException Thrown on failure
202: */
203: public TriggerInfo getTriggerInfo(ExecutionContext ec)
204: throws StandardException {
205: return (TriggerInfo) ec.siftTriggers(triggerInfo);
206: }
207:
208: ///////////////////////////////////////////////////////////////////
209: //
210: // INTERFACE METHODS
211: //
212: ///////////////////////////////////////////////////////////////////
213:
214: /**
215: * NOP routine. The work is done in InsertResultSet.
216: *
217: * @see ConstantAction#executeConstantAction
218: *
219: * @exception StandardException Thrown on failure
220: */
221: public final void executeConstantAction(Activation activation)
222: throws StandardException {
223: }
224:
225: // Formatable methods
226: /**
227: * Read this object from a stream of stored objects.
228: *
229: * @param in read this.
230: *
231: * @exception IOException thrown on error
232: * @exception ClassNotFoundException thrown on error
233: */
234: public void readExternal(ObjectInput in) throws IOException,
235: ClassNotFoundException {
236: conglomId = in.readLong();
237: heapSCOCI = (StaticCompiledOpenConglomInfo) in.readObject();
238: irgs = new IndexRowGenerator[ArrayUtil.readArrayLength(in)];
239: ArrayUtil.readArrayItems(in, irgs);
240:
241: indexCIDS = ArrayUtil.readLongArray(in);
242: indexSCOCIs = new StaticCompiledOpenConglomInfo[ArrayUtil
243: .readArrayLength(in)];
244: ArrayUtil.readArrayItems(in, indexSCOCIs);
245:
246: deferred = in.readBoolean();
247: targetProperties = (Properties) in.readObject();
248: targetUUID = (UUID) in.readObject();
249: lockMode = in.readInt();
250:
251: fkInfo = new FKInfo[ArrayUtil.readArrayLength(in)];
252: ArrayUtil.readArrayItems(in, fkInfo);
253:
254: triggerInfo = (TriggerInfo) in.readObject();
255:
256: baseRowReadList = (FormatableBitSet) in.readObject();
257: baseRowReadMap = ArrayUtil.readIntArray(in);
258: streamStorableHeapColIds = ArrayUtil.readIntArray(in);
259: singleRowSource = in.readBoolean();
260: indexNames = ArrayUtil.readStringArray(in);
261: }
262:
263: /**
264: * Write this object to a stream of stored objects.
265: *
266: * @param out write bytes here.
267: *
268: * @exception IOException thrown on error
269: */
270: public void writeExternal(ObjectOutput out) throws IOException {
271: out.writeLong(conglomId);
272: out.writeObject(heapSCOCI);
273: ArrayUtil.writeArray(out, irgs);
274: ArrayUtil.writeLongArray(out, indexCIDS);
275: ArrayUtil.writeArray(out, indexSCOCIs);
276: out.writeBoolean(deferred);
277: out.writeObject(targetProperties);
278: out.writeObject(targetUUID);
279: out.writeInt(lockMode);
280: ArrayUtil.writeArray(out, fkInfo);
281:
282: //
283: //Added for Xena.
284: out.writeObject(triggerInfo);
285:
286: //
287: //Moved from super class for Xena.
288: out.writeObject(baseRowReadList);
289:
290: //
291: //Added for Xena
292: ArrayUtil.writeIntArray(out, baseRowReadMap);
293: ArrayUtil.writeIntArray(out, streamStorableHeapColIds);
294:
295: //Added for Buffy
296: out.writeBoolean(singleRowSource);
297:
298: // Added for Mulan (Track Bug# 3322)
299: ArrayUtil.writeArray(out, indexNames);
300:
301: }
302:
303: // ACCESSORS
304:
305: /**
306: * Get the conglomerate id for the changed heap.
307: * @return the conglomerate id.
308: */
309: public long getConglomerateId() {
310: return conglomId;
311: }
312:
313: /**
314: * Get emptyHeapRow
315: *
316: * @param lcc The LanguageConnectionContext to use.
317: *
318: * @return an empty base table row for the table being updated.
319: *
320: * @exception StandardException on error
321: */
322: public ExecRow getEmptyHeapRow(LanguageConnectionContext lcc)
323: throws StandardException {
324: DataDictionary dd;
325: TableDescriptor td;
326:
327: if (emptyHeapRow == null) {
328:
329: dd = lcc.getDataDictionary();
330:
331: td = dd.getTableDescriptor(targetUUID);
332:
333: emptyHeapRow = td.getEmptyExecRow(lcc.getContextManager());
334: }
335:
336: return emptyHeapRow.getClone();
337: }
338:
339: /**
340: * Get the targetProperties from the constant action.
341: *
342: * @return The targetProperties
343: */
344: public Properties getTargetProperties() {
345: return targetProperties;
346: }
347:
348: /**
349: * The the value of the specified key, if it exists, from
350: * the targetProperties.
351: *
352: * @param key The key to search for
353: *
354: * @return The value for the specified key if it exists, otherwise null.
355: * (Return null if targetProperties is null.)
356: */
357: public String getProperty(String key) {
358: return (targetProperties == null) ? null : targetProperties
359: .getProperty(key);
360: }
361:
362: public FormatableBitSet getBaseRowReadList() {
363: return baseRowReadList;
364: }
365:
366: public int[] getBaseRowReadMap() {
367: return baseRowReadMap;
368: }
369:
370: public int[] getStreamStorableHeapColIds() {
371: return streamStorableHeapColIds;
372: }
373:
374: /**
375: * get the index name given the conglomerate id of the index.
376: *
377: * @param indexCID conglomerate ID of the index.
378: *
379: * @return index name of given index.
380: */
381: public String getIndexNameFromCID(long indexCID) {
382: int size = indexCIDS.length;
383:
384: if (indexNames == null) {
385: return null;
386: }
387:
388: for (int i = 0; i < size; i++) {
389: if (indexCIDS[i] == indexCID)
390: return indexNames[i];
391: }
392: return null;
393: }
394:
395: public String[] getIndexNames() {
396: return indexNames;
397: }
398: }
|