aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2014-09-16 02:34:51 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2014-09-16 02:34:51 +0000
commita9607826269664210d4d5040f1b3505074837087 (patch)
tree4edc4fb35687da08e7ba04ab91aa7acfce143954 /src
parent6daeb346299aada5c174dbe9d9be2933f0012830 (diff)
downloadjackcess-a9607826269664210d4d5040f1b3505074837087.tar.gz
jackcess-a9607826269664210d4d5040f1b3505074837087.zip
fix creation of calculated fields
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@876 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src')
-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
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/CalcFieldTest.java34
4 files changed, 62 insertions, 14 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
}
diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/CalcFieldTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/CalcFieldTest.java
index d230cba..26b2390 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/CalcFieldTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/CalcFieldTest.java
@@ -20,6 +20,7 @@ USA
package com.healthmarketscience.jackcess.impl;
+import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -75,11 +76,19 @@ public class CalcFieldTest extends TestCase
.addColumn(new ColumnBuilder("id", DataType.LONG)
.setAutoNumber(true))
.addColumn(new ColumnBuilder("data", DataType.TEXT))
- .addColumn(new ColumnBuilder("calc_data", DataType.TEXT)
+ .addColumn(new ColumnBuilder("calc_text", DataType.TEXT)
.setCalculatedInfo("[id] & \"_\" & [data]"))
+ .addColumn(new ColumnBuilder("calc_memo", DataType.MEMO)
+ .setCalculatedInfo("[id] & \"_\" & [data]"))
+ .addColumn(new ColumnBuilder("calc_bool", DataType.BOOLEAN)
+ .setCalculatedInfo("[id] > 0"))
+ .addColumn(new ColumnBuilder("calc_long", DataType.LONG)
+ .setCalculatedInfo("[id] + 1"))
+ .addColumn(new ColumnBuilder("calc_numeric", DataType.NUMERIC)
+ .setCalculatedInfo("[id] / 0.03"))
.toTable(db);
- Column col = t.getColumn("calc_data");
+ Column col = t.getColumn("calc_text");
assertTrue(col.isCalculated());
assertEquals("[id] & \"_\" & [data]", col.getProperties().getValue(
PropertyMap.EXPRESSION_PROP));
@@ -87,14 +96,31 @@ public class CalcFieldTest extends TestCase
col.getProperties().getValue(
PropertyMap.RESULT_TYPE_PROP));
- t.addRow(Column.AUTO_NUMBER, "foo", "1_foo");
+ String longStr = createString(1000);
+ BigDecimal bd1 = new BigDecimal("-1234.5678");
+ BigDecimal bd2 = new BigDecimal("0.0234");
+
+ t.addRow(Column.AUTO_NUMBER, "foo", "1_foo", longStr, true, 2, bd1);
+ t.addRow(Column.AUTO_NUMBER, "bar", "2_bar", longStr, false, -37, bd2);
List<? extends Map<String, Object>> expectedRows =
createExpectedTable(
createExpectedRow(
"id", 1,
"data", "foo",
- "calc_data", "1_foo"));
+ "calc_text", "1_foo",
+ "calc_memo", longStr,
+ "calc_bool", true,
+ "calc_long", 2,
+ "calc_numeric", bd1),
+ createExpectedRow(
+ "id", 2,
+ "data", "bar",
+ "calc_text", "2_bar",
+ "calc_memo", longStr,
+ "calc_bool", false,
+ "calc_long", -37,
+ "calc_numeric", bd2));
assertTable(expectedRows, t);