diff options
author | James Ahlborn <jtahlborn@yahoo.com> | 2016-06-16 02:32:43 +0000 |
---|---|---|
committer | James Ahlborn <jtahlborn@yahoo.com> | 2016-06-16 02:32:43 +0000 |
commit | 8f482230a1bc1a459e20dabc42649e0adff27107 (patch) | |
tree | 2cd875bfd585454f1c40095efaa7662a2fa1baa3 /src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java | |
parent | a45ac7fc22c133a110ae54a6261857f96491bff8 (diff) | |
download | jackcess-8f482230a1bc1a459e20dabc42649e0adff27107.tar.gz jackcess-8f482230a1bc1a459e20dabc42649e0adff27107.zip |
implement most of the dirty work for adding indexes
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/mutateops@996 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java')
-rw-r--r-- | src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java | 217 |
1 files changed, 146 insertions, 71 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java index 5c704b6..97e073c 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java @@ -113,9 +113,9 @@ public class TableImpl implements Table /** Type of the table (either TYPE_SYSTEM or TYPE_USER) */ private final byte _tableType; /** Number of actual indexes on the table */ - private final int _indexCount; + private int _indexCount; /** Number of logical indexes for the table */ - private final int _logicalIndexCount; + private int _logicalIndexCount; /** page number of the definition of this table */ private final int _tableDefPageNumber; /** max Number of columns in the table (includes previous deletions) */ @@ -998,19 +998,8 @@ public class TableImpl implements Table IndexImpl.writeDefinitions(creator, buffer); } - // write long value column usage map references - for(ColumnBuilder lvalCol : creator.getLongValueColumns()) { - buffer.putShort(lvalCol.getColumnNumber()); - TableCreator.ColumnState colState = - creator.getColumnState(lvalCol); - - // owned pages umap (both are on same page) - buffer.put(colState.getUmapOwnedRowNumber()); - ByteUtil.put3ByteInt(buffer, colState.getUmapPageNumber()); - // free space pages umap - buffer.put(colState.getUmapFreeRowNumber()); - ByteUtil.put3ByteInt(buffer, colState.getUmapPageNumber()); - } + // column usage map references + ColumnImpl.writeColUsageMapDefinitions(creator, buffer); //End of tabledef buffer.put((byte) 0xff); @@ -1116,6 +1105,7 @@ public class TableImpl implements Table boolean isVarCol = column.isVariableLength(); boolean isLongVal = column.getType().isLongValue(); + //// // calculate how much more space we need in the table def if(isLongVal) { mutator.addTdefLen(10); @@ -1126,10 +1116,12 @@ public class TableImpl implements Table int nameByteLen = DBMutator.calculateNameLength(column.getName()); mutator.addTdefLen(nameByteLen); + //// // load current table definition and add space for new info ByteBuffer tableBuffer = loadCompleteTableDefinitionBufferForUpdate( mutator); + //// // update various bits of the table def ByteUtil.forward(tableBuffer, 29); tableBuffer.putShort((short)(_maxColumnCount + 1)); @@ -1171,9 +1163,7 @@ public class TableImpl implements Table ColumnImpl.writeDefinition(mutator, column, tableBuffer); // skip existing column names and write new name - for(int i = 0; i < _columns.size(); ++i) { - ByteUtil.forward(tableBuffer, tableBuffer.getShort()); - } + skipNames(tableBuffer, _columns.size()); ByteUtil.insertEmptyData(tableBuffer, nameByteLen); System.out.println("FOO pre name " + tableBuffer.position()); writeName(tableBuffer, column.getName(), mutator.getCharset()); @@ -1185,9 +1175,11 @@ public class TableImpl implements Table // allocate usage maps for the long value col Map.Entry<Integer,Integer> umapInfo = addUsageMaps(2); System.out.println("FOO created umap " + umapInfo); - int umapPageNum = umapInfo.getKey(); - int umapRow1 = umapInfo.getValue(); - int umapRow2 = umapRow1 + 1; + DBMutator.ColumnState colState = mutator.getColumnState(column); + colState.setUmapPageNumber(umapInfo.getKey()); + byte rowNum = umapInfo.getValue().byteValue(); + colState.setUmapOwnedRowNumber(rowNum); + colState.setUmapFreeRowNumber((byte)(rowNum + 1)); // skip past index defs System.out.println("FOO pre move " + tableBuffer.position()); @@ -1197,11 +1189,7 @@ public class TableImpl implements Table ByteUtil.forward(tableBuffer, (_logicalIndexCount * format.SIZE_INDEX_INFO_BLOCK)); System.out.println("FOO moved to " + tableBuffer.position()); - for(int i = 0; i < _logicalIndexCount; ++i) { - short len = tableBuffer.getShort(); - System.out.println("FOO skipping " + len); - ByteUtil.forward(tableBuffer, len); - } + skipNames(tableBuffer, _logicalIndexCount); // skip existing usage maps while(tableBuffer.remaining() >= 2) { @@ -1220,32 +1208,24 @@ public class TableImpl implements Table System.out.println("FOO about to write " + tableBuffer.position()); umapPos = tableBuffer.position(); ByteUtil.insertEmptyData(tableBuffer, 10); - tableBuffer.putShort(column.getColumnNumber()); - - // owned pages umap (both are on same page) - tableBuffer.put((byte)umapRow1); - ByteUtil.put3ByteInt(tableBuffer, umapPageNum); - // free space pages umap - tableBuffer.put((byte)umapRow2); - ByteUtil.put3ByteInt(tableBuffer, umapPageNum); + ColumnImpl.writeColUsageMapDefinition( + mutator, column, tableBuffer); } // sanity check the updates - if(!mutator.validateUpdatedTdef(tableBuffer)) { - throw new IllegalStateException( - withErrorContext("Failed update table definition (unexpected length)")); - } + validateTableDefUpdate(mutator, tableBuffer); // before writing the new table def, create the column ColumnImpl newCol = ColumnImpl.create(this, tableBuffer, colDefPos, column.getName(), _columns.size()); newCol.setColumnIndex(_columns.size()); + //// // write updated table def back to the database writeTableDefinitionBuffer(tableBuffer, _tableDefPageNumber, mutator, mutator.getNextPages()); - + //// // now, update current TableImpl _columns.add(newCol); @@ -1288,89 +1268,184 @@ public class TableImpl implements Table * Writes a index defined by the given TableMutator to this table. * @usage _advanced_method_ */ - protected IndexImpl mutateAddIndex(TableMutator mutator) throws IOException + protected IndexData mutateAddIndexData(TableMutator mutator) throws IOException { IndexBuilder index = mutator.getIndex(); JetFormat format = mutator.getFormat(); + //// // calculate how much more space we need in the table def - mutator.addTdefLen(format.SIZE_INDEX_INFO_BLOCK); + mutator.addTdefLen(format.SIZE_INDEX_DEFINITION + + format.SIZE_INDEX_COLUMN_BLOCK); + + //// + // load current table definition and add space for new info + ByteBuffer tableBuffer = loadCompleteTableDefinitionBufferForUpdate( + mutator); + + //// + // update various bits of the table def + ByteUtil.forward(tableBuffer, 39); + tableBuffer.putInt(_indexCount + 1); + + // move to end of index data def blocks + tableBuffer.position(format.SIZE_TDEF_HEADER + + (_indexCount * format.SIZE_INDEX_DEFINITION)); + + // write index row count definition (empty initially) + ByteUtil.insertEmptyData(tableBuffer, format.SIZE_INDEX_DEFINITION); + IndexData.writeRowCountDefinitions(mutator, tableBuffer, 1); - // FIXME - int indexDataNumber = 0; - boolean addingIndexData = (indexDataNumber >= _indexCount); - if(addingIndexData) { + // skip columns and column names + ByteUtil.forward(tableBuffer, + (_columns.size() * format.SIZE_COLUMN_DEF_BLOCK)); + skipNames(tableBuffer, _columns.size()); - // we are adding an index data as well - mutator.addTdefLen(format.SIZE_INDEX_DEFINITION + - format.SIZE_INDEX_COLUMN_BLOCK); + // move to end of current index datas + ByteUtil.forward(tableBuffer, (_indexCount * + format.SIZE_INDEX_COLUMN_BLOCK)); + + // write index data def + DBMutator.IndexDataState idxDataState = mutator.getIndexDataState(index); + int idxDataDefPos = tableBuffer.position(); + ByteUtil.insertEmptyData(tableBuffer, format.SIZE_INDEX_COLUMN_BLOCK); + IndexData.writeDefinition(mutator, tableBuffer, idxDataState, null); + + // sanity check the updates + validateTableDefUpdate(mutator, tableBuffer); + + // before writing the new table def, create the index data + tableBuffer.position(0); + IndexData newIdxData = IndexData.create( + this, tableBuffer, idxDataState.getIndexDataNumber(), format); + tableBuffer.position(idxDataDefPos); + newIdxData.read(tableBuffer, _columns); + + //// + // write updated table def back to the database + writeTableDefinitionBuffer(tableBuffer, _tableDefPageNumber, mutator, + mutator.getNextPages()); + + //// + // now, update current TableImpl + + for(IndexData.ColumnDescriptor iCol : newIdxData.getColumns()) { + _indexColumns.add(iCol.getColumn()); } + + ++_indexCount; + _indexDatas.add(newIdxData); + + completeTableMutation(tableBuffer); + + return newIdxData; + } + + /** + * Writes a index defined by the given TableMutator to this table. + * @usage _advanced_method_ + */ + protected IndexImpl mutateAddIndex(TableMutator mutator) throws IOException + { + IndexBuilder index = mutator.getIndex(); + JetFormat format = mutator.getFormat(); + + //// + // calculate how much more space we need in the table def + mutator.addTdefLen(format.SIZE_INDEX_INFO_BLOCK); int nameByteLen = DBMutator.calculateNameLength(index.getName()); mutator.addTdefLen(nameByteLen); + //// // load current table definition and add space for new info ByteBuffer tableBuffer = loadCompleteTableDefinitionBufferForUpdate( mutator); + //// // update various bits of the table def ByteUtil.forward(tableBuffer, 35); tableBuffer.putInt(_logicalIndexCount + 1); - int numIdxData = _indexCount + (addingIndexData ? 1 : 0); - tableBuffer.putInt(numIdxData); // move to end of index data def blocks tableBuffer.position(format.SIZE_TDEF_HEADER + (_indexCount * format.SIZE_INDEX_DEFINITION)); - if(addingIndexData) { - // write index row count definition (empty initially) - ByteUtil.insertEmptyData(tableBuffer, format.SIZE_INDEX_DEFINITION); - IndexData.writeRowCountDefinitions(mutator, tableBuffer, 1); - } - // skip columns and column names ByteUtil.forward(tableBuffer, (_columns.size() * format.SIZE_COLUMN_DEF_BLOCK)); - for(int i = 0; i < _columns.size(); ++i) { - ByteUtil.forward(tableBuffer, tableBuffer.getShort()); - } + skipNames(tableBuffer, _columns.size()); // move to end of current index datas ByteUtil.forward(tableBuffer, (_indexCount * format.SIZE_INDEX_COLUMN_BLOCK)); + // move to end of current indexes + ByteUtil.forward(tableBuffer, (_logicalIndexCount * + format.SIZE_INDEX_INFO_BLOCK)); - if(addingIndexData) { - // write index data def - ByteUtil.insertEmptyData(tableBuffer, format.SIZE_INDEX_COLUMN_BLOCK); - - // FIXME - } + int idxDefPos = tableBuffer.position(); + IndexImpl.writeDefinition(mutator, index, tableBuffer); - // FIXME + // skip existing index names and write new name + skipNames(tableBuffer, _logicalIndexCount); + ByteUtil.insertEmptyData(tableBuffer, nameByteLen); + writeName(tableBuffer, index.getName(), mutator.getCharset()); - IndexImpl newIdx = null; + // sanity check the updates + validateTableDefUpdate(mutator, tableBuffer); - // FIXME + // before writing the new table def, create the index + tableBuffer.position(idxDefPos); + IndexImpl newIdx = new IndexImpl(tableBuffer, _indexDatas, format); + newIdx.setName(index.getName()); + + //// + // write updated table def back to the database + writeTableDefinitionBuffer(tableBuffer, _tableDefPageNumber, mutator, + mutator.getNextPages()); + //// + // now, update current TableImpl - // FIXME, need to reset fkenforcer? + ++_logicalIndexCount; + _indexes.add(newIdx); completeTableMutation(tableBuffer); return newIdx; } + private void validateTableDefUpdate(TableMutator mutator, ByteBuffer tableBuffer) + throws IOException + { + if(!mutator.validateUpdatedTdef(tableBuffer)) { + throw new IllegalStateException( + withErrorContext("Failed updating table definition (unexpected length)")); + } + } + private void completeTableMutation(ByteBuffer tableBuffer) throws IOException { // lastly, may need to clear table def buffer _tableDefBufferH.possiblyInvalidate(_tableDefPageNumber, tableBuffer); + // update any foreign key enforcing + _fkEnforcer.reset(); + // update modification count so any active RowStates can keep themselves // up-to-date ++_modCount; } + /** + * Skips the given number of names in the table buffer. + */ + private static void skipNames(ByteBuffer tableBuffer, int count) { + for(int i = 0; i < count; ++i) { + ByteUtil.forward(tableBuffer, tableBuffer.getShort()); + } + } + private ByteBuffer loadCompleteTableDefinitionBufferForUpdate( TableMutator mutator) throws IOException @@ -1591,7 +1666,7 @@ public class TableImpl implements Table // index umap int indexIdx = i - 2; - TableCreator.IndexDataState idxDataState = + DBMutator.IndexDataState idxDataState = creator.getIndexDataStates().get(indexIdx); // allocate root page for the index @@ -1615,7 +1690,7 @@ public class TableImpl implements Table lvalColIdx /= 2; ColumnBuilder lvalCol = lvalCols.get(lvalColIdx); - TableCreator.ColumnState colState = + DBMutator.ColumnState colState = creator.getColumnState(lvalCol); umapBuf.put(rowStart, UsageMap.MAP_TYPE_INLINE); |