[Home] DMelt member access. Java source code: org.apache.derby.impl.sql.execute.DeferredConstraintsMemory
/*
Derby - Class org.apache.derby.impl.sql.execute.DeferredConstraintsMemory
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to you under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.derby.impl.sql.execute;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.derby.catalog.UUID;
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.services.io.FormatableBitSet;
import org.apache.derby.iapi.sql.Activation;
import org.apache.derby.iapi.sql.PreparedStatement;
import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
import org.apache.derby.iapi.sql.conn.SQLSessionContext;
import org.apache.derby.iapi.sql.conn.StatementContext;
import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
import org.apache.derby.iapi.sql.dictionary.DataDictionary;
import org.apache.derby.iapi.sql.dictionary.ForeignKeyConstraintDescriptor;
import org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor;
import org.apache.derby.iapi.sql.dictionary.ReferencedKeyConstraintDescriptor;
import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
import org.apache.derby.iapi.sql.execute.ExecRow;
import org.apache.derby.iapi.store.access.BackingStoreHashtable;
import org.apache.derby.iapi.store.access.ScanController;
import org.apache.derby.iapi.store.access.TransactionController;
import org.apache.derby.iapi.types.DataValueDescriptor;
import org.apache.derby.iapi.types.RowLocation;
import org.apache.derby.iapi.types.SQLRef;
import org.apache.derby.shared.common.reference.SQLState;
/**
* This class provides support for deferrable constraints. When the constraint
* mode is deferred, any violation of the constraint should not be flagged
* until the constraint mode is switched back to immediate, which may happen by
* explicitly setting the constraint mode to immediate, or implicitly at commit
* time. It may also happen implicitly when returning from a stored procedure
* if the constraint mode is immediate in the caller context.
*
* The approach taken in Derby to support deferred constraints is to make a note
* when the violation happens (at insert or update time), and then remember that
* violation until the mode switches back as described above. We note exactly
* which rows cause violations, so checking can happen as quickly as possible
* when we get there. The core mechanism used to remember the violations as well
* as the deferred checking is embodied in this class.
*
*/
final public class DeferredConstraintsMemory
{
/**
* Save the contents of an constraint supporting index row in a
* hash table (which may spill to disk) for later checking,
* typically on transaction commit, or upon request.
*
* @param lcc the language connection context
* @param deferredRowsHashTable
* client cached value
* @param constraintId the id of the unique or primary key constraint
* @param insertRow the duplicate row to be saved in the hash table
* for later checking
* @return the hash table (for caching by client to minimize lookups)
* @throws StandardException standard error policy
*/
public static BackingStoreHashtable rememberDuplicate(
final LanguageConnectionContext lcc,
BackingStoreHashtable deferredRowsHashTable,
UUID constraintId,
final DataValueDescriptor[] insertRow) throws StandardException {
// Don't copy the RowLocation, we don't need it:
final int keyLength = insertRow.length -1 ;
if (deferredRowsHashTable == null) {
// Use the backing hashtable for this index's deferred rows
// by checking the transaction's map of such backing hash
// tables (one per index conglomerate). Use it if it
// exists, else make a new one.
final HashMap hashTables =
lcc.getDeferredHashTables();
final ValidationInfo vi = hashTables.get(constraintId);
if (vi == null) {
deferredRowsHashTable =
makeDeferredHashTable(lcc.getTransactionExecute(), keyLength);
hashTables.put(
constraintId,
new UniquePkInfo(deferredRowsHashTable, constraintId));
} else {
deferredRowsHashTable = vi.infoRows;
}
}
DataValueDescriptor[] hashRowArray = new DataValueDescriptor[keyLength];
System.arraycopy(insertRow, 0, hashRowArray, 0, keyLength);
deferredRowsHashTable.putRow(true, hashRowArray, null);
return deferredRowsHashTable;
}
/**
* Save the row location of an offending row (one or more check constraints
* were violated) in a hash table (which may spill to disk) for later
* checking, typically on transaction commit, or upon request.
*
* The row locations are subject to invalidation, cf.
* {@code CheckInfo#setInvalidatedRowLocations}.
*
* @param basetableId the id of the target table
* @param schemaName the schema of the target table
* @param tableName the target table name
* @param deferredCheckViolations
* client cached value
* @param lcc the language connection context
* @param violatingCheckConstraints offending constraint(s)
* @param offendingRow the duplicate row to be saved in the hash table
* for later checking
* @param result OUT parameter: the allocated CheckInfo
* @return the hash table (for caching by client to minimize lookups)
* @throws StandardException standard error policy
*/
public static BackingStoreHashtable rememberCheckViolations(
final LanguageConnectionContext lcc,
UUID basetableId,
final String schemaName,
final String tableName,
BackingStoreHashtable deferredCheckViolations,
final List violatingCheckConstraints,
final RowLocation offendingRow,
CheckInfo[] result) throws StandardException {
if (violatingCheckConstraints.isEmpty()) {
return null;
}
if (deferredCheckViolations == null) {
// Use the backing hashtable for this base tables deferred rows
// by checking the transaction's map of such backing hash
// tables (one per base table conglomerate). Use it if it
// exists, else make a new one.
final HashMap hashTables =
lcc.getDeferredHashTables();
final CheckInfo vi = (CheckInfo) hashTables.get(basetableId);
if (vi == null) {
// size 1 below: the row location in the target table of the
// offending row
deferredCheckViolations =
makeDeferredHashTable(lcc.getTransactionExecute(), 1);
CheckInfo ci = new CheckInfo(deferredCheckViolations,
schemaName,
tableName,
violatingCheckConstraints);
hashTables.put(basetableId, ci);
result[0] = ci;
} else {
vi.addCulprits(violatingCheckConstraints);
deferredCheckViolations = vi.infoRows;
result[0] = vi;
}
}
final DataValueDescriptor[] hashRowArray = new DataValueDescriptor[1];
hashRowArray[0] = new SQLRef(offendingRow).cloneValue(true);
deferredCheckViolations.putRow(true, hashRowArray, null);
return deferredCheckViolations;
}
public static Enumeration