001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.InsertVTIResultSet
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.services.sanity.SanityManager;
025:
026: import org.apache.derby.iapi.error.StandardException;
027:
028: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
029:
030: import org.apache.derby.iapi.types.DataValueDescriptor;
031:
032: import org.apache.derby.iapi.sql.execute.CursorResultSet;
033: import org.apache.derby.iapi.sql.execute.ExecRow;
034: import org.apache.derby.iapi.sql.execute.NoPutResultSet;
035:
036: import org.apache.derby.iapi.sql.Activation;
037: import org.apache.derby.iapi.sql.ResultDescription;
038:
039: import org.apache.derby.vti.DeferModification;
040:
041: import java.sql.PreparedStatement;
042: import java.sql.ResultSet;
043:
044: import java.util.Properties;
045:
046: /**
047: * Insert the rows from the source into the specified
048: * base table. This will cause constraints to be checked
049: * and triggers to be executed based on the c's and t's
050: * compiled into the insert plan.
051: */
052: class InsertVTIResultSet extends DMLVTIResultSet {
053:
054: private PreparedStatement ps;
055: private VTIResultSet vtiRS;
056: private java.sql.ResultSet rs;
057:
058: private TemporaryRowHolderImpl rowHolder;
059:
060: /**
061: *
062: * @exception StandardException Thrown on error
063: */
064: public InsertVTIResultSet(NoPutResultSet source,
065: NoPutResultSet vtiRS, Activation activation)
066: throws StandardException {
067: super (source, activation);
068: this .vtiRS = (VTIResultSet) vtiRS;
069: }
070:
071: /**
072: @exception StandardException Standard Cloudscape error policy
073: */
074: protected void openCore() throws StandardException {
075: /* We must instantiate the VTI on each execution if any of the
076: * parameters contain a ?.
077: */
078: if (ps == null) {
079: ps = (PreparedStatement) vtiRS.getVTIConstructor().invoke(
080: activation);
081: }
082:
083: if (ps instanceof DeferModification) {
084: try {
085: ((DeferModification) ps).modificationNotify(
086: DeferModification.INSERT_STATEMENT,
087: constants.deferred);
088: } catch (Throwable t) {
089: throw StandardException.unexpectedUserException(t);
090: }
091: }
092:
093: ExecRow row = getNextRowCore(sourceResultSet);
094:
095: try {
096: rs = ps.executeQuery();
097: } catch (Throwable t) {
098: throw StandardException.unexpectedUserException(t);
099: }
100:
101: /* Get or re-use the row changer.
102: * NOTE: We need to set ourself as the top result set
103: * if this is not the 1st execution. (Done in constructor
104: * for 1st execution.)
105: */
106: if (!firstExecute) {
107: lcc.getStatementContext().setTopResultSet(this ,
108: subqueryTrackingArray);
109: }
110:
111: /* The source does not know whether or not we are doing a
112: * deferred mode insert. If we are, then we must clear the
113: * index scan info from the activation so that the row changer
114: * does not re-use that information (which won't be valid for
115: * a deferred mode insert).
116: */
117: if (constants.deferred) {
118: activation.clearIndexScanInfo();
119: }
120:
121: if (firstExecute && constants.deferred) {
122: Properties properties = new Properties();
123:
124: /*
125: ** If deferred we save a copy of the entire row.
126: */
127: rowHolder = new TemporaryRowHolderImpl(activation,
128: properties, resultDescription);
129: }
130:
131: while (row != null) {
132: /*
133: ** If we're doing a deferred insert, insert into the temporary
134: ** conglomerate. Otherwise, insert directly into the permanent
135: ** conglomerates using the rowChanger.
136: */
137: if (constants.deferred) {
138: rowHolder.insert(row);
139: } else {
140: insertIntoVTI(rs, row);
141: }
142:
143: rowCount++;
144:
145: // No need to do a next on a single row source
146: if (constants.singleRowSource) {
147: row = null;
148: } else {
149: row = getNextRowCore(sourceResultSet);
150: }
151: }
152:
153: /*
154: ** If it's a deferred insert, scan the temporary conglomerate and
155: ** insert the rows into the permanent conglomerates using rowChanger.
156: */
157: if (constants.deferred) {
158: CursorResultSet tempRS = rowHolder.getResultSet();
159: try {
160: tempRS.open();
161: while ((row = tempRS.getNextRow()) != null) {
162: insertIntoVTI(rs, row);
163: }
164: } finally {
165: sourceResultSet.clearCurrentRow();
166: tempRS.close();
167: }
168: }
169:
170: if (rowHolder != null) {
171: rowHolder.close();
172: // rowHolder kept across opens
173: }
174: } // end of normalInsertCore
175:
176: private void insertIntoVTI(ResultSet target, ExecRow row)
177: throws StandardException {
178: try {
179: target.moveToInsertRow();
180:
181: DataValueDescriptor[] rowArray = row.getRowArray();
182: for (int index = 0; index < rowArray.length; index++) {
183: DataValueDescriptor dvd = rowArray[index];
184:
185: try {
186: if (dvd.isNull())
187: target.updateNull(index + 1);
188: else
189: dvd.setInto(target, index + 1);
190: } catch (Throwable t) {
191: // backwards compatibility - 5.0 and before used
192: // updateObject always.
193: target.updateObject(index + 1, dvd.getObject());
194: }
195: }
196:
197: target.insertRow();
198: } catch (Throwable t) {
199: throw StandardException.unexpectedUserException(t);
200: }
201: }
202:
203: /**
204: * @see org.apache.derby.iapi.sql.ResultSet#cleanUp
205: *
206: * @exception StandardException Thrown on error
207: */
208: public void cleanUp() throws StandardException {
209: if (rowHolder != null) {
210: rowHolder.close();
211: }
212:
213: if (rs != null) {
214: try {
215: rs.close();
216: } catch (Throwable t) {
217: throw StandardException.unexpectedUserException(t);
218: }
219: rs = null;
220: }
221:
222: // Close the ps if it needs to be instantiated on each execution
223: if (!vtiRS.isReuseablePs() && ps != null) {
224: try {
225: ps.close();
226: ps = null;
227: } catch (Throwable t) {
228: throw StandardException.unexpectedUserException(t);
229: }
230: }
231: super .cleanUp();
232: } // end of cleanUp
233:
234: // Class implementation
235:
236: public void finish() throws StandardException {
237:
238: if ((ps != null) && !vtiRS.isReuseablePs()) {
239: try {
240: ps.close();
241: ps = null;
242: } catch (Throwable t) {
243: throw StandardException.unexpectedUserException(t);
244: }
245: }
246: super .finish();
247: } // end of finish
248: }
|