aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java5
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java13
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java24
3 files changed, 32 insertions, 10 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java b/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java
index 628df86..bbfca27 100644
--- a/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java
+++ b/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java
@@ -215,6 +215,11 @@ public class ColumnBuilder {
return putProperty(PropertyMap.RESULT_TYPE_PROP, getType().getValue());
}
+ public boolean isVariableLength() {
+ // calculated columns are written as var len
+ return(getType().isVariableLength() || isCalculated());
+ }
+
/**
* Sets whether of not the new column allows unicode compression.
*/
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java b/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
index e548da2..727818a 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/CalculatedColumnUtil.java
@@ -40,7 +40,9 @@ class CalculatedColumnUtil
// offset to the actual data
private static final int CALC_DATA_OFFSET = CALC_DATA_LEN_OFFSET + 4;
// total amount of extra bytes added for calculated values
- private static final int CALC_EXTRA_DATA_LEN = 23;
+ static final int CALC_EXTRA_DATA_LEN = 23;
+ // ms access seems to define all fixed-len calc fields as this length
+ static final short CALC_FIXED_FIELD_LEN = 39;
// fully encode calculated BOOLEAN "true" value
private static final byte[] CALC_BOOL_TRUE = wrapCalculatedValue(
@@ -278,7 +280,8 @@ class CalculatedColumnUtil
throws IOException
{
int totalDataLen = Math.min(CALC_EXTRA_DATA_LEN + 16 + 4, getLength());
- int dataLen = totalDataLen - CALC_EXTRA_DATA_LEN;
+ // data length must be multiple of 4
+ int dataLen = toMul4(totalDataLen - CALC_EXTRA_DATA_LEN);
ByteBuffer buffer = prepareWrappedCalcValue(dataLen, order);
writeCalcNumericValue(buffer, obj, dataLen);
@@ -293,7 +296,7 @@ class CalculatedColumnUtil
// numeric bytes need to be a multiple of 4 and we currently handle at
// most 16 bytes
int numByteLen = ((totalLen > 0) ? totalLen : buffer.remaining()) - 2;
- numByteLen = Math.min((numByteLen / 4) * 4, 16);
+ numByteLen = Math.min(toMul4(numByteLen), 16);
byte scale = buffer.get();
boolean negate = (buffer.get() != 0);
@@ -371,6 +374,10 @@ class CalculatedColumnUtil
ByteUtil.swap8Bytes(bytes, pos);
}
}
+
+ private static int toMul4(int val) {
+ return ((val / 4) * 4);
+ }
}
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
index 40c8c6c..0fbe7c2 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
@@ -1264,7 +1264,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
*/
private static byte getColumnBitFlags(ColumnBuilder col) {
byte flags = UNKNOWN_FLAG_MASK;
- if(!col.getType().isVariableLength()) {
+ if(!col.isVariableLength()) {
flags |= FIXED_LEN_FLAG_MASK;
}
if(col.isAutoNumber()) {
@@ -1377,7 +1377,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
public static short countVariableLength(List<ColumnBuilder> columns) {
short rtn = 0;
for (ColumnBuilder col : columns) {
- if (col.getType().isVariableLength()) {
+ if (col.isVariableLength()) {
rtn++;
}
}
@@ -1390,10 +1390,10 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
* found in the list
* @usage _advanced_method_
*/
- public static short countNonLongVariableLength(List<ColumnBuilder> columns) {
+ private static short countNonLongVariableLength(List<ColumnBuilder> columns) {
short rtn = 0;
for (ColumnBuilder col : columns) {
- if (col.getType().isVariableLength() && !col.getType().isLongValue()) {
+ if (col.isVariableLength() && !col.getType().isLongValue()) {
rtn++;
}
}
@@ -1572,7 +1572,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
buffer.putInt(TableImpl.MAGIC_TABLE_NUMBER); //constant magic number
buffer.putShort(col.getColumnNumber()); //Column Number
- if (col.getType().isVariableLength()) {
+ if(col.isVariableLength()) {
if(!col.getType().isLongValue()) {
buffer.putShort(variableOffset++);
} else {
@@ -1614,7 +1614,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
buffer.putInt(0); //Unknown, but always 0.
//Offset for fixed length columns
- if (col.getType().isVariableLength()) {
+ if(col.isVariableLength()) {
buffer.putShort((short) 0);
} else {
buffer.putShort(fixedOffset);
@@ -1622,7 +1622,17 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> {
}
if(!col.getType().isLongValue()) {
- buffer.putShort(col.getLength()); //Column length
+ 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
}