use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class InsertResultSet method emptyIndexes.
/**
* Empty the indexes after doing a bulk insert replace
* where the table has 0 rows after the replace.
* RESOLVE: This method is ugly! Prior to 2.0, we simply
* scanned back across the table to build the indexes. We
* changed this in 2.0 to populate the sorters via a call back
* as we populated the table. Doing a 0 row replace into a
* table with indexes is a degenerate case, hence we allow
* ugly and unoptimized code.
*
* @exception StandardException Thrown on failure
*/
private void emptyIndexes(long newHeapConglom, InsertConstantAction constants, TableDescriptor td, DataDictionary dd, ExecRow fullTemplate) throws StandardException {
int numIndexes = constants.irgs.length;
ExecIndexRow[] idxRows = new ExecIndexRow[numIndexes];
ExecRow baseRows;
ColumnOrdering[][] order = new ColumnOrdering[numIndexes][];
int numColumns = td.getNumberOfColumns();
collation = new int[numIndexes][];
// Create the BitSet for mapping the partial row to the full row
FormatableBitSet bitSet = new FormatableBitSet(numColumns + 1);
// Need to check each index for referenced columns
int numReferencedColumns = 0;
for (int index = 0; index < numIndexes; index++) {
int[] baseColumnPositions = constants.irgs[index].baseColumnPositions();
for (int bcp = 0; bcp < baseColumnPositions.length; bcp++) {
if (!bitSet.get(baseColumnPositions[bcp])) {
bitSet.set(baseColumnPositions[bcp]);
numReferencedColumns++;
}
}
}
// We can finally create the partial base row
baseRows = activation.getExecutionFactory().getValueRow(numReferencedColumns);
// Fill in each base row with nulls of the correct data type
int colNumber = 0;
for (int index = 0; index < numColumns; index++) {
if (bitSet.get(index + 1)) {
colNumber++;
// NOTE: 1-based column numbers
baseRows.setColumn(colNumber, fullTemplate.getColumn(index + 1).cloneValue(false));
}
}
needToDropSort = new boolean[numIndexes];
sortIds = new long[numIndexes];
/* Do the initial set up before scanning the heap.
* For each index, build a single index row and a sorter.
*/
for (int index = 0; index < numIndexes; index++) {
// create a single index row template for each index
idxRows[index] = constants.irgs[index].getIndexRowTemplate();
// Get an index row based on the base row
// (This call is only necessary here because we need to pass a
// template to the sorter.)
constants.irgs[index].getIndexRow(baseRows, rl, idxRows[index], bitSet);
/* For non-unique indexes, we order by all columns + the RID.
* For unique indexes, we just order by the columns.
* We create a unique index observer for unique indexes
* so that we can catch duplicate key
*/
ConglomerateDescriptor cd;
// Get the ConglomerateDescriptor for the index
cd = td.getConglomerateDescriptor(constants.indexCIDS[index]);
int[] baseColumnPositions = constants.irgs[index].baseColumnPositions();
boolean[] isAscending = constants.irgs[index].isAscending();
int numColumnOrderings;
SortObserver sortObserver;
final IndexRowGenerator indDes = cd.getIndexDescriptor();
if (indDes.isUnique() || indDes.isUniqueDeferrable()) {
numColumnOrderings = indDes.isUnique() ? baseColumnPositions.length : baseColumnPositions.length + 1;
String indexOrConstraintName = cd.getConglomerateName();
boolean deferred = false;
boolean uniqueDeferrable = false;
UUID uniqueDeferrableConstraintId = null;
if (cd.isConstraint()) {
// so, the index is backing up a constraint
ConstraintDescriptor conDesc = dd.getConstraintDescriptor(td, cd.getUUID());
indexOrConstraintName = conDesc.getConstraintName();
deferred = lcc.isEffectivelyDeferred(lcc.getCurrentSQLSessionContext(activation), conDesc.getUUID());
uniqueDeferrable = conDesc.deferrable();
uniqueDeferrableConstraintId = conDesc.getUUID();
}
sortObserver = new UniqueIndexSortObserver(lcc, uniqueDeferrableConstraintId, // don't clone rows
false, uniqueDeferrable, deferred, indexOrConstraintName, idxRows[index], true, td.getName());
} else {
numColumnOrderings = baseColumnPositions.length + 1;
sortObserver = new BasicSortObserver(false, false, idxRows[index], true);
}
order[index] = new ColumnOrdering[numColumnOrderings];
for (int ii = 0; ii < isAscending.length; ii++) {
order[index][ii] = new IndexColumnOrder(ii, isAscending[ii]);
}
if (numColumnOrderings > isAscending.length) {
order[index][isAscending.length] = new IndexColumnOrder(isAscending.length);
}
// create the sorters
sortIds[index] = tc.createSort((Properties) null, idxRows[index].getRowArrayClone(), order[index], sortObserver, // not in order
false, // est rows
rowCount, // est row size, -1 means no idea
-1);
needToDropSort[index] = true;
}
// Populate sorters and get the output of each sorter into a row
// source. The sorters have the indexed columns only and the columns
// are in the correct order.
rowSources = new RowLocationRetRowSource[numIndexes];
// Fill in the RowSources
SortController[] sorter = new SortController[numIndexes];
for (int index = 0; index < numIndexes; index++) {
sorter[index] = tc.openSort(sortIds[index]);
sorter[index].completedInserts();
rowSources[index] = tc.openSortRowSource(sortIds[index]);
}
long[] newIndexCongloms = new long[numIndexes];
// Populate each index
for (int index = 0; index < numIndexes; index++) {
ConglomerateController indexCC;
Properties properties = new Properties();
ConglomerateDescriptor cd;
// Get the ConglomerateDescriptor for the index
cd = td.getConglomerateDescriptor(constants.indexCIDS[index]);
// Build the properties list for the new conglomerate
indexCC = tc.openCompiledConglomerate(false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE, constants.indexSCOCIs[index], indexDCOCIs[index]);
// Get the properties on the old index
indexCC.getInternalTablePropertySet(properties);
/* Create the properties that language supplies when creating the
* the index. (The store doesn't preserve these.)
*/
int indexRowLength = idxRows[index].nColumns();
properties.put("baseConglomerateId", Long.toString(newHeapConglom));
if (cd.getIndexDescriptor().isUnique()) {
properties.put("nUniqueColumns", Integer.toString(indexRowLength - 1));
} else {
properties.put("nUniqueColumns", Integer.toString(indexRowLength));
}
if (cd.getIndexDescriptor().isUniqueWithDuplicateNulls() && !cd.getIndexDescriptor().hasDeferrableChecking()) {
properties.put("uniqueWithDuplicateNulls", Boolean.toString(true));
}
properties.put("rowLocationColumn", Integer.toString(indexRowLength - 1));
properties.put("nKeyFields", Integer.toString(indexRowLength));
indexCC.close();
collation[index] = constants.irgs[index].getColumnCollationIds(td.getColumnDescriptorList());
// We can finally drain the sorter and rebuild the index
// Populate the index.
newIndexCongloms[index] = tc.createAndLoadConglomerate("BTREE", idxRows[index].getRowArray(), // default column sort order
null, collation[index], properties, TransactionController.IS_DEFAULT, rowSources[index], (long[]) null);
/* Update the DataDictionary
*
* Update sys.sysconglomerates with new conglomerate #, if the
* conglomerate is shared by duplicate indexes, all the descriptors
* for those indexes need to be updated with the new number.
*/
dd.updateConglomerateDescriptor(td.getConglomerateDescriptors(constants.indexCIDS[index]), newIndexCongloms[index], tc);
// Drop the old conglomerate
tc.dropConglomerate(constants.indexCIDS[index]);
}
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class B2I method create.
/*
** Methods of B2I.
*/
/**
* Create an empty secondary index b-tree, using the generic b-tree to do the
* generic part of the creation process.
*
* This routine opens the newly created container, adds a single page, and
* makes this page the root by inserting a LeafControlRow onto this page
* at slot 0 and marking in that control row that the page is a root page.
*
* The following properties are specific to the b-tree secondary index:
* <UL>
* <LI> "baseConglomerateId" (integer). The conglomerate id of the base
* conglomerate is never actually accessed by the b-tree secondary
* index implementation, it only serves as a namespace for row locks.
* This property is required.
* <LI> "rowLocationColumn" (integer). The zero-based index into the row which
* the b-tree secondary index will assume holds a @see RowLocation of
* the base row in the base conglomerate. This value will be used
* for acquiring locks. In this implementation RowLocationColumn must be
* the last key column.
* This property is required.
* </UL>
*
* A secondary index i (a, b) on table t (a, b, c) would have rows
* which looked like (a, b, row_location). baseConglomerateId is set to the
* conglomerate id of t. rowLocationColumns is set to 2. allowsDuplicates
* would be set to false, @see BTree#create. To create a unique
* secondary index set uniquenessColumns to 2, this means that the btree
* code will compare the key values but not the row id when determing
* uniqueness. To create a nonunique secondary index set uniquenessColumns
* to 3, this would mean that the uniqueness test would include the row
* location and since all row locations will be unique all rows inserted
* into the index will be differentiated (at least) by row location.
*
* @see BTree#create
*
* @exception StandardException Standard exception policy.
*/
public void create(TransactionManager xact_manager, int segmentId, long input_conglomid, DataValueDescriptor[] template, ColumnOrdering[] columnOrder, int[] collationIds, Properties properties, int temporaryFlag) throws StandardException {
String property_value = null;
Transaction rawtran = xact_manager.getRawStoreXact();
if (properties == null) {
throw (StandardException.newException(SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
}
// Get baseConglomerateId //
property_value = properties.getProperty(PROPERTY_BASECONGLOMID);
if (property_value == null) {
throw (StandardException.newException(SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
}
if (SanityManager.DEBUG) {
if (property_value == null)
SanityManager.THROWASSERT(PROPERTY_BASECONGLOMID + "property not passed to B2I.create()");
}
baseConglomerateId = Long.parseLong(property_value);
// Get rowLocationColumn //
property_value = properties.getProperty(PROPERTY_ROWLOCCOLUMN);
if (SanityManager.DEBUG) {
if (property_value == null)
SanityManager.THROWASSERT(PROPERTY_ROWLOCCOLUMN + "property not passed to B2I.create()");
}
if (property_value == null) {
throw (StandardException.newException(SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
}
rowLocationColumn = Integer.parseInt(property_value);
// comparing the columns in the index easier.
if (SanityManager.DEBUG) {
SanityManager.ASSERT(rowLocationColumn == template.length - 1, "rowLocationColumn is not the last column in the index");
SanityManager.ASSERT(template[rowLocationColumn] instanceof RowLocation);
// There must be at least one key column
if (rowLocationColumn < 1)
SanityManager.THROWASSERT("rowLocationColumn (" + rowLocationColumn + ") expected to be >= 1");
}
/* convert the sorting order information into a boolean array map.
* If the sorting order for the columns is not provided, we
* assign the default as Ascending Order.
* array length is equal to template length, because column order
* length changes whether it is unique or is non unique. store assumes
* template length arrays. So, we make template length array and make
* the last column as ascending instead of having lot of execeptions
* code.
*/
ascDescInfo = new boolean[template.length];
for (int i = 0; i < ascDescInfo.length; i++) {
if (columnOrder != null && i < columnOrder.length)
ascDescInfo[i] = columnOrder[i].getIsAscending();
else
// default values - ascending order
ascDescInfo[i] = true;
}
// get collation ids from input collation ids, store it in the
// conglom state.
collation_ids = ConglomerateUtil.createCollationIds(template.length, collationIds);
hasCollatedTypes = hasCollatedColumns(collation_ids);
// Do the generic part of creating the b-tree.
super.create(rawtran, segmentId, input_conglomid, template, properties, getTypeFormatId(), temporaryFlag);
// open the base conglomerate - to get the lock
ConglomerateController base_cc = xact_manager.openConglomerate(baseConglomerateId, false, TransactionController.OPENMODE_FOR_LOCK_ONLY, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE);
OpenBTree open_btree = new OpenBTree();
BTreeLockingPolicy b2i_locking_policy = new B2ITableLocking3(rawtran, TransactionController.MODE_TABLE, rawtran.newLockingPolicy(LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true), base_cc, open_btree);
// The following call will "open" the new btree. Create is
// an interesting case. What we really want is read only table lock
// on the base conglomerate and update locks on the index. For now
// just get the update lock on the base table, this is done by the
// lockTable() call made by base class.
open_btree.init(// current user xact
(TransactionManager) xact_manager, // current xact
(TransactionManager) xact_manager, // have init open the container.
(ContainerHandle) null, rawtran, false, (ContainerHandle.MODE_FORUPDATE), TransactionController.MODE_TABLE, // get table level lock.
b2i_locking_policy, this, // no logical undo necessary, as
(LogicalUndo) null, // rows will not move.
(DynamicCompiledOpenConglomInfo) null);
// Open the newly created container, and insert the first control row.
LeafControlRow.initEmptyBtree(open_btree);
open_btree.close();
base_cc.close();
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class B2I method drop.
/**
* Drop this b-tree secondary index.
* @see Conglomerate#drop
* @see BTree#drop
*
* @exception StandardException Standard exception policy.
*/
public void drop(TransactionManager xact_manager) throws StandardException {
// HACK to get around problem where index is dropped after the base
// table.
ConglomerateController base_cc = null;
/* Get X table lock to make sure no thread is accessing index */
base_cc = lockTable(xact_manager, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_TABLE, TransactionController.ISOLATION_REPEATABLE_READ);
xact_manager.getRawStoreXact().dropContainer(id);
if (base_cc != null)
base_cc.close();
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class T_CreateConglomRet method t_003.
/**
* Test BTree.openScan(), BtreeScan.init(), BtreeScan.next(),
* BtreeScan.fetch().
*
* @exception StandardException Standard exception policy.
* @exception T_Fail Throws T_Fail on any test failure.
*/
protected boolean t_003(TransactionController tc) throws StandardException, T_Fail {
T_SecondaryIndexRow index_row = new T_SecondaryIndexRow();
// base row template - last column is just to make row long so that
// multiple pages are spanned.
DataValueDescriptor[] base_row = TemplateRow.newU8Row(4);
base_row[3] = new SQLChar();
String string_1500char = new String();
for (int i = 0; i < 300; i++) string_1500char += "mikem";
boolean ret_val = true;
long value = -1;
long[] col1 = { 1, 3, 4, 4, 4, 5, 5, 5, 6, 7, 9 };
long[] col2 = { 1, 1, 2, 4, 6, 2, 4, 6, 1, 1, 1 };
long[] col3 = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
// set of deleted rows to make scans more interesting
long[] d_col1 = { 0, 2, 3, 4, 4, 5, 5, 5, 6, 7, 8, 10, 11, 12 };
long[] d_col2 = { 1, 1, 2, 3, 5, 0, 3, 5, 0, 0, 1, 42, 42, 1 };
long[] d_col3 = { 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104 };
REPORT("Starting t_003");
// create the base table
long base_conglomid = tc.createConglomerate(// create a heap conglomerate
"heap", // base table template row
base_row, // column sort order - not required for heap
null, // default collation
null, // default properties
null, // not temporary
TransactionController.IS_DEFAULT);
// Open the base table
ConglomerateController base_cc = tc.openConglomerate(base_conglomid, false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE);
// initialize the secondary index row - pointing it at base row
index_row.init(base_row, base_cc.newRowLocationTemplate(), 5);
Properties properties = createProperties(// no current properties list
null, // don't allow duplicates
false, // 4 columns in index row
5, // non-unique index
5, // maintain parent links
true, // base conglom id
base_conglomid, // row loc in last column
4);
long index_conglomid = tc.createConglomerate(// create a btree secondary
"BTREE", // row template
index_row.getRow(), // column sort order - default
null, // default collation
null, // properties
properties, // not temporary
TransactionController.IS_DEFAULT);
// Open the conglomerate.
ConglomerateController index_cc = tc.openConglomerate(index_conglomid, false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE);
// Create a row.
T_SecondaryIndexRow template = new T_SecondaryIndexRow();
RowLocation row_loc = base_cc.newRowLocationTemplate();
template.init(base_row, row_loc, 5);
// insert them in reverse order just to make sure btree is sorting them
for (int i = col1.length - 1; i >= 0; i--) {
((SQLLongint) (template.getRow()[0])).setValue(col1[i]);
((SQLLongint) (template.getRow()[1])).setValue(col2[i]);
((SQLLongint) (template.getRow()[2])).setValue(col3[i]);
base_row[3] = new SQLChar(string_1500char);
base_cc.insertAndFetchLocation(base_row, row_loc);
// ")" + template);
if (index_cc.insert(template.getRow()) != 0)
throw T_Fail.testFailMsg("insert failed");
}
index_cc.checkConsistency();
((B2IController) index_cc).debugConglomerate();
ret_val = t_003_scan_test_cases(tc, index_conglomid, template);
// may or may not clean these up.
for (int i = d_col1.length - 1; i >= 0; i--) {
((SQLLongint) (template.getRow()[0])).setValue(d_col1[i]);
((SQLLongint) (template.getRow()[1])).setValue(d_col2[i]);
((SQLLongint) (template.getRow()[2])).setValue(d_col3[i]);
base_row[3] = new SQLChar(string_1500char);
base_cc.insertAndFetchLocation(base_row, row_loc);
// ")" + template);
if (index_cc.insert(template.getRow()) != 0)
throw T_Fail.testFailMsg("insert failed");
// now delete the row.
base_cc.delete(row_loc);
ScanController delete_scan = tc.openScan(index_conglomid, false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE, (FormatableBitSet) null, template.getRow(), ScanController.GE, null, template.getRow(), ScanController.GT);
if (!delete_scan.next()) {
throw T_Fail.testFailMsg("delete could not find key");
} else {
delete_scan.delete();
if (delete_scan.next())
throw T_Fail.testFailMsg("delete found more than one key");
}
delete_scan.close();
}
ret_val = t_003_scan_test_cases(tc, index_conglomid, template);
// Close the conglomerate.
index_cc.close();
tc.commit();
REPORT("Ending t_003");
return (ret_val);
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class T_CreateConglomRet method t_006.
/**
* Test unimplemented interfaces.
*
* The following ScanController interfaces are not supported by the
* btree implementation, because row locations are not returned outside
* the interface. At some point we may package a key as a row location
* but that does not really give any more functionality than using scan
* to find your key:
* ScanController.fetchLocation()
* ScanController.newRowLocationTemplate()
* ScanController.replace()
* ConglomerateController.delete()
* ConglomerateController.fetch()
* ConglomerateController.insertAndFetchLocation()
* ConglomerateController.newRowLocationTemplate()
* ConglomerateController.replace()
*
* @exception StandardException Standard exception policy.
* @exception T_Fail Throws T_Fail on any test failure.
*/
protected boolean t_006(TransactionController tc) throws StandardException, T_Fail {
REPORT("Starting t_006");
T_CreateConglomRet create_ret = new T_CreateConglomRet();
createCongloms(tc, 2, false, false, 0, create_ret);
// Open the base conglomerate.
ConglomerateController base_cc = tc.openConglomerate(create_ret.base_conglomid, false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE);
// Open the index conglomerate.
ConglomerateController index_cc = tc.openConglomerate(create_ret.index_conglomid, false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE);
// Create a base row template.
DataValueDescriptor[] base_row = TemplateRow.newU8Row(2);
RowLocation base_rowloc = base_cc.newRowLocationTemplate();
T_SecondaryIndexRow index_row_from_base_row = new T_SecondaryIndexRow();
index_row_from_base_row.init(base_row, base_rowloc, 3);
((SQLLongint) base_row[0]).setValue(1);
// Create a row.
T_SecondaryIndexRow index_row = new T_SecondaryIndexRow();
index_row.init(TemplateRow.newU8Row(2), base_cc.newRowLocationTemplate(), 3);
// test: make sure scan position is right after inserts before scan
// no split case. In this case the slot position of the current
// position should change, but the code will keep a record handle
// and not need to reposition by key.
// before keys: 1000, 3000
// last key gotten froms scan : 0
// insert keys:1-900
// next key from scan should be: 5
// insert 1000
((SQLLongint) base_row[1]).setValue(1000);
base_cc.insertAndFetchLocation(base_row, base_rowloc);
if (index_cc.insert(index_row_from_base_row.getRow()) != 0) {
throw T_Fail.testFailMsg("insert failed");
}
// try each of the unsupported interfaces:
try {
index_cc.delete(null);
return (FAIL("t_006: ConglomerateController.delete() succeeded."));
} catch (StandardException e) {
}
try {
if (!index_cc.fetch(null, RowUtil.EMPTY_ROW, (FormatableBitSet) null)) {
return (FAIL("t_006: ConglomerateController.fetch() bad ret."));
}
return (FAIL("t_006: ConglomerateController.fetch() succeeded."));
} catch (StandardException e) {
}
try {
index_cc.insertAndFetchLocation((DataValueDescriptor[]) null, null);
return (FAIL("t_006: ConglomerateController.insertAndFetchLocation() succeeded."));
} catch (StandardException e) {
}
try {
RowLocation rowloc = index_cc.newRowLocationTemplate();
return (FAIL("t_006: ConglomerateController.newRowLocationTemplate() succeeded."));
} catch (StandardException e) {
}
try {
index_cc.replace(null, null, null);
return (FAIL("t_006: ConglomerateController.replace() succeeded."));
} catch (StandardException e) {
}
index_cc.close();
// open a new scan
ScanController scan = tc.openScan(create_ret.index_conglomid, false, 0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE, (FormatableBitSet) null, null, ScanController.NA, null, null, ScanController.NA);
int numrows = 0;
while (scan.next()) {
numrows++;
scan.fetch(index_row_from_base_row.getRow());
try {
scan.fetchLocation(null);
return (FAIL("t_006: scan.fetchLocation() succeeded"));
} catch (StandardException e) {
}
try {
RowLocation rowloc = scan.newRowLocationTemplate();
return (FAIL("t_006: scan.newRowLocationTemplate() succeeded"));
} catch (StandardException e) {
}
try {
scan.replace(index_row_from_base_row.getRow(), (FormatableBitSet) null);
return (FAIL("t_006: scan.replace() succeeded"));
} catch (StandardException e) {
}
}
// make sure that scan.next() continues to return false
if (scan.next())
return (FAIL("t_006: scan.next() returned true after false."));
scan.close();
if (numrows != 1) {
return (FAIL("(t_scan) wrong number of rows. Expected " + "1 row, but got " + numrows + "rows."));
}
REPORT("Ending t_006");
return (true);
}
Aggregations