diff options
Diffstat (limited to 'src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java')
-rw-r--r-- | src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java | 179 |
1 files changed, 98 insertions, 81 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java index 8db672f..998e80a 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java @@ -33,6 +33,7 @@ import java.sql.Blob; import java.sql.Clob; import java.sql.SQLException; import java.util.Calendar; +import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; @@ -309,13 +310,17 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> { return new ColumnImpl(args); } - /** + /** * Sets the usage maps for this column. */ void setUsageMaps(UsageMap ownedPages, UsageMap freeSpacePages) { // base does nothing } + void collectUsageMapPages(Collection<Integer> pages) { + // base does nothing + } + /** * Secondary column initialization after the table is fully loaded. */ @@ -1405,22 +1410,6 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> { } /** - * @param columns A list of columns in a table definition - * @return The number of variable length columns which are not long values - * found in the list - * @usage _advanced_method_ - */ - private static short countNonLongVariableLength(List<ColumnBuilder> columns) { - short rtn = 0; - for (ColumnBuilder col : columns) { - if (col.isVariableLength() && !col.getType().isLongValue()) { - rtn++; - } - } - return rtn; - } - - /** * @return an appropriate BigDecimal representation of the given object. * <code>null</code> is returned as 0 and Numbers are converted * using their double representation. @@ -1585,90 +1574,118 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> { protected static void writeDefinitions(TableCreator creator, ByteBuffer buffer) throws IOException { - List<ColumnBuilder> columns = creator.getColumns(); - short fixedOffset = (short) 0; - short variableOffset = (short) 0; // we specifically put the "long variable" values after the normal // variable length values so that we have a better chance of fitting it // all (because "long variable" values can go in separate pages) - short longVariableOffset = countNonLongVariableLength(columns); - for (ColumnBuilder col : columns) { + int longVariableOffset = creator.countNonLongVariableLength(); + creator.setColumnOffsets(0, 0, longVariableOffset); - buffer.put(col.getType().getValue()); - buffer.putInt(TableImpl.MAGIC_TABLE_NUMBER); //constant magic number - buffer.putShort(col.getColumnNumber()); //Column Number + for (ColumnBuilder col : creator.getColumns()) { + writeDefinition(creator, col, buffer); + } - if(col.isVariableLength()) { - if(!col.getType().isLongValue()) { - buffer.putShort(variableOffset++); - } else { - buffer.putShort(longVariableOffset++); - } - } else { - buffer.putShort((short) 0); - } + for (ColumnBuilder col : creator.getColumns()) { + TableImpl.writeName(buffer, col.getName(), creator.getCharset()); + } + } - buffer.putShort(col.getColumnNumber()); //Column Number again + protected static void writeDefinition( + TableMutator mutator, ColumnBuilder col, ByteBuffer buffer) + throws IOException + { + TableMutator.ColumnOffsets colOffsets = mutator.getColumnOffsets(); - if(col.getType().isTextual()) { - // this will write 4 bytes (note we don't support writing dbs which - // use the text code page) - writeSortOrder(buffer, col.getTextSortOrder(), creator.getFormat()); - } else { - // note scale/precision not stored for calculated numeric fields - if(col.getType().getHasScalePrecision() && !col.isCalculated()) { - buffer.put(col.getPrecision()); // numeric precision - buffer.put(col.getScale()); // numeric scale - } else { - buffer.put((byte) 0x00); //unused - buffer.put((byte) 0x00); //unused - } - buffer.putShort((short) 0); //Unknown - } + buffer.put(col.getType().getValue()); + buffer.putInt(TableImpl.MAGIC_TABLE_NUMBER); //constant magic number + buffer.putShort(col.getColumnNumber()); //Column Number - buffer.put(getColumnBitFlags(col)); // misc col flags + if(col.isVariableLength()) { + buffer.putShort(colOffsets.getNextVariableOffset(col)); + } else { + buffer.putShort((short) 0); + } - // note access doesn't seem to allow unicode compression for calced fields - if(col.isCalculated()) { - buffer.put(CALCULATED_EXT_FLAG_MASK); - } else if (col.isCompressedUnicode()) { //Compressed - buffer.put(COMPRESSED_UNICODE_EXT_FLAG_MASK); + buffer.putShort(col.getColumnNumber()); //Column Number again + + if(col.getType().isTextual()) { + // this will write 4 bytes (note we don't support writing dbs which + // use the text code page) + writeSortOrder(buffer, col.getTextSortOrder(), mutator.getFormat()); + } else { + // note scale/precision not stored for calculated numeric fields + if(col.getType().getHasScalePrecision() && !col.isCalculated()) { + buffer.put(col.getPrecision()); // numeric precision + buffer.put(col.getScale()); // numeric scale } else { - buffer.put((byte)0); + buffer.put((byte) 0x00); //unused + buffer.put((byte) 0x00); //unused } + buffer.putShort((short) 0); //Unknown + } - buffer.putInt(0); //Unknown, but always 0. + buffer.put(getColumnBitFlags(col)); // misc col flags - //Offset for fixed length columns - if(col.isVariableLength()) { - buffer.putShort((short) 0); - } else { - buffer.putShort(fixedOffset); - fixedOffset += col.getType().getFixedSize(col.getLength()); - } + // note access doesn't seem to allow unicode compression for calced fields + if(col.isCalculated()) { + buffer.put(CALCULATED_EXT_FLAG_MASK); + } else if (col.isCompressedUnicode()) { //Compressed + buffer.put(COMPRESSED_UNICODE_EXT_FLAG_MASK); + } else { + buffer.put((byte)0); + } + + buffer.putInt(0); //Unknown, but always 0. - if(!col.getType().isLongValue()) { - short length = col.getLength(); - if(col.isCalculated()) { - // calced columns have additional value overhead - if(!col.getType().isVariableLength() || - col.getType().getHasScalePrecision()) { - length = CalculatedColumnUtil.CALC_FIXED_FIELD_LEN; - } else { - length += CalculatedColumnUtil.CALC_EXTRA_DATA_LEN; - } + //Offset for fixed length columns + if(col.isVariableLength()) { + buffer.putShort((short) 0); + } else { + buffer.putShort(colOffsets.getNextFixedOffset(col)); + } + + if(!col.getType().isLongValue()) { + short length = col.getLength(); + if(col.isCalculated()) { + // calced columns have additional value overhead + if(!col.getType().isVariableLength() || + col.getType().getHasScalePrecision()) { + length = CalculatedColumnUtil.CALC_FIXED_FIELD_LEN; + } else { + length += CalculatedColumnUtil.CALC_EXTRA_DATA_LEN; } - buffer.putShort(length); //Column length - } else { - buffer.putShort((short)0x0000); // unused } - + buffer.putShort(length); //Column length + } else { + buffer.putShort((short)0x0000); // unused } - for (ColumnBuilder col : columns) { - TableImpl.writeName(buffer, col.getName(), creator.getCharset()); + } + + protected static void writeColUsageMapDefinitions( + TableCreator creator, ByteBuffer buffer) + throws IOException + { + // write long value column usage map references + for(ColumnBuilder lvalCol : creator.getLongValueColumns()) { + writeColUsageMapDefinition(creator, lvalCol, buffer); } } + protected static void writeColUsageMapDefinition( + TableMutator creator, ColumnBuilder lvalCol, ByteBuffer buffer) + throws IOException + { + TableMutator.ColumnState colState = creator.getColumnState(lvalCol); + + buffer.putShort(lvalCol.getColumnNumber()); + + // 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()); + } + /** * Reads the sort order info from the given buffer from the given position. */ |