package com.healthmarketscience.jackcess;
import java.io.IOException;
-import java.sql.SQLException;
import java.util.Map;
import com.healthmarketscience.jackcess.complex.ComplexColumnInfo;
* @author James Ahlborn
* @usage _general_class_
*/
-public interface Column
+public interface Column
{
/**
* Meaningless placeholder object for inserting values in an autonumber
* @usage _general_field_
*/
public static final Object AUTO_NUMBER = "<AUTO_NUMBER>";
-
+
/**
* Meaningless placeholder object for updating rows which indicates that a
* given column should keep its existing value.
* @usage _general_field_
*/
public static final Object KEEP_VALUE = "<KEEP_VALUE>";
-
+
/**
* @usage _general_method_
*/
/**
* @usage _general_method_
*/
- public int getSQLType() throws SQLException;
+ public int getSQLType() throws IOException;
/**
* @usage _general_method_
* @usage _general_method_
*/
public PropertyMap getProperties() throws IOException;
-
+
/**
* Returns the column which tracks the version history for an "append only"
* column.
* @usage _intermediate_method_
*/
public ColumnValidator getColumnValidator();
-
+
/**
* Sets a new ColumnValidator. If {@code null}, resets to the value
* returned from the Database's ColumnValidatorFactory (if the factory
* @usage _intermediate_method_
*/
public void setColumnValidator(ColumnValidator newValidator);
-
+
public Object setRowValue(Object[] rowArray, Object value);
-
+
public Object setRowValue(Map<String,Object> rowMap, Object value);
-
+
public Object getRowValue(Object[] rowArray);
-
+
public Object getRowValue(Map<String,?> rowMap);
}
package com.healthmarketscience.jackcess;
import java.io.IOException;
-import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**
* Sets the type for the new column based on the given SQL type.
*/
- public ColumnBuilder setSQLType(int type) throws SQLException {
+ public ColumnBuilder setSQLType(int type) throws IOException {
return setSQLType(type, 0, null);
}
* data length (in type specific units).
*/
public ColumnBuilder setSQLType(int type, int lengthInUnits)
- throws SQLException
+ throws IOException
{
return setSQLType(type, lengthInUnits, null);
}
*/
public ColumnBuilder setSQLType(int type, int lengthInUnits,
Database.FileFormat fileFormat)
- throws SQLException
+ throws IOException
{
return setType(DataType.fromSQLType(type, lengthInUnits, fileFormat));
}
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
-import java.sql.SQLException;
import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import com.healthmarketscience.jackcess.impl.JetFormat;
+import com.healthmarketscience.jackcess.impl.SqlHelper;
/**
* Supported access data types.
return _maxSize;
}
- public int getSQLType() throws SQLException {
+ public int getSQLType() throws IOException {
if (_sqlType != null) {
return _sqlType;
}
- throw new SQLException("Unsupported data type: " + toString());
+ throw new JackcessException("Unsupported data type: " + toString());
}
public int getMinScale() {
}
public static DataType fromSQLType(int sqlType)
- throws SQLException
+ throws IOException
{
return fromSQLType(sqlType, 0, null);
}
public static DataType fromSQLType(int sqlType, int lengthInUnits)
- throws SQLException
+ throws IOException
{
return fromSQLType(sqlType, lengthInUnits, null);
}
public static DataType fromSQLType(int sqlType, int lengthInUnits,
Database.FileFormat fileFormat)
- throws SQLException
+ throws IOException
{
DataType[] rtnArr = SQL_TYPES.get(sqlType);
if(rtnArr == null) {
- throw new SQLException("Unsupported SQL type: " + sqlType);
+ throw new JackcessException("Unsupported SQL type: " + sqlType);
}
JetFormat format =
((fileFormat != null) ?
DataType altType)
{
try {
- java.lang.reflect.Field sqlTypeField = Types.class.getField(typeName);
- Integer value = (Integer)sqlTypeField.get(null);
+ Integer value = SqlHelper.INSTANCE.getNewSqlType(typeName);
SQL_TYPES.put(value, new DataType[]{type});
if(altType != null) {
ALT_SQL_TYPES.put(value, altType);
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.SQLException;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;
}
@Override
- public int getSQLType() throws SQLException {
+ public int getSQLType() throws IOException {
return _type.getSQLType();
}
return null;
} else if(value instanceof CharSequence) {
return (CharSequence)value;
- } else if(value instanceof Clob) {
- try {
- Clob c = (Clob)value;
- // note, start pos is 1-based
- return c.getSubString(1L, (int)c.length());
- } catch(SQLException e) {
- throw (IOException)(new IOException(e.getMessage())).initCause(e);
- }
+ } else if(SqlHelper.INSTANCE.isClob(value)) {
+ return SqlHelper.INSTANCE.getClobString(value);
} else if(value instanceof Reader) {
char[] buf = new char[8 * 1024];
StringBuilder sout = new StringBuilder();
return null;
} else if(value instanceof byte[]) {
return (byte[])value;
- } else if(value instanceof OleUtil.OleBlobImpl) {
- return ((OleUtil.OleBlobImpl)value).getBytes();
- } else if(value instanceof Blob) {
- try {
- Blob b = (Blob)value;
- // note, start pos is 1-based
- return b.getBytes(1L, (int)b.length());
- } catch(SQLException e) {
- throw (IOException)(new IOException(e.getMessage())).initCause(e);
- }
- } else if(value instanceof RawData) {
- return ((RawData)value).getBytes();
+ } else if(value instanceof InMemoryBlob) {
+ return ((InMemoryBlob)value).getBytes();
+ } else if(SqlHelper.INSTANCE.isBlob(value)) {
+ return SqlHelper.INSTANCE.getBlobBytes(value);
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
/**
* Wrapper for raw column data which can be re-written.
*/
- private static class RawData implements Serializable
+ private static final class RawData implements Serializable, InMemoryBlob
{
private static final long serialVersionUID = 0L;
_bytes = bytes;
}
- private byte[] getBytes() {
+ @Override
+ public byte[] getBytes() {
return _bytes;
}
return LocalDateTime.ofInstant(inst, db.getZoneId());
}
}
+
+ /** internal interface for types which hold bytes in memory */
+ static interface InMemoryBlob {
+ public byte[] getBytes() throws IOException;
+ }
}
}
- static final class OleBlobImpl implements OleBlob
+ static final class OleBlobImpl implements OleBlob, ColumnImpl.InMemoryBlob
{
private byte[] _bytes;
private ContentImpl _content;
return _bytes.length;
}
+ @Override
public byte[] getBytes() throws IOException {
if(_bytes == null) {
throw new IOException("blob is closed");
--- /dev/null
+/*
+Copyright (c) 2021 James Ahlborn
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.healthmarketscience.jackcess.impl;
+
+import java.io.IOException;
+
+/**
+ * Helper class to isolate the java.sql module interactions from the core of
+ * jackcess (in java 9+ environments). If the module is enabled (indicating
+ * that the application is already using sql constructs), then jackcess will
+ * seamlessly interact with sql types. If the module is not enabled
+ * (indicating that the application is not using any sql constructs), then
+ * jackcess will not require the module in order to function otherwise
+ * normally.
+ *
+ * This base class is the "fallback" class if the java.sql module is not
+ * available.
+ *
+ * @author James Ahlborn
+ */
+public class SqlHelper {
+
+ public static final SqlHelper INSTANCE = loadInstance();
+
+ public SqlHelper() {}
+
+ public boolean isBlob(Object value) {
+ return false;
+ }
+
+ public byte[] getBlobBytes(Object value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isClob(Object value) {
+ return false;
+ }
+
+ public CharSequence getClobString(Object value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Integer getNewSqlType(String typeName) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ private static final SqlHelper loadInstance() {
+ // attempt to load the implementation of this class which works with
+ // java.sql classes. if that fails, use this fallback instance instead.
+ try {
+ return (SqlHelper)
+ Class.forName("com.healthmarketscience.jackcess.impl.SqlHelperImpl")
+ .newInstance();
+ } catch(Throwable ignored) {}
+ return new SqlHelper();
+ }
+}
--- /dev/null
+/*
+Copyright (c) 2021 James Ahlborn
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.healthmarketscience.jackcess.impl;
+
+import java.io.IOException;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.SQLException;
+import java.sql.Types;
+
+/**
+ * Implementation of SqlHelperImpl which works with the java.sql modules
+ * classes. This class is used if the java.sql module is enabled in the
+ * application.
+ *
+ * @author James Ahlborn
+ */
+public class SqlHelperImpl extends SqlHelper {
+
+ public SqlHelperImpl() {}
+
+ @Override
+ public boolean isBlob(Object value) {
+ return (value instanceof Blob);
+ }
+
+ @Override
+ public byte[] getBlobBytes(Object value) throws IOException {
+ try {
+ Blob b = (Blob)value;
+ // note, start pos is 1-based
+ return b.getBytes(1L, (int)b.length());
+ } catch(SQLException e) {
+ throw (IOException)(new IOException(e.getMessage())).initCause(e);
+ }
+ }
+
+ @Override
+ public boolean isClob(Object value) {
+ return (value instanceof Clob);
+ }
+
+ @Override
+ public CharSequence getClobString(Object value) throws IOException {
+ try {
+ Clob c = (Clob)value;
+ // note, start pos is 1-based
+ return c.getSubString(1L, (int)c.length());
+ } catch(SQLException e) {
+ throw (IOException)(new IOException(e.getMessage())).initCause(e);
+ }
+ }
+
+ @Override
+ public Integer getNewSqlType(String typeName) throws Exception {
+ java.lang.reflect.Field sqlTypeField = Types.class.getField(typeName);
+ return (Integer)sqlTypeField.get(null);
+ }
+}
package com.healthmarketscience.jackcess.util;
+import com.healthmarketscience.jackcess.ColumnBuilder;
+import com.healthmarketscience.jackcess.DataType;
+import com.healthmarketscience.jackcess.Database;
+import com.healthmarketscience.jackcess.Table;
+import com.healthmarketscience.jackcess.TableBuilder;
+import com.healthmarketscience.jackcess.impl.ByteUtil;
+import com.healthmarketscience.jackcess.impl.DatabaseImpl;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.healthmarketscience.jackcess.ColumnBuilder;
-import com.healthmarketscience.jackcess.DataType;
-import com.healthmarketscience.jackcess.Database;
-import com.healthmarketscience.jackcess.Table;
-import com.healthmarketscience.jackcess.TableBuilder;
-import com.healthmarketscience.jackcess.impl.ByteUtil;
-import com.healthmarketscience.jackcess.impl.DatabaseImpl;
-
/**
* Utility class for importing tables to an Access database from other
* sources. See the {@link Builder} for convenient configuration of the
* @return a List of Columns
*/
public static List<ColumnBuilder> toColumns(ResultSetMetaData md)
- throws SQLException
+ throws SQLException, IOException
{
List<ColumnBuilder> columns = new ArrayList<ColumnBuilder>();
for (int i = 1; i <= md.getColumnCount(); i++) {
import java.nio.charset.Charset;
import java.nio.channels.FileChannel;
import java.nio.channels.NonWritableChannelException;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import com.healthmarketscience.jackcess.DataType;
import com.healthmarketscience.jackcess.Database;
+import com.healthmarketscience.jackcess.JackcessException;
import static com.healthmarketscience.jackcess.Database.*;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.PropertyMap;
Integer sqlType = null;
try {
sqlType = dt.getSQLType();
- } catch(SQLException ignored) {}
+ } catch(JackcessException ignored) {}
if(sqlType != null) {
assertEquals(dt, DataType.fromSQLType(sqlType));