int[][] index_col_map = null;
ScanController[] index_scan = null;
ConglomerateController[] index_cc = null;
DataValueDescriptor[][] index_row = null;
TransactionController nested_tc = null;
try {
nested_tc =
tc.startNestedUserTransaction(false);
switch (td.getTableType())
{
/* Skip views and vti tables */
case TableDescriptor.VIEW_TYPE:
case TableDescriptor.VTI_TYPE:
return;
// other types give various errors here
// DERBY-719,DERBY-720
default:
break;
}
/* Get a row template for the base table */
ExecRow baseRow =
lcc.getLanguageConnectionFactory().getExecutionFactory().getValueRow(
td.getNumberOfColumns());
/* Fill the row with nulls of the correct type */
ColumnDescriptorList cdl = td.getColumnDescriptorList();
int cdlSize = cdl.size();
for (int index = 0; index < cdlSize; index++)
{
ColumnDescriptor cd = (ColumnDescriptor) cdl.elementAt(index);
baseRow.setColumn(cd.getPosition(), cd.getType().getNull());
}
DataValueDescriptor[][] row_array = new DataValueDescriptor[100][];
row_array[0] = baseRow.getRowArray();
RowLocation[] old_row_location_array = new RowLocation[100];
RowLocation[] new_row_location_array = new RowLocation[100];
// Create the following 3 arrays which will be used to update
// each index as the scan moves rows about the heap as part of
// the compress:
// index_col_map - map location of index cols in the base row,
// ie. index_col_map[0] is column offset of 1st
// key column in base row. All offsets are 0
// based.
// index_scan - open ScanController used to delete old index row
// index_cc - open ConglomerateController used to insert new
// row
ConglomerateDescriptor[] conglom_descriptors =
td.getConglomerateDescriptors();
// conglom_descriptors has an entry for the conglomerate and each
// one of it's indexes.
num_indexes = conglom_descriptors.length - 1;
// if indexes exist, set up data structures to update them
if (num_indexes > 0)
{
// allocate arrays
index_col_map = new int[num_indexes][];
index_scan = new ScanController[num_indexes];
index_cc = new ConglomerateController[num_indexes];
index_row = new DataValueDescriptor[num_indexes][];
setup_indexes(
nested_tc,
td,
index_col_map,
index_scan,
index_cc,
index_row);
}
/* Open the heap for reading */
base_group_fetch_cc =
nested_tc.defragmentConglomerate(
td.getHeapConglomerateId(),
false,
true,
TransactionController.OPENMODE_FORUPDATE,
TransactionController.MODE_TABLE,
TransactionController.ISOLATION_SERIALIZABLE);
int num_rows_fetched = 0;
while ((num_rows_fetched =
base_group_fetch_cc.fetchNextGroup(
row_array,
old_row_location_array,
new_row_location_array)) != 0)
{
if (num_indexes > 0)
{
for (int row = 0; row < num_rows_fetched; row++)
{
for (int index = 0; index < num_indexes; index++)
{
fixIndex(
row_array[row],
index_row[index],
old_row_location_array[row],
new_row_location_array[row],
index_cc[index],
index_scan[index],
index_col_map[index]);
}
}
}
}
// TODO - It would be better if commits happened more frequently
// in the nested transaction, but to do that there has to be more
// logic to catch a ddl that might jump in the middle of the
// above loop and invalidate the various table control structures
// which are needed to properly update the indexes. For example
// the above loop would corrupt an index added midway through
// the loop if not properly handled. See DERBY-1188.
nested_tc.commit();
}
finally
{
/* Clean up before we leave */
if (base_group_fetch_cc != null)
{
base_group_fetch_cc.close();
base_group_fetch_cc = null;
}
if (num_indexes > 0)
{
for (int i = 0; i < num_indexes; i++)
{
if (index_scan != null && index_scan[i] != null)
{
index_scan[i].close();
index_scan[i] = null;
}
if (index_cc != null && index_cc[i] != null)
{
index_cc[i].close();
index_cc[i] = null;
}
}
}
if (nested_tc != null)
{
nested_tc.destroy();
}
}
return;