--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.execute.InsertVTIResultSet\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql.execute;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+\r
+import org.apache.derby.iapi.sql.execute.CursorResultSet;\r
+import org.apache.derby.iapi.sql.execute.ExecRow;\r
+import org.apache.derby.iapi.sql.execute.NoPutResultSet;\r
+\r
+import org.apache.derby.iapi.sql.Activation;\r
+import org.apache.derby.iapi.sql.ResultDescription;\r
+\r
+import org.apache.derby.vti.DeferModification;\r
+\r
+import java.sql.PreparedStatement;\r
+import java.sql.ResultSet;\r
+\r
+import java.util.Properties;\r
+\r
+/**\r
+ * Insert the rows from the source into the specified\r
+ * base table. This will cause constraints to be checked\r
+ * and triggers to be executed based on the c's and t's\r
+ * compiled into the insert plan.\r
+ */\r
+class InsertVTIResultSet extends DMLVTIResultSet\r
+{\r
+\r
+ private PreparedStatement ps;\r
+ private VTIResultSet vtiRS;\r
+ private java.sql.ResultSet rs;\r
+\r
+ private TemporaryRowHolderImpl rowHolder;\r
+\r
+ /**\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public InsertVTIResultSet(NoPutResultSet source, \r
+ NoPutResultSet vtiRS,\r
+ Activation activation)\r
+ throws StandardException\r
+ {\r
+ super(source, activation);\r
+ this.vtiRS = (VTIResultSet) vtiRS;\r
+ }\r
+ \r
+ /**\r
+ @exception StandardException Standard Derby error policy\r
+ */\r
+ protected void openCore() throws StandardException\r
+ {\r
+ /* We must instantiate the VTI on each execution if any of the\r
+ * parameters contain a ?.\r
+ */\r
+ if (ps == null) \r
+ {\r
+ ps = (PreparedStatement) vtiRS.getVTIConstructor().invoke(activation);\r
+ }\r
+\r
+ if( ps instanceof DeferModification)\r
+ {\r
+ try\r
+ {\r
+ ((DeferModification) ps).modificationNotify( DeferModification.INSERT_STATEMENT, constants.deferred);\r
+ }\r
+ catch (Throwable t)\r
+ {\r
+ throw StandardException.unexpectedUserException(t);\r
+ }\r
+ }\r
+\r
+ ExecRow row = getNextRowCore(sourceResultSet);\r
+\r
+ try\r
+ {\r
+ rs = ps.executeQuery();\r
+ }\r
+ catch (Throwable t)\r
+ {\r
+ throw StandardException.unexpectedUserException(t);\r
+ }\r
+\r
+ /* Get or re-use the row changer.\r
+ * NOTE: We need to set ourself as the top result set\r
+ * if this is not the 1st execution. (Done in constructor\r
+ * for 1st execution.)\r
+ */\r
+ if (! firstExecute)\r
+ {\r
+ lcc.getStatementContext().setTopResultSet(this, subqueryTrackingArray);\r
+ }\r
+\r
+ /* The source does not know whether or not we are doing a\r
+ * deferred mode insert. If we are, then we must clear the\r
+ * index scan info from the activation so that the row changer\r
+ * does not re-use that information (which won't be valid for\r
+ * a deferred mode insert).\r
+ */\r
+ if (constants.deferred)\r
+ {\r
+ activation.clearIndexScanInfo();\r
+ }\r
+\r
+ if (firstExecute && constants.deferred)\r
+ {\r
+ Properties properties = new Properties();\r
+\r
+ /*\r
+ ** If deferred we save a copy of the entire row.\r
+ */\r
+ rowHolder =\r
+ new TemporaryRowHolderImpl(activation, properties,\r
+ resultDescription);\r
+ }\r
+\r
+ while ( row != null )\r
+ {\r
+ /*\r
+ ** If we're doing a deferred insert, insert into the temporary\r
+ ** conglomerate. Otherwise, insert directly into the permanent\r
+ ** conglomerates using the rowChanger.\r
+ */\r
+ if (constants.deferred)\r
+ {\r
+ rowHolder.insert(row);\r
+ }\r
+ else\r
+ {\r
+ insertIntoVTI(rs, row);\r
+ }\r
+\r
+ rowCount++;\r
+\r
+ // No need to do a next on a single row source\r
+ if (constants.singleRowSource)\r
+ {\r
+ row = null;\r
+ }\r
+ else\r
+ {\r
+ row = getNextRowCore(sourceResultSet);\r
+ }\r
+ }\r
+\r
+ /*\r
+ ** If it's a deferred insert, scan the temporary conglomerate and\r
+ ** insert the rows into the permanent conglomerates using rowChanger.\r
+ */\r
+ if (constants.deferred)\r
+ {\r
+ CursorResultSet tempRS = rowHolder.getResultSet();\r
+ try\r
+ {\r
+ tempRS.open();\r
+ while ((row = tempRS.getNextRow()) != null)\r
+ {\r
+ insertIntoVTI(rs, row);\r
+ }\r
+ } finally\r
+ {\r
+ sourceResultSet.clearCurrentRow();\r
+ tempRS.close();\r
+ }\r
+ }\r
+\r
+ if (rowHolder != null)\r
+ {\r
+ rowHolder.close();\r
+ // rowHolder kept across opens\r
+ }\r
+ } // end of normalInsertCore\r
+\r
+ private void insertIntoVTI(ResultSet target, ExecRow row)\r
+ throws StandardException\r
+ {\r
+ try\r
+ {\r
+ target.moveToInsertRow();\r
+\r
+ DataValueDescriptor[] rowArray = row.getRowArray();\r
+ for (int index = 0; index < rowArray.length; index++)\r
+ {\r
+ DataValueDescriptor dvd = rowArray[index];\r
+\r
+ try {\r
+ if (dvd.isNull())\r
+ target.updateNull(index + 1);\r
+ else\r
+ dvd.setInto(target, index + 1);\r
+ } catch (Throwable t) {\r
+ // backwards compatibility - 5.0 and before used\r
+ // updateObject always.\r
+ target.updateObject(index + 1, dvd.getObject());\r
+ }\r
+ }\r
+\r
+ target.insertRow();\r
+ }\r
+ catch (Throwable t)\r
+ {\r
+ throw StandardException.unexpectedUserException(t);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @see org.apache.derby.iapi.sql.ResultSet#cleanUp\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void cleanUp() throws StandardException\r
+ {\r
+ if (rowHolder != null)\r
+ {\r
+ rowHolder.close();\r
+ }\r
+\r
+ if (rs != null)\r
+ {\r
+ try\r
+ {\r
+ rs.close();\r
+ }\r
+ catch (Throwable t)\r
+ {\r
+ throw StandardException.unexpectedUserException(t);\r
+ }\r
+ rs = null;\r
+ }\r
+\r
+ // Close the ps if it needs to be instantiated on each execution\r
+ if (!vtiRS.isReuseablePs() && ps != null)\r
+ {\r
+ try\r
+ {\r
+ ps.close();\r
+ ps = null;\r
+ }\r
+ catch (Throwable t)\r
+ {\r
+ throw StandardException.unexpectedUserException(t);\r
+ }\r
+ }\r
+ super.cleanUp();\r
+ } // end of cleanUp\r
+\r
+ // Class implementation\r
+\r
+ public void finish() throws StandardException {\r
+\r
+ if ((ps != null) && !vtiRS.isReuseablePs())\r
+ {\r
+ try\r
+ {\r
+ ps.close();\r
+ ps = null;\r
+ }\r
+ catch (Throwable t)\r
+ {\r
+ throw StandardException.unexpectedUserException(t);\r
+ }\r
+ }\r
+ super.finish();\r
+ } // end of finish\r
+}\r
+\r