/* Copyright (c) 2001-2019, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb;

import org.hsqldb.ParserDQL.CompileContext;
import org.hsqldb.navigator.RowIterator;
import org.hsqldb.navigator.RowSetNavigator;
import org.hsqldb.navigator.RowSetNavigatorClient;
import org.hsqldb.navigator.RowSetNavigatorDataChange;
import org.hsqldb.navigator.RowSetNavigatorDataChangeMemory;
import org.hsqldb.persist.PersistentStore;
import org.hsqldb.result.Result;
import org.hsqldb.result.ResultConstants;
import org.hsqldb.trigger.Trigger;
import org.hsqldb.types.Type;

Implementation of Statement for INSERT statements.

Author:Fred Toussi (fredt@users dot sourceforge.net)
Version:2.5.0
Since:1.9.0
/** * Implementation of Statement for INSERT statements.<p> * * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 2.5.0 * @since 1.9.0 */
public class StatementInsert extends StatementDML { static final int isNone = 0; static final int isIgnore = 1; static final int isReplace = 2; static final int isUpdate = 3; int overrideUserValue = -1; int specialAction = isNone;
Instantiate this as an INSERT_VALUES statement.
/** * Instantiate this as an INSERT_VALUES statement. */
StatementInsert(Session session, Table targetTable, int[] insertColumnMap, Expression insertExpression, boolean[] insertCheckColumns, Expression[] updateExpressions, boolean[] updateCheckColumns, int[] updateColumnMap, Expression[] targets, int specialAction, CompileContext compileContext) { super(StatementTypes.INSERT, StatementTypes.X_SQL_DATA_CHANGE, session.getCurrentSchemaHsqlName()); this.targetTable = targetTable; this.baseTable = targetTable.isTriggerInsertable() ? targetTable : targetTable .getBaseTable(); this.insertColumnMap = insertColumnMap; this.insertCheckColumns = insertCheckColumns; this.insertExpression = insertExpression; this.updateCheckColumns = updateCheckColumns; this.updateExpressions = updateExpressions; this.updateColumnMap = updateColumnMap; this.targets = targets; this.specialAction = specialAction; setupChecks(); setDatabaseObjects(session, compileContext); checkAccessRights(session); isSimpleInsert = insertExpression != null && insertExpression.nodes.length == 1 && updatableTableCheck == null && specialAction == isNone; }
Instantiate this as an INSERT_SELECT statement.
/** * Instantiate this as an INSERT_SELECT statement. */
StatementInsert(Session session, Table targetTable, int[] insertColumnMap, boolean[] insertCheckColumns, QueryExpression queryExpression, Expression[] updateExpressions, boolean[] updateCheckColumns, int[] updateColumnMap, Expression[] targets, int specialAction, int override, CompileContext compileContext) { super(StatementTypes.INSERT, StatementTypes.X_SQL_DATA_CHANGE, session.getCurrentSchemaHsqlName()); this.targetTable = targetTable; this.baseTable = targetTable.isTriggerInsertable() ? targetTable : targetTable .getBaseTable(); this.insertColumnMap = insertColumnMap; this.insertCheckColumns = insertCheckColumns; this.queryExpression = queryExpression; this.overrideUserValue = override; this.updateCheckColumns = updateCheckColumns; this.updateExpressions = updateExpressions; this.updateColumnMap = updateColumnMap; this.targets = targets; this.specialAction = specialAction; setupChecks(); setDatabaseObjects(session, compileContext); checkAccessRights(session); }
Executes an INSERT_SELECT or INSERT_VALUES statement. It is assumed that the argument is of the correct type.
Returns:the result of executing the statement
/** * Executes an INSERT_SELECT or INSERT_VALUES statement. It is assumed that * the argument is of the correct type. * * @return the result of executing the statement */
Result getResult(Session session) { Result resultOut = null; RowSetNavigator generatedNavigator = null; PersistentStore store = baseTable.getRowStore(session); int count = 0; if (generatedIndexes != null) { resultOut = Result.newUpdateCountResult(generatedResultMetaData, 0); generatedNavigator = resultOut.getChainedResult().getNavigator(); } if (isSimpleInsert) { Type[] colTypes = baseTable.getColumnTypes(); Object[] data = getInsertData(session, colTypes, insertExpression.nodes[0].nodes); return insertSingleRow(session, store, data); } RowSetNavigator newDataNavigator = queryExpression == null ? getInsertValuesNavigator(session) : getInsertSelectNavigator(session); RowSetNavigatorDataChange changeNavigator = null; if (specialAction != StatementInsert.isNone) { while (newDataNavigator.next()) { boolean remove = false; Object[] data = newDataNavigator.getCurrent(); for (int i = 0, size = baseTable.constraintList.length; i < size; i++) { Constraint constraint = baseTable.constraintList[i]; if (constraint.isUniqueOrPK()) { RowIterator it = constraint.findUniqueRows(session, data); while (it.next()) { remove = true; if (specialAction == StatementInsert.isIgnore) { break; } if (changeNavigator == null) { changeNavigator = new RowSetNavigatorDataChangeMemory( session); } Row row = it.getCurrentRow(); if (constraint.core.mainIndex.compareRowNonUnique( session, row.getData(), data, constraint.core.mainCols) != 0) { break; } changeNavigator.addRow(session, row, data, baseTable.getColumnTypes(), baseTable.defaultColumnMap); count++; } it.release(); } } if (remove) { newDataNavigator.removeCurrent(); } } } if (specialAction == StatementInsert.isReplace && changeNavigator != null) { count = update(session, baseTable, changeNavigator, null); changeNavigator.endMainDataSet(); } else if (specialAction == StatementInsert.isUpdate && changeNavigator != null) { Type[] colTypes = baseTable.getColumnTypes(); session.sessionContext.setRangeIterator( changeNavigator.getUpdateRowIterator()); while (changeNavigator.next()) { session.sessionData.startRowProcessing(); Row row = changeNavigator.getCurrentRow(); Object[] newData = row.getDataCopy(); getUpdatedData(session, targets, baseTable, updateColumnMap, updateExpressions, colTypes, newData); changeNavigator.addUpdate(row, newData, updateColumnMap); session.sessionContext.rownum++; } count = update(session, baseTable, changeNavigator, null); changeNavigator.endMainDataSet(); } if (newDataNavigator.getSize() != 0) { insertRowSet(session, generatedNavigator, newDataNavigator); count += newDataNavigator.getSize(); } if (baseTable.triggerLists[Trigger.INSERT_AFTER].length > 0) { baseTable.fireTriggers(session, Trigger.INSERT_AFTER, newDataNavigator); } if (resultOut == null) { resultOut = new Result(ResultConstants.UPDATECOUNT, count); } else { resultOut.setUpdateCount(count); } if (count == 0) { session.addWarning(HsqlException.noDataCondition); } session.sessionContext .diagnosticsVariables[ExpressionColumn.idx_row_count] = Integer.valueOf(count); return resultOut; } RowSetNavigator getInsertSelectNavigator(Session session) { Type[] colTypes = baseTable.getColumnTypes(); int[] columnMap = insertColumnMap; // Result result = queryExpression.getResult(session, 0); RowSetNavigator nav = result.initialiseNavigator(); Type[] sourceTypes = result.metaData.columnTypes; RowSetNavigatorClient newData = new RowSetNavigatorClient(nav.getSize()); while (nav.next()) { Object[] data = baseTable.getNewRowData(session); Object[] sourceData = nav.getCurrent(); for (int i = 0; i < columnMap.length; i++) { int j = columnMap[i]; if (j == this.overrideUserValue) { continue; } Type sourceType = sourceTypes[i]; data[j] = colTypes[j].convertToType(session, sourceData[i], sourceType); } newData.add(data); } return newData; } RowSetNavigator getInsertValuesNavigator(Session session) { Type[] colTypes = baseTable.getColumnTypes(); // Expression[] list = insertExpression.nodes; RowSetNavigatorClient newData = new RowSetNavigatorClient(list.length); for (int j = 0; j < list.length; j++) { Expression[] rowArgs = list[j].nodes; Object[] data = getInsertData(session, colTypes, rowArgs); newData.add(data); } return newData; } }