001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.UpdateVTIResultSet
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 java.sql.PreparedStatement;
040: import java.sql.ResultSet;
041:
042: import java.util.Properties;
043:
044: /**
045: * Update the rows from the source into the specified
046: * base table.
047: */
048: class UpdateVTIResultSet extends DMLVTIResultSet {
049: private java.sql.ResultSet rs;
050:
051: private TemporaryRowHolderImpl rowHolder;
052:
053: /**
054: *
055: * @exception StandardException Thrown on error
056: */
057: public UpdateVTIResultSet(NoPutResultSet source,
058: Activation activation) throws StandardException {
059: super (source, activation);
060: }
061:
062: /**
063: @exception StandardException Standard Cloudscape error policy
064: */
065: protected void openCore() throws StandardException {
066: int rowLocationColumn = -1;
067: boolean firstRow = true;
068:
069: rs = activation.getTargetVTI();
070: ExecRow row = getNextRowCore(sourceResultSet);
071:
072: if (null != row)
073: rowLocationColumn = row.nColumns();
074: if (!firstExecute)
075: lcc.getStatementContext().setTopResultSet(this ,
076: subqueryTrackingArray);
077:
078: /* The source does not know whether or not we are doing a
079: * deferred mode insert. If we are, then we must clear the
080: * index scan info from the activation so that the row changer
081: * does not re-use that information (which won't be valid for
082: * a deferred mode insert).
083: */
084: if (constants.deferred) {
085: activation.clearIndexScanInfo();
086: }
087:
088: if (null == rowHolder && constants.deferred) {
089: Properties properties = new Properties();
090:
091: /*
092: ** If deferred we save a copy of the entire row.
093: */
094: rowHolder = new TemporaryRowHolderImpl(activation,
095: properties, resultDescription);
096: }
097:
098: try {
099: while (row != null) {
100: if (constants.deferred) {
101: // Add the row number to the row.
102: if (firstRow) {
103: row.getColumn(rowLocationColumn).setValue(
104: rs.getRow());
105: firstRow = false;
106: } else {
107: DataValueDescriptor rowLocation = row
108: .cloneColumn(rowLocationColumn);
109: rowLocation.setValue(rs.getRow());
110: row.setColumn(rowLocationColumn, rowLocation);
111: }
112: rowHolder.insert(row);
113: } else
114: updateVTI(rs, row);
115: rowCount++;
116:
117: // No need to do a next on a single row source
118: if (constants.singleRowSource) {
119: row = null;
120: } else {
121: row = getNextRowCore(sourceResultSet);
122: }
123: }
124: } catch (StandardException se) {
125: throw se;
126: } catch (Throwable t) {
127: throw StandardException.unexpectedUserException(t);
128: }
129:
130: /*
131: ** If it's a deferred update, scan the temporary conglomerate and
132: ** insert the rows into the VTI using rowChanger.
133: */
134: if (constants.deferred) {
135: CursorResultSet tempRS = rowHolder.getResultSet();
136: try {
137: tempRS.open();
138: while ((row = tempRS.getNextRow()) != null) {
139: int rowNumber = row.getColumn(rowLocationColumn)
140: .getInt();
141: rs.absolute(rowNumber);
142: updateVTI(rs, row);
143: }
144: } catch (Throwable t) {
145: throw StandardException.unexpectedUserException(t);
146: } finally {
147: sourceResultSet.clearCurrentRow();
148: tempRS.close();
149: }
150: }
151:
152: if (rowHolder != null) {
153: rowHolder.close();
154: // rowHolder kept across opens
155: }
156: } // end of openCore
157:
158: private void updateVTI(ResultSet target, ExecRow row)
159: throws StandardException {
160: int[] changedColumnIds = constants.changedColumnIds;
161: try {
162: for (int i = 0; i < changedColumnIds.length; i++) {
163: int columnId = changedColumnIds[i];
164: DataValueDescriptor newValue = row.getColumn(i + 1);
165: if (newValue.isNull())
166: target.updateNull(columnId);
167: else
168: newValue.setInto(target, columnId);
169: }
170: target.updateRow();
171: } catch (Throwable t) {
172: throw StandardException.unexpectedUserException(t);
173: }
174: } // end of updateVTI
175: }
|