diff options
author | James Ahlborn <jtahlborn@yahoo.com> | 2014-09-13 20:02:57 +0000 |
---|---|---|
committer | James Ahlborn <jtahlborn@yahoo.com> | 2014-09-13 20:02:57 +0000 |
commit | 2e8ed2591678a6bec8dd6152d521f9d121af000a (patch) | |
tree | 0cac37addbc62fe6e29614649f13e5f82ac4cdd3 /src | |
parent | 84089cb1372dc7f12ddacdfd165b0c1e8633f8ed (diff) | |
download | jackcess-2e8ed2591678a6bec8dd6152d521f9d121af000a.tar.gz jackcess-2e8ed2591678a6bec8dd6152d521f9d121af000a.zip |
Add the ability to create tables with calculated fields
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@873 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src')
5 files changed, 100 insertions, 6 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8ef8f7e..6b41e9c 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -18,6 +18,9 @@ Add the ability to set properties in DatabaseBuilder, TableBuilder, and ColumnBuilder. </action> + <action dev="jahlborn" type="add"> + Add the ability to create tables with calculated fields. + </action> </release> <release version="2.0.4" date="2014-04-05"> <action dev="jahlborn" type="add"> diff --git a/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java b/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java index 57c5bb5..628df86 100644 --- a/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java +++ b/src/main/java/com/healthmarketscience/jackcess/ColumnBuilder.java @@ -63,6 +63,8 @@ public class ColumnBuilder { private boolean _autoNumber; /** whether or not the column allows compressed unicode */ private boolean _compressedUnicode; + /** whether or not the column is calculated */ + private boolean _calculated; /** whether or not the column is a hyperlink (memo only) */ private boolean _hyperlink; /** 0-based column number */ @@ -192,6 +194,28 @@ public class ColumnBuilder { } /** + * Sets whether of not the new column is a calculated column. + */ + public ColumnBuilder setCalculated(boolean calculated) { + _calculated = calculated; + return this; + } + + public boolean isCalculated() { + return _calculated; + } + + /** + * Convenience method to set the various info for a calculated type (flag, + * result type property and expression) + */ + public ColumnBuilder setCalculatedInfo(String expression) { + setCalculated(true); + putProperty(PropertyMap.EXPRESSION_PROP, expression); + return putProperty(PropertyMap.RESULT_TYPE_PROP, getType().getValue()); + } + + /** * Sets whether of not the new column allows unicode compression. */ public ColumnBuilder setHyperlink(boolean hyperlink) { @@ -227,6 +251,10 @@ public class ColumnBuilder { public Map<String,PropertyMap.Property> getProperties() { return _props; } + + private PropertyMap.Property getProperty(String name) { + return ((_props != null) ? _props.get(name) : null); + } /** * Sets all attributes except name from the given Column template. @@ -370,6 +398,25 @@ public class ColumnBuilder { "Only memo columns can be hyperlinks"); } } + + if(isCalculated()) { + if(!format.isSupportedCalculatedDataType(getType())) { + throw new IllegalArgumentException( + "Database format " + format + " does not support calculated type " + + getType()); + } + + // must have an expression + if(getProperty(PropertyMap.EXPRESSION_PROP) == null) { + throw new IllegalArgumentException( + "No expression provided for calculated type " + getType()); + } + + // must have result type (just fill in if missing) + if(getProperty(PropertyMap.RESULT_TYPE_PROP) == null) { + putProperty(PropertyMap.RESULT_TYPE_PROP, getType().getValue()); + } + } } /** diff --git a/src/main/java/com/healthmarketscience/jackcess/TableBuilder.java b/src/main/java/com/healthmarketscience/jackcess/TableBuilder.java index b28d35b..c1d95f2 100644 --- a/src/main/java/com/healthmarketscience/jackcess/TableBuilder.java +++ b/src/main/java/com/healthmarketscience/jackcess/TableBuilder.java @@ -212,7 +212,7 @@ public class TableBuilder { _props.put(name, PropertyMapImpl.createProperty(name, type, value)); return this; } - + /** * Creates a new Table in the given Database with the currently configured * attributes. diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java index 4dc1afd..40c8c6c 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java @@ -1571,6 +1571,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> { buffer.put(col.getType().getValue()); buffer.putInt(TableImpl.MAGIC_TABLE_NUMBER); //constant magic number buffer.putShort(col.getColumnNumber()); //Column Number + if (col.getType().isVariableLength()) { if(!col.getType().isLongValue()) { buffer.putShort(variableOffset++); @@ -1580,13 +1581,16 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> { } else { buffer.putShort((short) 0); } + 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(), creator.getFormat()); } else { - if(col.getType().getHasScalePrecision()) { + // 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 { @@ -1595,13 +1599,20 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> { } buffer.putShort((short) 0); //Unknown } + buffer.put(getColumnBitFlags(col)); // misc col flags - if (col.isCompressedUnicode()) { //Compressed - buffer.put((byte) 1); + + // 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.put((byte)0); } + buffer.putInt(0); //Unknown, but always 0. + //Offset for fixed length columns if (col.getType().isVariableLength()) { buffer.putShort((short) 0); @@ -1609,11 +1620,13 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl> { buffer.putShort(fixedOffset); fixedOffset += col.getType().getFixedSize(col.getLength()); } + if(!col.getType().isLongValue()) { buffer.putShort(col.getLength()); //Column length } else { buffer.putShort((short)0x0000); // unused } + } for (ColumnBuilder col : columns) { TableImpl.writeName(buffer, col.getName(), creator.getCharset()); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java b/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java index ebc9081..fcb39bd 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/JetFormat.java @@ -32,11 +32,13 @@ import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; import java.util.Map; +import java.util.Set; -import com.healthmarketscience.jackcess.Database; import com.healthmarketscience.jackcess.DataType; +import com.healthmarketscience.jackcess.Database; /** * Encapsulates constants describing a specific version of the Access Jet format @@ -139,6 +141,13 @@ public abstract class JetFormat { } } + /** calculated types supported in version 14 */ + private static final Set<DataType> V14_CALC_TYPES = + EnumSet.of(DataType.BOOLEAN, DataType.BYTE, DataType.INT, DataType.LONG, + DataType.FLOAT, DataType.DOUBLE, DataType.GUID, + DataType.SHORT_DATE_TIME, DataType.MONEY, DataType.NUMERIC, + DataType.TEXT, DataType.MEMO); + /** the JetFormat constants for the Jet database version "3" */ public static final JetFormat VERSION_3 = new Jet3Format(); /** the JetFormat constants for the Jet database version "4" */ @@ -507,6 +516,8 @@ public abstract class JetFormat { public abstract boolean isSupportedDataType(DataType type); + public abstract boolean isSupportedCalculatedDataType(DataType type); + @Override public String toString() { return _name; @@ -733,6 +744,11 @@ public abstract class JetFormat { public boolean isSupportedDataType(DataType type) { return (type != DataType.COMPLEX_TYPE); } + + @Override + public boolean isSupportedCalculatedDataType(DataType type) { + return false; + } } private static class Jet4Format extends JetFormat { @@ -958,6 +974,11 @@ public abstract class JetFormat { public boolean isSupportedDataType(DataType type) { return (type != DataType.COMPLEX_TYPE); } + + @Override + public boolean isSupportedCalculatedDataType(DataType type) { + return false; + } } private static final class MSISAMFormat extends Jet4Format { @@ -1010,6 +1031,11 @@ public abstract class JetFormat { public boolean isSupportedDataType(DataType type) { return true; } + + @Override + public boolean isSupportedCalculatedDataType(DataType type) { + return false; + } } private static final class Jet14Format extends Jet12Format { @@ -1031,6 +1057,11 @@ public abstract class JetFormat { protected Map<String,Database.FileFormat> getPossibleFileFormats() { return PossibleFileFormats.POSSIBLE_VERSION_14; } + + @Override + public boolean isSupportedCalculatedDataType(DataType type) { + return V14_CALC_TYPES.contains(type); + } } } |