From e54c7d0b75bacd15807e2620759ff816534949e8 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Sat, 2 Mar 2013 15:09:44 +0000 Subject: [PATCH] separate Database into internal and external; remove SimpleIndexData; make fk enforce true by default; remove import methods from Database git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/jackcess-2@667 f203690c-595d-4dc9-a70b-905162fa7fd2 --- TODO.txt | 12 + .../jackcess/BigIndexData.java | 86 -- .../jackcess/ByteUtil.java | 2 +- .../healthmarketscience/jackcess/Column.java | 4 +- .../jackcess/ColumnBuilder.java | 2 +- .../jackcess/DatabaseBuilder.java | 8 +- .../{Database.java => DatabaseImpl.java} | 790 ++---------------- .../jackcess/ExportUtil.java | 24 +- .../jackcess/GeneralIndexCodes.java | 4 +- .../jackcess/GeneralLegacyIndexCodes.java | 6 +- .../jackcess/ImportUtil.java | 40 +- .../jackcess/IndexData.java | 104 ++- .../jackcess/IndexPageCache.java | 8 +- .../jackcess/JetFormat.java | 36 +- .../jackcess/MemFileChannel.java | 8 +- .../jackcess/PageChannel.java | 2 +- .../jackcess/PropertyMap.java | 4 +- .../jackcess/PropertyMaps.java | 10 +- .../jackcess/SimpleIndexData.java | 241 ------ .../healthmarketscience/jackcess/Table.java | 25 +- .../jackcess/TableBuilder.java | 14 +- .../jackcess/TableCreator.java | 8 +- .../jackcess/UsageMap.java | 8 +- .../jackcess/complex/ComplexColumnInfo.java | 6 +- 24 files changed, 246 insertions(+), 1206 deletions(-) delete mode 100644 src/java/com/healthmarketscience/jackcess/BigIndexData.java rename src/java/com/healthmarketscience/jackcess/{Database.java => DatabaseImpl.java} (71%) delete mode 100644 src/java/com/healthmarketscience/jackcess/SimpleIndexData.java diff --git a/TODO.txt b/TODO.txt index d8472b8..2157a0a 100644 --- a/TODO.txt +++ b/TODO.txt @@ -20,3 +20,15 @@ Missing pieces: * EASY - figure out how msaccess manages page/row locks * MEDIUM + +Refactor goals: +- simplify public API (separate "internal" and "external" api) +- separate table creation objects from existing metadata objects +- remove "simple" index support? +- remove "table traversal methods" from Table? +- enable integrity by default? +- remove import/export methods from Database? +- move database open/create options to DBBuilder +- tweak how import filters work to make them more flexible? +- tweak lookup apis (specify column vs column name) +- separate classes into more packages (api,builder,util,impl) diff --git a/src/java/com/healthmarketscience/jackcess/BigIndexData.java b/src/java/com/healthmarketscience/jackcess/BigIndexData.java deleted file mode 100644 index c06af26..0000000 --- a/src/java/com/healthmarketscience/jackcess/BigIndexData.java +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright (c) 2008 Health Market Science, Inc. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -USA - -You can contact Health Market Science at info@healthmarketscience.com -or at the following address: - -Health Market Science -2700 Horizon Drive -Suite 200 -King of Prussia, PA 19406 -*/ - -package com.healthmarketscience.jackcess; - -import java.io.IOException; - - -/** - * Implementation of an Access table index which supports large indexes. - * @author James Ahlborn - */ -public class BigIndexData extends IndexData { - - /** Cache which manages the index pages */ - private final IndexPageCache _pageCache; - - public BigIndexData(Table table, int number, int uniqueEntryCount, - int uniqueEntryCountOffset) { - super(table, number, uniqueEntryCount, uniqueEntryCountOffset); - _pageCache = new IndexPageCache(this); - } - - @Override - protected void updateImpl() throws IOException { - _pageCache.write(); - } - - @Override - protected void readIndexEntries() - throws IOException - { - _pageCache.setRootPageNumber(getRootPageNumber()); - } - - @Override - protected DataPage findDataPage(Entry entry) - throws IOException - { - return _pageCache.findCacheDataPage(entry); - } - - @Override - protected DataPage getDataPage(int pageNumber) - throws IOException - { - return _pageCache.getCacheDataPage(pageNumber); - } - - @Override - public String toString() { - return super.toString() + "\n" + _pageCache.toString(); - } - - /** - * Used by unit tests to validate the internal status of the index. - */ - void validate() throws IOException { - _pageCache.validate(); - } - -} diff --git a/src/java/com/healthmarketscience/jackcess/ByteUtil.java b/src/java/com/healthmarketscience/jackcess/ByteUtil.java index b500268..b06f033 100644 --- a/src/java/com/healthmarketscience/jackcess/ByteUtil.java +++ b/src/java/com/healthmarketscience/jackcess/ByteUtil.java @@ -486,7 +486,7 @@ public final class ByteUtil { * Convert the given number of bytes from the given database page to a * hexidecimal string for display. */ - public static String toHexString(Database db, int pageNumber, int size) + public static String toHexString(DatabaseImpl db, int pageNumber, int size) throws IOException { ByteBuffer buffer = db.getPageChannel().createPageBuffer(); diff --git a/src/java/com/healthmarketscience/jackcess/Column.java b/src/java/com/healthmarketscience/jackcess/Column.java index 57df40e..d6f71c3 100644 --- a/src/java/com/healthmarketscience/jackcess/Column.java +++ b/src/java/com/healthmarketscience/jackcess/Column.java @@ -334,7 +334,7 @@ public class Column implements Comparable { /** * @usage _general_method_ */ - public Database getDatabase() { + public DatabaseImpl getDatabase() { return getTable().getDatabase(); } @@ -742,7 +742,7 @@ public class Column implements Comparable { if(getType() == null) { throw new IllegalArgumentException("must have type"); } - Database.validateIdentifierName(getName(), format.MAX_COLUMN_NAME_LENGTH, + DatabaseImpl.validateIdentifierName(getName(), format.MAX_COLUMN_NAME_LENGTH, "column"); if(getType().isUnsupported()) { diff --git a/src/java/com/healthmarketscience/jackcess/ColumnBuilder.java b/src/java/com/healthmarketscience/jackcess/ColumnBuilder.java index befff67..c09ec97 100644 --- a/src/java/com/healthmarketscience/jackcess/ColumnBuilder.java +++ b/src/java/com/healthmarketscience/jackcess/ColumnBuilder.java @@ -161,7 +161,7 @@ public class ColumnBuilder { */ public ColumnBuilder escapeName() { - _name = Database.escapeIdentifier(_name); + _name = DatabaseImpl.escapeIdentifier(_name); return this; } diff --git a/src/java/com/healthmarketscience/jackcess/DatabaseBuilder.java b/src/java/com/healthmarketscience/jackcess/DatabaseBuilder.java index fa0a394..0b43657 100644 --- a/src/java/com/healthmarketscience/jackcess/DatabaseBuilder.java +++ b/src/java/com/healthmarketscience/jackcess/DatabaseBuilder.java @@ -149,15 +149,15 @@ public class DatabaseBuilder * Opens an existingnew Database using the configured information. */ public Database open() throws IOException { - return Database.open(_mdbFile, _readOnly, _channel, _autoSync, _charset, - _timeZone, _codecProvider); + return DatabaseImpl.open(_mdbFile, _readOnly, _channel, _autoSync, _charset, + _timeZone, _codecProvider); } /** * Creates a new Database using the configured information. */ public Database create() throws IOException { - return Database.create(_fileFormat, _mdbFile, _channel, _autoSync, _charset, - _timeZone); + return DatabaseImpl.create(_fileFormat, _mdbFile, _channel, _autoSync, + _charset, _timeZone); } } diff --git a/src/java/com/healthmarketscience/jackcess/Database.java b/src/java/com/healthmarketscience/jackcess/DatabaseImpl.java similarity index 71% rename from src/java/com/healthmarketscience/jackcess/Database.java rename to src/java/com/healthmarketscience/jackcess/DatabaseImpl.java index 2867587..4854fd6 100644 --- a/src/java/com/healthmarketscience/jackcess/Database.java +++ b/src/java/com/healthmarketscience/jackcess/DatabaseImpl.java @@ -27,11 +27,8 @@ King of Prussia, PA 19406 package com.healthmarketscience.jackcess; -import java.io.BufferedReader; -import java.io.Closeable; import java.io.File; import java.io.FileNotFoundException; -import java.io.Flushable; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; @@ -42,8 +39,6 @@ import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.charset.Charset; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -68,29 +63,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * An Access database. - *

- * There is optional support for large indexes (enabled by default). This - * optional support can be disabled via a few different means: - *

    - *
  • Setting the system property {@value #USE_BIG_INDEX_PROPERTY} to - * {@code "false"} will disable "large" index support across the jvm
  • - *
  • Calling {@link #setUseBigIndex} on a Database instance will override - * any system property setting for "large" index support for all tables - * subsequently created from that instance
  • - *
  • Calling {@link #getTable(String,boolean)} can selectively - * enable/disable "large" index support on a per-table basis (overriding - * any Database or system property setting)
  • - *
* * @author Tim McCune * @usage _general_class_ */ -public class Database - implements Iterable, Closeable, Flushable -{ - - private static final Log LOG = LogFactory.getLog(Database.class); +public class DatabaseImpl extends Database +{ + private static final Log LOG = LogFactory.getLog(DatabaseImpl.class); /** this is the default "userId" used if we cannot find existing info. this seems to be some standard "Admin" userId for access files */ @@ -100,110 +79,6 @@ public class Database SYS_DEFAULT_SID[1] = (byte) 0x33; } - /** default value for the auto-sync value ({@code true}). this is slower, - * but leaves more chance of a useable database in the face of failures. - * @usage _general_field_ - */ - public static final boolean DEFAULT_AUTO_SYNC = true; - - /** the default value for the resource path used to load classpath - * resources. - * @usage _general_field_ - */ - public static final String DEFAULT_RESOURCE_PATH = - "com/healthmarketscience/jackcess/"; - - /** - * the default sort order for table columns. - * @usage _intermediate_field_ - */ - public static final Table.ColumnOrder DEFAULT_COLUMN_ORDER = - Table.ColumnOrder.DATA; - - /** (boolean) system property which can be used to disable the default big - * index support. - * @usage _general_field_ - */ - public static final String USE_BIG_INDEX_PROPERTY = - "com.healthmarketscience.jackcess.bigIndex"; - - /** system property which can be used to set the default TimeZone used for - * date calculations. - * @usage _general_field_ - */ - public static final String TIMEZONE_PROPERTY = - "com.healthmarketscience.jackcess.timeZone"; - - /** system property prefix which can be used to set the default Charset - * used for text data (full property includes the JetFormat version). - * @usage _general_field_ - */ - public static final String CHARSET_PROPERTY_PREFIX = - "com.healthmarketscience.jackcess.charset."; - - /** system property which can be used to set the path from which classpath - * resources are loaded (must end with a "/" if non-empty). Default value - * is {@link #DEFAULT_RESOURCE_PATH} if unspecified. - * @usage _general_field_ - */ - public static final String RESOURCE_PATH_PROPERTY = - "com.healthmarketscience.jackcess.resourcePath"; - - /** (boolean) system property which can be used to indicate that the current - * vm has a poor nio implementation (specifically for - * FileChannel.transferFrom) - * @usage _intermediate_field_ - */ - public static final String BROKEN_NIO_PROPERTY = - "com.healthmarketscience.jackcess.brokenNio"; - - /** system property which can be used to set the default sort order for - * table columns. Value should be one {@link Table.ColumnOrder} enum - * values. - * @usage _intermediate_field_ - */ - public static final String COLUMN_ORDER_PROPERTY = - "com.healthmarketscience.jackcess.columnOrder"; - - /** system property which can be used to set the default enforcement of - * foreign-key relationships. Defaults to {@code false}. - * @usage _general_field_ - */ - public static final String FK_ENFORCE_PROPERTY = - "com.healthmarketscience.jackcess.enforceForeignKeys"; - - /** - * default error handler used if none provided (just rethrows exception) - * @usage _general_field_ - */ - public static final ErrorHandler DEFAULT_ERROR_HANDLER = new ErrorHandler() { - public Object handleRowError(Column column, - byte[] columnData, - Table.RowState rowState, - Exception error) - throws IOException - { - // really can only be RuntimeException or IOException - if(error instanceof IOException) { - throw (IOException)error; - } - throw (RuntimeException)error; - } - }; - - /** - * default link resolver used if none provided - * @usage _general_field_ - */ - public static final LinkResolver DEFAULT_LINK_RESOLVER = new LinkResolver() { - public Database resolveLinkedDatabase(Database linkerDb, - String linkeeFileName) - throws IOException - { - return Database.open(new File(linkeeFileName)); - } - }; - /** the resource path to be used when loading classpath resources */ static final String RESOURCE_PATH = System.getProperty(RESOURCE_PATH_PROPERTY, DEFAULT_RESOURCE_PATH); @@ -292,41 +167,6 @@ public class Database /** read/write channel access mode */ static final String RW_CHANNEL_MODE = "rw"; - /** - * Enum which indicates which version of Access created the database. - * @usage _general_class_ - */ - public static enum FileFormat { - - V1997(null, JetFormat.VERSION_3), - V2000(RESOURCE_PATH + "empty.mdb", JetFormat.VERSION_4), - V2003(RESOURCE_PATH + "empty2003.mdb", JetFormat.VERSION_4), - V2007(RESOURCE_PATH + "empty2007.accdb", JetFormat.VERSION_12, ".accdb"), - V2010(RESOURCE_PATH + "empty2010.accdb", JetFormat.VERSION_14, ".accdb"), - MSISAM(null, JetFormat.VERSION_MSISAM, ".mny"); - - private final String _emptyFile; - private final JetFormat _format; - private final String _ext; - - private FileFormat(String emptyDBFile, JetFormat jetFormat) { - this(emptyDBFile, jetFormat, ".mdb"); - } - - private FileFormat(String emptyDBFile, JetFormat jetFormat, String ext) { - _emptyFile = emptyDBFile; - _format = jetFormat; - _ext = ext; - } - - public JetFormat getJetFormat() { return _format; } - - public String getFileExtension() { return _ext; } - - @Override - public String toString() { return name() + ", jetFormat: " + getJetFormat(); } - } - /** Prefix for column or table names that are reserved words */ private static final String ESCAPE_PREFIX = "x"; /** Name of the system object that is the parent of all tables */ @@ -454,8 +294,6 @@ public class Database private Table _complexCols; /** SIDs to use for the ACEs added for new tables */ private final List _newTableSIDs = new ArrayList(); - /** "big index support" is optional, but enabled by default */ - private Boolean _useBigIndex; /** optional error handler to use when row errors are encountered */ private ErrorHandler _dbErrorHandler; /** the file format of the database */ @@ -494,128 +332,6 @@ public class Database /** Calendar for use interpreting dates/times in Columns */ private Calendar _calendar; - /** - * Open an existing Database. If the existing file is not writeable, the - * file will be opened read-only. Auto-syncing is enabled for the returned - * Database. - *

- * Equivalent to: - * {@code open(mdbFile, false);} - * - * @param mdbFile File containing the database - * - * @see #open(File,boolean) - * @see DatabaseBuilder for more flexible Database opening - * @usage _general_method_ - */ - public static Database open(File mdbFile) throws IOException { - return open(mdbFile, false); - } - - /** - * Open an existing Database. If the existing file is not writeable or the - * readOnly flag is {@code true}, the file will be opened read-only. - * Auto-syncing is enabled for the returned Database. - *

- * Equivalent to: - * {@code open(mdbFile, readOnly, DEFAULT_AUTO_SYNC);} - * - * @param mdbFile File containing the database - * @param readOnly iff {@code true}, force opening file in read-only - * mode - * - * @see #open(File,boolean,boolean) - * @see DatabaseBuilder for more flexible Database opening - * @usage _general_method_ - */ - public static Database open(File mdbFile, boolean readOnly) - throws IOException - { - return open(mdbFile, readOnly, DEFAULT_AUTO_SYNC); - } - - /** - * Open an existing Database. If the existing file is not writeable or the - * readOnly flag is {@code true}, the file will be opened read-only. - * @param mdbFile File containing the database - * @param readOnly iff {@code true}, force opening file in read-only - * mode - * @param autoSync whether or not to enable auto-syncing on write. if - * {@code true}, writes will be immediately flushed to disk. - * This leaves the database in a (fairly) consistent state - * on each write, but can be very inefficient for many - * updates. if {@code false}, flushing to disk happens at - * the jvm's leisure, which can be much faster, but may - * leave the database in an inconsistent state if failures - * are encountered during writing. Writes may be flushed at - * any time using {@link #flush}. - * @see DatabaseBuilder for more flexible Database opening - * @usage _general_method_ - */ - public static Database open(File mdbFile, boolean readOnly, boolean autoSync) - throws IOException - { - return open(mdbFile, readOnly, autoSync, null, null); - } - - /** - * Open an existing Database. If the existing file is not writeable or the - * readOnly flag is {@code true}, the file will be opened read-only. - * @param mdbFile File containing the database - * @param readOnly iff {@code true}, force opening file in read-only - * mode - * @param autoSync whether or not to enable auto-syncing on write. if - * {@code true}, writes will be immediately flushed to disk. - * This leaves the database in a (fairly) consistent state - * on each write, but can be very inefficient for many - * updates. if {@code false}, flushing to disk happens at - * the jvm's leisure, which can be much faster, but may - * leave the database in an inconsistent state if failures - * are encountered during writing. Writes may be flushed at - * any time using {@link #flush}. - * @param charset Charset to use, if {@code null}, uses default - * @param timeZone TimeZone to use, if {@code null}, uses default - * @see DatabaseBuilder for more flexible Database opening - * @usage _intermediate_method_ - */ - public static Database open(File mdbFile, boolean readOnly, boolean autoSync, - Charset charset, TimeZone timeZone) - throws IOException - { - return open(mdbFile, readOnly, autoSync, charset, timeZone, null); - } - - /** - * Open an existing Database. If the existing file is not writeable or the - * readOnly flag is {@code true}, the file will be opened read-only. - * @param mdbFile File containing the database - * @param readOnly iff {@code true}, force opening file in read-only - * mode - * @param autoSync whether or not to enable auto-syncing on write. if - * {@code true}, writes will be immediately flushed to disk. - * This leaves the database in a (fairly) consistent state - * on each write, but can be very inefficient for many - * updates. if {@code false}, flushing to disk happens at - * the jvm's leisure, which can be much faster, but may - * leave the database in an inconsistent state if failures - * are encountered during writing. Writes may be flushed at - * any time using {@link #flush}. - * @param charset Charset to use, if {@code null}, uses default - * @param timeZone TimeZone to use, if {@code null}, uses default - * @param provider CodecProvider for handling page encoding/decoding, may be - * {@code null} if no special encoding is necessary - * @see DatabaseBuilder for more flexible Database opening - * @usage _intermediate_method_ - */ - public static Database open(File mdbFile, boolean readOnly, boolean autoSync, - Charset charset, TimeZone timeZone, - CodecProvider provider) - throws IOException - { - return open(mdbFile, readOnly, null, autoSync, charset, timeZone, - provider); - } - /** * Open an existing Database. If the existing file is not writeable or the * readOnly flag is {@code true}, the file will be opened read-only. @@ -639,7 +355,7 @@ public class Database * {@code null} if no special encoding is necessary * @usage _advanced_method_ */ - static Database open(File mdbFile, boolean readOnly, FileChannel channel, + static DatabaseImpl open(File mdbFile, boolean readOnly, FileChannel channel, boolean autoSync, Charset charset, TimeZone timeZone, CodecProvider provider) throws IOException @@ -673,7 +389,7 @@ public class Database } } - Database db = new Database(mdbFile, channel, closeChannel, autoSync, + DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync, null, charset, timeZone, provider); success = true; return db; @@ -690,120 +406,6 @@ public class Database } } - /** - * Create a new Access 2000 Database - *

- * Equivalent to: - * {@code create(FileFormat.V2000, mdbFile, DEFAULT_AUTO_SYNC);} - * - * @param mdbFile Location to write the new database to. If this file - * already exists, it will be overwritten. - * - * @see #create(File,boolean) - * @see DatabaseBuilder for more flexible Database creation - * @usage _general_method_ - */ - public static Database create(File mdbFile) throws IOException { - return create(mdbFile, DEFAULT_AUTO_SYNC); - } - - /** - * Create a new Database for the given fileFormat - *

- * Equivalent to: - * {@code create(fileFormat, mdbFile, DEFAULT_AUTO_SYNC);} - * - * @param fileFormat version of new database. - * @param mdbFile Location to write the new database to. If this file - * already exists, it will be overwritten. - * - * @see #create(File,boolean) - * @see DatabaseBuilder for more flexible Database creation - * @usage _general_method_ - */ - public static Database create(FileFormat fileFormat, File mdbFile) - throws IOException - { - return create(fileFormat, mdbFile, DEFAULT_AUTO_SYNC); - } - - /** - * Create a new Access 2000 Database - *

- * Equivalent to: - * {@code create(FileFormat.V2000, mdbFile, DEFAULT_AUTO_SYNC);} - * - * @param mdbFile Location to write the new database to. If this file - * already exists, it will be overwritten. - * @param autoSync whether or not to enable auto-syncing on write. if - * {@code true}, writes will be immediately flushed to disk. - * This leaves the database in a (fairly) consistent state - * on each write, but can be very inefficient for many - * updates. if {@code false}, flushing to disk happens at - * the jvm's leisure, which can be much faster, but may - * leave the database in an inconsistent state if failures - * are encountered during writing. Writes may be flushed at - * any time using {@link #flush}. - * @see DatabaseBuilder for more flexible Database creation - * @usage _general_method_ - */ - public static Database create(File mdbFile, boolean autoSync) - throws IOException - { - return create(FileFormat.V2000, mdbFile, autoSync); - } - - /** - * Create a new Database for the given fileFormat - * @param fileFormat version of new database. - * @param mdbFile Location to write the new database to. If this file - * already exists, it will be overwritten. - * @param autoSync whether or not to enable auto-syncing on write. if - * {@code true}, writes will be immediately flushed to disk. - * This leaves the database in a (fairly) consistent state - * on each write, but can be very inefficient for many - * updates. if {@code false}, flushing to disk happens at - * the jvm's leisure, which can be much faster, but may - * leave the database in an inconsistent state if failures - * are encountered during writing. Writes may be flushed at - * any time using {@link #flush}. - * @see DatabaseBuilder for more flexible Database creation - * @usage _general_method_ - */ - public static Database create(FileFormat fileFormat, File mdbFile, - boolean autoSync) - throws IOException - { - return create(fileFormat, mdbFile, autoSync, null, null); - } - - /** - * Create a new Database for the given fileFormat - * @param fileFormat version of new database. - * @param mdbFile Location to write the new database to. If this file - * already exists, it will be overwritten. - * @param autoSync whether or not to enable auto-syncing on write. if - * {@code true}, writes will be immediately flushed to disk. - * This leaves the database in a (fairly) consistent state - * on each write, but can be very inefficient for many - * updates. if {@code false}, flushing to disk happens at - * the jvm's leisure, which can be much faster, but may - * leave the database in an inconsistent state if failures - * are encountered during writing. Writes may be flushed at - * any time using {@link #flush}. - * @param charset Charset to use, if {@code null}, uses default - * @param timeZone TimeZone to use, if {@code null}, uses default - * @see DatabaseBuilder for more flexible Database creation - * @usage _intermediate_method_ - */ - public static Database create(FileFormat fileFormat, File mdbFile, - boolean autoSync, Charset charset, - TimeZone timeZone) - throws IOException - { - return create(fileFormat, mdbFile, null, autoSync, charset, timeZone); - } - /** * Create a new Database for the given fileFormat * @param fileFormat version of new database. @@ -824,7 +426,7 @@ public class Database * @param timeZone TimeZone to use, if {@code null}, uses default * @usage _advanced_method_ */ - static Database create(FileFormat fileFormat, File mdbFile, + static DatabaseImpl create(FileFormat fileFormat, File mdbFile, FileChannel channel, boolean autoSync, Charset charset, TimeZone timeZone) throws IOException @@ -844,7 +446,7 @@ public class Database channel.truncate(0); transferFrom(channel, getResourceAsStream(fileFormat._emptyFile)); channel.force(true); - Database db = new Database(mdbFile, channel, closeChannel, autoSync, + DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync, fileFormat, charset, timeZone, null); success = true; return db; @@ -899,7 +501,7 @@ public class Database * @param charset Charset to use, if {@code null}, uses default * @param timeZone TimeZone to use, if {@code null}, uses default */ - protected Database(File file, FileChannel channel, boolean closeChannel, + protected DatabaseImpl(File file, FileChannel channel, boolean closeChannel, boolean autoSync, FileFormat fileFormat, Charset charset, TimeZone timeZone, CodecProvider provider) throws IOException @@ -923,9 +525,7 @@ public class Database readSystemCatalog(); } - /** - * Returns the File underlying this Database - */ + @Override public File getFile() { return _file; } @@ -944,18 +544,12 @@ public class Database return _format; } - /** - * @return The system catalog table - * @usage _advanced_method_ - */ + @Override public Table getSystemCatalog() { return _systemCatalog; } - /** - * @return The system Access Control Entries table (loaded on demand) - * @usage _advanced_method_ - */ + @Override public Table getAccessControlEntries() throws IOException { if(_accessControlEntries == null) { _accessControlEntries = getSystemTable(TABLE_SYSTEM_ACES); @@ -982,85 +576,40 @@ public class Database } return _complexCols; } - - /** - * Whether or not big index support is enabled for tables. - * @usage _advanced_method_ - */ - public boolean doUseBigIndex() { - return (_useBigIndex != null ? _useBigIndex : true); - } - - /** - * Set whether or not big index support is enabled for tables. - * @usage _intermediate_method_ - */ - public void setUseBigIndex(boolean useBigIndex) { - _useBigIndex = useBigIndex; - } - /** - * Gets the currently configured ErrorHandler (always non-{@code null}). - * This will be used to handle all errors unless overridden at the Table or - * Cursor level. - * @usage _intermediate_method_ - */ + @Override public ErrorHandler getErrorHandler() { return((_dbErrorHandler != null) ? _dbErrorHandler : DEFAULT_ERROR_HANDLER); } - /** - * Sets a new ErrorHandler. If {@code null}, resets to the - * {@link #DEFAULT_ERROR_HANDLER}. - * @usage _intermediate_method_ - */ + @Override public void setErrorHandler(ErrorHandler newErrorHandler) { _dbErrorHandler = newErrorHandler; } - /** - * Gets the currently configured LinkResolver (always non-{@code null}). - * This will be used to handle all linked database loading. - * @usage _intermediate_method_ - */ + @Override public LinkResolver getLinkResolver() { return((_linkResolver != null) ? _linkResolver : DEFAULT_LINK_RESOLVER); } - /** - * Sets a new LinkResolver. If {@code null}, resets to the - * {@link #DEFAULT_LINK_RESOLVER}. - * @usage _intermediate_method_ - */ + @Override public void setLinkResolver(LinkResolver newLinkResolver) { _linkResolver = newLinkResolver; } - /** - * Returns an unmodifiable view of the currently loaded linked databases, - * mapped from the linked database file name to the linked database. This - * information may be useful for implementing a LinkResolver. - * @usage _intermediate_method_ - */ + @Override public Map getLinkedDatabases() { return ((_linkedDbs == null) ? Collections.emptyMap() : Collections.unmodifiableMap(_linkedDbs)); } - /** - * Gets currently configured TimeZone (always non-{@code null}). - * @usage _intermediate_method_ - */ + @Override public TimeZone getTimeZone() { return _timeZone; } - /** - * Sets a new TimeZone. If {@code null}, resets to the value returned by - * {@link #getDefaultTimeZone}. - * @usage _intermediate_method_ - */ + @Override public void setTimeZone(TimeZone newTimeZone) { if(newTimeZone == null) { newTimeZone = getDefaultTimeZone(); @@ -1070,20 +619,13 @@ public class Database _calendar = null; } - /** - * Gets currently configured Charset (always non-{@code null}). - * @usage _intermediate_method_ - */ + @Override public Charset getCharset() { return _charset; } - /** - * Sets a new Charset. If {@code null}, resets to the value returned by - * {@link #getDefaultCharset}. - * @usage _intermediate_method_ - */ + @Override public void setCharset(Charset newCharset) { if(newCharset == null) { newCharset = getDefaultCharset(getFormat()); @@ -1091,20 +633,12 @@ public class Database _charset = newCharset; } - /** - * Gets currently configured {@link Table.ColumnOrder} (always non-{@code - * null}). - * @usage _intermediate_method_ - */ + @Override public Table.ColumnOrder getColumnOrder() { return _columnOrder; } - /** - * Sets a new Table.ColumnOrder. If {@code null}, resets to the value - * returned by {@link #getDefaultColumnOrder}. - * @usage _intermediate_method_ - */ + @Override public void setColumnOrder(Table.ColumnOrder newColumnOrder) { if(newColumnOrder == null) { newColumnOrder = getDefaultColumnOrder(); @@ -1112,19 +646,12 @@ public class Database _columnOrder = newColumnOrder; } - /** - * Gets currently foreign-key enforcement policy. - * @usage _intermediate_method_ - */ + @Override public boolean isEnforceForeignKeys() { return _enforceForeignKeys; } - /** - * Sets a new foreign-key enforcement policy. If {@code null}, resets to - * the value returned by {@link #isEnforceForeignKeys}. - * @usage _intermediate_method_ - */ + @Override public void setEnforceForeignKeys(Boolean newEnforceForeignKeys) { if(newEnforceForeignKeys == null) { newEnforceForeignKeys = getDefaultEnforceForeignKeys(); @@ -1161,17 +688,12 @@ public class Database return _propsHandler; } - /** - * Returns the FileFormat of this database (which may involve inspecting the - * database itself). - * @throws IllegalStateException if the file format cannot be determined - * @usage _general_method_ - */ + @Override public FileFormat getFileFormat() throws IOException { if(_fileFormat == null) { - Map possibleFileFormats = + Map possibleFileFormats = getFormat().getPossibleFileFormats(); if(possibleFileFormats.size() == 1) { @@ -1282,7 +804,7 @@ public class Database */ private void readSystemCatalog() throws IOException { _systemCatalog = readTable(TABLE_SYSTEM_CATALOG, PAGE_SYSTEM_CATALOG, - SYSTEM_OBJECT_FLAGS, defaultUseBigIndex()); + SYSTEM_OBJECT_FLAGS); try { _tableFinder = new DefaultTableFinder( @@ -1313,10 +835,7 @@ public class Database } } - /** - * @return The names of all of the user tables (String) - * @usage _general_method_ - */ + @Override public Set getTableNames() throws IOException { if(_tableNames == null) { Set tableNames = @@ -1327,13 +846,7 @@ public class Database return _tableNames; } - /** - * @return The names of all of the system tables (String). Note, in order - * to read these tables, you must use {@link #getSystemTable}. - * Extreme care should be taken if modifying these tables - * directly!. - * @usage _intermediate_method_ - */ + @Override public Set getSystemTableNames() throws IOException { Set sysTableNames = new TreeSet(String.CASE_INSENSITIVE_ORDER); @@ -1341,37 +854,14 @@ public class Database return sysTableNames; } - /** - * @return an unmodifiable Iterator of the user Tables in this Database. - * @throws IllegalStateException if an IOException is thrown by one of the - * operations, the actual exception will be contained within - * @throws ConcurrentModificationException if a table is added to the - * database while an Iterator is in use. - * @usage _general_method_ - */ + @Override public Iterator

iterator() { return new TableIterator(); } - /** - * @param name Table name - * @return The table, or null if it doesn't exist - * @usage _general_method_ - */ + @Override public Table getTable(String name) throws IOException { - return getTable(name, defaultUseBigIndex()); - } - - /** - * @param name Table name - * @param useBigIndex whether or not "big index support" should be enabled - * for the table (this value will override any other - * settings) - * @return The table, or null if it doesn't exist - * @usage _intermediate_method_ - */ - public Table getTable(String name, boolean useBigIndex) throws IOException { - return getTable(name, false, useBigIndex); + return getTable(name, false); } /** @@ -1397,19 +887,15 @@ public class Database String name = (String)objectRow.get(CAT_COL_NAME); int flags = (Integer)objectRow.get(CAT_COL_FLAGS); - return readTable(name, tableDefPageNumber, flags, defaultUseBigIndex()); + return readTable(name, tableDefPageNumber, flags); } /** * @param name Table name * @param includeSystemTables whether to consider returning a system table - * @param useBigIndex whether or not "big index support" should be enabled - * for the table (this value will override any other - * settings) * @return The table, or null if it doesn't exist */ - private Table getTable(String name, boolean includeSystemTables, - boolean useBigIndex) + private Table getTable(String name, boolean includeSystemTables) throws IOException { TableInfo tableInfo = lookupTable(name); @@ -1435,12 +921,12 @@ public class Database _linkedDbs.put(linkedDbName, linkedDb); } - return linkedDb.getTable(linkedTableName, includeSystemTables, - useBigIndex); + return ((DatabaseImpl)linkedDb).getTable(linkedTableName, + includeSystemTables); } return readTable(tableInfo.tableName, tableInfo.pageNumber, - tableInfo.flags, useBigIndex); + tableInfo.flags); } /** @@ -1466,6 +952,7 @@ public class Database List indexes) throws IOException { + // FIXME, rework table creation if(lookupTable(name) != null) { throw new IllegalArgumentException( "Cannot create table with name of existing table"); @@ -1483,6 +970,7 @@ public class Database String linkedTableName) throws IOException { + // FIXME, rework table creation if(lookupTable(name) != null) { throw new IllegalArgumentException( "Cannot create linked table with name of existing table"); @@ -1517,10 +1005,7 @@ public class Database addToAccessControlEntries(tdefPageNumber); } - /** - * Finds all the relationships in the database between the given tables. - * @usage _intermediate_method_ - */ + @Override public List getRelationships(Table table1, Table table2) throws IOException { @@ -1557,12 +1042,8 @@ public class Database return relationships; } - /** - * Finds all the queries in the database. - * @usage _intermediate_method_ - */ - public List getQueries() - throws IOException + @Override + public List getQueries() throws IOException { // the queries table does not get loaded until first accessed if(_queries == null) { @@ -1612,29 +1093,13 @@ public class Database return queries; } - /** - * Returns a reference to any available table in this access - * database, including system tables. - *

- * Warning, this method is not designed for common use, only for the - * occassional time when access to a system table is necessary. Messing - * with system tables can strip the paint off your house and give your whole - * family a permanent, orange afro. You have been warned. - * - * @param tableName Table name, may be a system table - * @return The table, or {@code null} if it doesn't exist - * @usage _intermediate_method_ - */ - public Table getSystemTable(String tableName) - throws IOException + @Override + public Table getSystemTable(String tableName) throws IOException { - return getTable(tableName, true, defaultUseBigIndex()); + return getTable(tableName, true); } - /** - * @return the core properties for the database - * @usage _general_method_ - */ + @Override public PropertyMap getDatabaseProperties() throws IOException { if(_dbPropMaps == null) { _dbPropMaps = getPropertiesForDbObject(OBJECT_NAME_DB_PROPS); @@ -1642,10 +1107,7 @@ public class Database return _dbPropMaps.getDefault(); } - /** - * @return the summary properties for the database - * @usage _general_method_ - */ + @Override public PropertyMap getSummaryProperties() throws IOException { if(_summaryPropMaps == null) { _summaryPropMaps = getPropertiesForDbObject(OBJECT_NAME_SUMMARY_PROPS); @@ -1653,10 +1115,7 @@ public class Database return _summaryPropMaps.getDefault(); } - /** - * @return the user-defined properties for the database - * @usage _general_method_ - */ + @Override public PropertyMap getUserDefinedProperties() throws IOException { if(_userDefPropMaps == null) { _userDefPropMaps = getPropertiesForDbObject(OBJECT_NAME_USERDEF_PROPS); @@ -1706,10 +1165,7 @@ public class Database return readProperties(propsBytes, objectId); } - /** - * @return the current database password, or {@code null} if none set. - * @usage _general_method_ - */ + @Override public String getDatabasePassword() throws IOException { ByteBuffer buffer = takeSharedBuffer(); @@ -1905,8 +1361,7 @@ public class Database /** * Reads a table with the given name from the given pageNumber. */ - private Table readTable(String name, int pageNumber, int flags, - boolean useBigIndex) + private Table readTable(String name, int pageNumber, int flags) throws IOException { // first, check for existing table @@ -1926,7 +1381,7 @@ public class Database ", but page type is " + pageType); } return _tableCache.put( - new Table(this, buffer, pageNumber, name, flags, useBigIndex)); + new Table(this, buffer, pageNumber, name, flags)); } finally { releaseSharedBuffer(buffer); } @@ -1952,121 +1407,7 @@ public class Database return Cursor.createCursor(table); } - /** - * Copy an existing JDBC ResultSet into a new table in this database - * - * @param name Name of the new table to create - * @param source ResultSet to copy from - * - * @return the name of the copied table - * - * @see ImportUtil#importResultSet(ResultSet,Database,String) - * @usage _general_method_ - */ - public String copyTable(String name, ResultSet source) - throws SQLException, IOException - { - return ImportUtil.importResultSet(source, this, name); - } - - /** - * Copy an existing JDBC ResultSet into a new table in this database - * - * @param name Name of the new table to create - * @param source ResultSet to copy from - * @param filter valid import filter - * - * @return the name of the imported table - * - * @see ImportUtil#importResultSet(ResultSet,Database,String,ImportFilter) - * @usage _general_method_ - */ - public String copyTable(String name, ResultSet source, ImportFilter filter) - throws SQLException, IOException - { - return ImportUtil.importResultSet(source, this, name, filter); - } - - /** - * Copy a delimited text file into a new table in this database - * - * @param name Name of the new table to create - * @param f Source file to import - * @param delim Regular expression representing the delimiter string. - * - * @return the name of the imported table - * - * @see ImportUtil#importFile(File,Database,String,String) - * @usage _general_method_ - */ - public String importFile(String name, File f, String delim) - throws IOException - { - return ImportUtil.importFile(f, this, name, delim); - } - - /** - * Copy a delimited text file into a new table in this database - * - * @param name Name of the new table to create - * @param f Source file to import - * @param delim Regular expression representing the delimiter string. - * @param filter valid import filter - * - * @return the name of the imported table - * - * @see ImportUtil#importFile(File,Database,String,String,ImportFilter) - * @usage _general_method_ - */ - public String importFile(String name, File f, String delim, - ImportFilter filter) - throws IOException - { - return ImportUtil.importFile(f, this, name, delim, filter); - } - - /** - * Copy a delimited text file into a new table in this database - * - * @param name Name of the new table to create - * @param in Source reader to import - * @param delim Regular expression representing the delimiter string. - * - * @return the name of the imported table - * - * @see ImportUtil#importReader(BufferedReader,Database,String,String) - * @usage _general_method_ - */ - public String importReader(String name, BufferedReader in, String delim) - throws IOException - { - return ImportUtil.importReader(in, this, name, delim); - } - - /** - * Copy a delimited text file into a new table in this database - * @param name Name of the new table to create - * @param in Source reader to import - * @param delim Regular expression representing the delimiter string. - * @param filter valid import filter - * - * @return the name of the imported table - * - * @see ImportUtil#importReader(BufferedReader,Database,String,String,ImportFilter) - * @usage _general_method_ - */ - public String importReader(String name, BufferedReader in, String delim, - ImportFilter filter) - throws IOException - { - return ImportUtil.importReader(in, this, name, delim, filter); - } - - /** - * Flushes any current changes to the database file (and any linked - * databases) to disk. - * @usage _general_method_ - */ + @Override public void flush() throws IOException { if(_linkedDbs != null) { for(Database linkedDb : _linkedDbs.values()) { @@ -2076,10 +1417,7 @@ public class Database _pageChannel.flush(); } - /** - * Close the database file (and any linked databases) - * @usage _general_method_ - */ + @Override public void close() throws IOException { if(_linkedDbs != null) { for(Database linkedDb : _linkedDbs.values()) { @@ -2196,22 +1534,6 @@ public class Database return ((flags & SYSTEM_OBJECT_FLAGS) != 0); } - /** - * Returns {@code false} if "big index support" has been disabled explicity - * on the this Database or via a system property, {@code true} otherwise. - * @usage _advanced_method_ - */ - public boolean defaultUseBigIndex() { - if(_useBigIndex != null) { - return _useBigIndex; - } - String prop = System.getProperty(USE_BIG_INDEX_PROPERTY); - if(prop != null) { - return Boolean.TRUE.toString().equalsIgnoreCase(prop); - } - return true; - } - /** * Returns the default TimeZone. This is normally the platform default * TimeZone as returned by {@link TimeZone#getDefault}, but can be @@ -2277,7 +1599,7 @@ public class Database /** * Returns the default enforce foreign-keys policy. This defaults to - * {@code false}, but can be overridden using the system + * {@code true}, but can be overridden using the system * property {@value #FK_ENFORCE_PROPERTY}. * @usage _advanced_method_ */ @@ -2287,7 +1609,7 @@ public class Database if(prop != null) { return Boolean.TRUE.toString().equalsIgnoreCase(prop); } - return false; + return true; } /** @@ -2338,7 +1660,7 @@ public class Database static InputStream getResourceAsStream(String resourceName) throws IOException { - InputStream stream = Database.class.getClassLoader() + InputStream stream = DatabaseImpl.class.getClassLoader() .getResourceAsStream(resourceName); if(stream == null) { diff --git a/src/java/com/healthmarketscience/jackcess/ExportUtil.java b/src/java/com/healthmarketscience/jackcess/ExportUtil.java index ad8d502..7ee1c35 100644 --- a/src/java/com/healthmarketscience/jackcess/ExportUtil.java +++ b/src/java/com/healthmarketscience/jackcess/ExportUtil.java @@ -70,7 +70,7 @@ public class ExportUtil { * @see #exportAll(Database,File,String) * @see Builder */ - public static void exportAll(Database db, File dir) + public static void exportAll(DatabaseImpl db, File dir) throws IOException { exportAll(db, dir, DEFAULT_FILE_EXT); } @@ -90,7 +90,7 @@ public class ExportUtil { * @see #exportFile(Database,String,File,boolean,String,char,ExportFilter) * @see Builder */ - public static void exportAll(Database db, File dir, + public static void exportAll(DatabaseImpl db, File dir, String ext) throws IOException { for (String tableName : db.getTableNames()) { exportFile(db, tableName, new File(dir, tableName + "." + ext), false, @@ -115,7 +115,7 @@ public class ExportUtil { * @see #exportFile(Database,String,File,boolean,String,char,ExportFilter) * @see Builder */ - public static void exportAll(Database db, File dir, + public static void exportAll(DatabaseImpl db, File dir, String ext, boolean header) throws IOException { for (String tableName : db.getTableNames()) { @@ -147,7 +147,7 @@ public class ExportUtil { * @see #exportFile(Database,String,File,boolean,String,char,ExportFilter) * @see Builder */ - public static void exportAll(Database db, File dir, + public static void exportAll(DatabaseImpl db, File dir, String ext, boolean header, String delim, char quote, ExportFilter filter) throws IOException { @@ -172,7 +172,7 @@ public class ExportUtil { * @see #exportFile(Database,String,File,boolean,String,char,ExportFilter) * @see Builder */ - public static void exportFile(Database db, String tableName, + public static void exportFile(DatabaseImpl db, String tableName, File f) throws IOException { exportFile(db, tableName, f, false, DEFAULT_DELIMITER, DEFAULT_QUOTE_CHAR, SimpleExportFilter.INSTANCE); @@ -201,7 +201,7 @@ public class ExportUtil { * @see #exportWriter(Database,String,BufferedWriter,boolean,String,char,ExportFilter) * @see Builder */ - public static void exportFile(Database db, String tableName, + public static void exportFile(DatabaseImpl db, String tableName, File f, boolean header, String delim, char quote, ExportFilter filter) throws IOException { BufferedWriter out = null; @@ -235,7 +235,7 @@ public class ExportUtil { * @see #exportWriter(Database,String,BufferedWriter,boolean,String,char,ExportFilter) * @see Builder */ - public static void exportWriter(Database db, String tableName, + public static void exportWriter(DatabaseImpl db, String tableName, BufferedWriter out) throws IOException { exportWriter(db, tableName, out, false, DEFAULT_DELIMITER, DEFAULT_QUOTE_CHAR, SimpleExportFilter.INSTANCE); @@ -263,7 +263,7 @@ public class ExportUtil { * @see #exportWriter(Cursor,BufferedWriter,boolean,String,char,ExportFilter) * @see Builder */ - public static void exportWriter(Database db, String tableName, + public static void exportWriter(DatabaseImpl db, String tableName, BufferedWriter out, boolean header, String delim, char quote, ExportFilter filter) throws IOException @@ -406,7 +406,7 @@ public class ExportUtil { */ public static class Builder { - private Database _db; + private DatabaseImpl _db; private String _tableName; private String _ext = DEFAULT_FILE_EXT; private Cursor _cursor; @@ -415,11 +415,11 @@ public class ExportUtil { private ExportFilter _filter = SimpleExportFilter.INSTANCE; private boolean _header; - public Builder(Database db) { + public Builder(DatabaseImpl db) { this(db, null); } - public Builder(Database db, String tableName) { + public Builder(DatabaseImpl db, String tableName) { _db = db; _tableName = tableName; } @@ -428,7 +428,7 @@ public class ExportUtil { _cursor = cursor; } - public Builder setDatabase(Database db) { + public Builder setDatabase(DatabaseImpl db) { _db = db; return this; } diff --git a/src/java/com/healthmarketscience/jackcess/GeneralIndexCodes.java b/src/java/com/healthmarketscience/jackcess/GeneralIndexCodes.java index 6e11c60..9cf3bb3 100644 --- a/src/java/com/healthmarketscience/jackcess/GeneralIndexCodes.java +++ b/src/java/com/healthmarketscience/jackcess/GeneralIndexCodes.java @@ -31,9 +31,9 @@ public class GeneralIndexCodes extends GeneralLegacyIndexCodes { // stash the codes in some resource files private static final String CODES_FILE = - Database.RESOURCE_PATH + "index_codes_gen.txt"; + DatabaseImpl.RESOURCE_PATH + "index_codes_gen.txt"; private static final String EXT_CODES_FILE = - Database.RESOURCE_PATH + "index_codes_ext_gen.txt"; + DatabaseImpl.RESOURCE_PATH + "index_codes_ext_gen.txt"; private static final class Codes { diff --git a/src/java/com/healthmarketscience/jackcess/GeneralLegacyIndexCodes.java b/src/java/com/healthmarketscience/jackcess/GeneralLegacyIndexCodes.java index e6d204c..6ddd62d 100644 --- a/src/java/com/healthmarketscience/jackcess/GeneralLegacyIndexCodes.java +++ b/src/java/com/healthmarketscience/jackcess/GeneralLegacyIndexCodes.java @@ -75,9 +75,9 @@ public class GeneralLegacyIndexCodes { // stash the codes in some resource files private static final String CODES_FILE = - Database.RESOURCE_PATH + "index_codes_genleg.txt"; + DatabaseImpl.RESOURCE_PATH + "index_codes_genleg.txt"; private static final String EXT_CODES_FILE = - Database.RESOURCE_PATH + "index_codes_ext_genleg.txt"; + DatabaseImpl.RESOURCE_PATH + "index_codes_ext_genleg.txt"; /** * Enum which classifies the types of char encoding strategies used when @@ -326,7 +326,7 @@ public class GeneralLegacyIndexCodes { reader = new BufferedReader( new InputStreamReader( - Database.getResourceAsStream(codesFilePath), "US-ASCII")); + DatabaseImpl.getResourceAsStream(codesFilePath), "US-ASCII")); int start = asUnsignedChar(firstChar); int end = asUnsignedChar(lastChar); diff --git a/src/java/com/healthmarketscience/jackcess/ImportUtil.java b/src/java/com/healthmarketscience/jackcess/ImportUtil.java index 0fc1802..b3ccb94 100644 --- a/src/java/com/healthmarketscience/jackcess/ImportUtil.java +++ b/src/java/com/healthmarketscience/jackcess/ImportUtil.java @@ -74,7 +74,7 @@ public class ImportUtil List columns = new LinkedList(); for (int i = 1; i <= md.getColumnCount(); i++) { Column column = new Column(); - column.setName(Database.escapeIdentifier(md.getColumnName(i))); + column.setName(DatabaseImpl.escapeIdentifier(md.getColumnName(i))); int lengthInUnits = md.getColumnDisplaySize(i); column.setSQLType(md.getColumnType(i), lengthInUnits); DataType type = column.getType(); @@ -113,7 +113,7 @@ public class ImportUtil * @see #importResultSet(ResultSet,Database,String,ImportFilter) * @see Builder */ - public static String importResultSet(ResultSet source, Database db, + public static String importResultSet(ResultSet source, DatabaseImpl db, String name) throws SQLException, IOException { @@ -135,7 +135,7 @@ public class ImportUtil * @see #importResultSet(ResultSet,Database,String,ImportFilter,boolean) * @see Builder */ - public static String importResultSet(ResultSet source, Database db, + public static String importResultSet(ResultSet source, DatabaseImpl db, String name, ImportFilter filter) throws SQLException, IOException { @@ -157,14 +157,14 @@ public class ImportUtil * * @see Builder */ - public static String importResultSet(ResultSet source, Database db, + public static String importResultSet(ResultSet source, DatabaseImpl db, String name, ImportFilter filter, boolean useExistingTable) throws SQLException, IOException { ResultSetMetaData md = source.getMetaData(); - name = Database.escapeIdentifier(name); + name = DatabaseImpl.escapeIdentifier(name); Table table = null; if(!useExistingTable || ((table = db.getTable(name)) == null)) { List columns = toColumns(md); @@ -211,7 +211,7 @@ public class ImportUtil * @see #importFile(File,Database,String,String,ImportFilter) * @see Builder */ - public static String importFile(File f, Database db, String name, + public static String importFile(File f, DatabaseImpl db, String name, String delim) throws IOException { @@ -234,7 +234,7 @@ public class ImportUtil * @see #importReader(BufferedReader,Database,String,String,ImportFilter) * @see Builder */ - public static String importFile(File f, Database db, String name, + public static String importFile(File f, DatabaseImpl db, String name, String delim, ImportFilter filter) throws IOException { @@ -262,7 +262,7 @@ public class ImportUtil * @see #importReader(BufferedReader,Database,String,String,ImportFilter,boolean) * @see Builder */ - public static String importFile(File f, Database db, String name, + public static String importFile(File f, DatabaseImpl db, String name, String delim, char quote, ImportFilter filter, boolean useExistingTable) @@ -292,7 +292,7 @@ public class ImportUtil * @see #importReader(BufferedReader,Database,String,String,char,ImportFilter,boolean,boolean) * @see Builder */ - public static String importFile(File f, Database db, String name, + public static String importFile(File f, DatabaseImpl db, String name, String delim, char quote, ImportFilter filter, boolean useExistingTable, @@ -330,7 +330,7 @@ public class ImportUtil * @see #importReader(BufferedReader,Database,String,String,ImportFilter) * @see Builder */ - public static String importReader(BufferedReader in, Database db, + public static String importReader(BufferedReader in, DatabaseImpl db, String name, String delim) throws IOException { @@ -353,7 +353,7 @@ public class ImportUtil * @see #importReader(BufferedReader,Database,String,String,ImportFilter,boolean) * @see Builder */ - public static String importReader(BufferedReader in, Database db, + public static String importReader(BufferedReader in, DatabaseImpl db, String name, String delim, ImportFilter filter) throws IOException @@ -380,7 +380,7 @@ public class ImportUtil * * @see Builder */ - public static String importReader(BufferedReader in, Database db, + public static String importReader(BufferedReader in, DatabaseImpl db, String name, String delim, ImportFilter filter, boolean useExistingTable) @@ -410,7 +410,7 @@ public class ImportUtil * * @see Builder */ - public static String importReader(BufferedReader in, Database db, + public static String importReader(BufferedReader in, DatabaseImpl db, String name, String delim, char quote, ImportFilter filter, boolean useExistingTable) @@ -439,7 +439,7 @@ public class ImportUtil * * @see Builder */ - public static String importReader(BufferedReader in, Database db, + public static String importReader(BufferedReader in, DatabaseImpl db, String name, String delim, char quote, ImportFilter filter, boolean useExistingTable, boolean header) @@ -453,7 +453,7 @@ public class ImportUtil Pattern delimPat = Pattern.compile(delim); try { - name = Database.escapeIdentifier(name); + name = DatabaseImpl.escapeIdentifier(name); Table table = null; if(!useExistingTable || ((table = db.getTable(name)) == null)) { @@ -590,7 +590,7 @@ public class ImportUtil /** * Returns a new table with a unique name and the given table definition. */ - private static Table createUniqueTable(Database db, String name, + private static Table createUniqueTable(DatabaseImpl db, String name, List columns, ResultSetMetaData md, ImportFilter filter) @@ -613,7 +613,7 @@ public class ImportUtil */ public static class Builder { - private Database _db; + private DatabaseImpl _db; private String _tableName; private String _delim = ExportUtil.DEFAULT_DELIMITER; private char _quote = ExportUtil.DEFAULT_QUOTE_CHAR; @@ -621,16 +621,16 @@ public class ImportUtil private boolean _useExistingTable; private boolean _header = true; - public Builder(Database db) { + public Builder(DatabaseImpl db) { this(db, null); } - public Builder(Database db, String tableName) { + public Builder(DatabaseImpl db, String tableName) { _db = db; _tableName = tableName; } - public Builder setDatabase(Database db) { + public Builder setDatabaseImpl(DatabaseImpl db) { _db = db; return this; } diff --git a/src/java/com/healthmarketscience/jackcess/IndexData.java b/src/java/com/healthmarketscience/jackcess/IndexData.java index 2c24a2d..e3d508c 100644 --- a/src/java/com/healthmarketscience/jackcess/IndexData.java +++ b/src/java/com/healthmarketscience/jackcess/IndexData.java @@ -51,7 +51,7 @@ import static com.healthmarketscience.jackcess.ByteUtil.ByteStream; * * @author Tim McCune */ -public abstract class IndexData { +public class IndexData { protected static final Log LOG = LogFactory.getLog(Index.class); @@ -70,6 +70,8 @@ public abstract class IndexData { /** special object which will always be greater than any other value, when searching for an index entry range in a multi-value index */ public static final Object MIN_VALUE = new Object(); + + private static final DataPage NEW_ROOT_DATA_PAGE = new RootDataPage(); protected static final int INVALID_INDEX_PAGE_NUMBER = 0; @@ -176,6 +178,8 @@ public abstract class IndexData { private boolean _primaryKey; /** FIXME, for SimpleIndex, we can't write multi-page indexes or indexes using the entry compression scheme */ private boolean _readOnly; + /** Cache which manages the index pages */ + private final IndexPageCache _pageCache; protected IndexData(Table table, int number, int uniqueEntryCount, int uniqueEntryCountOffset) @@ -185,6 +189,7 @@ public abstract class IndexData { _uniqueEntryCount = uniqueEntryCount; _uniqueEntryCountOffset = uniqueEntryCountOffset; _maxPageEntrySize = calcMaxPageEntrySize(_table.getFormat()); + _pageCache = new IndexPageCache(this); } /** @@ -200,11 +205,7 @@ public abstract class IndexData { (number * format.SIZE_INDEX_DEFINITION) + 4); int uniqueEntryCount = tableBuffer.getInt(uniqueEntryCountOffset); - return(table.doUseBigIndex() ? - new BigIndexData(table, number, uniqueEntryCount, - uniqueEntryCountOffset) : - new SimpleIndexData(table, number, uniqueEntryCount, - uniqueEntryCountOffset)); + return new IndexData(table, number, uniqueEntryCount, uniqueEntryCountOffset); } public Table getTable() { @@ -341,6 +342,13 @@ public abstract class IndexData { _ownedPages.addPageNumber(pageNumber); } + /** + * Used by unit tests to validate the internal status of the index. + */ + void validate() throws IOException { + _pageCache.validate(); + } + /** * Returns the number of index entries in the index. Only called by unit * tests. @@ -367,7 +375,7 @@ public abstract class IndexData { */ public void initialize() throws IOException { if(!_initialized) { - readIndexEntries(); + _pageCache.setRootPageNumber(getRootPageNumber()); _initialized = true; } } @@ -386,7 +394,7 @@ public abstract class IndexData { throw new UnsupportedOperationException( "FIXME cannot write indexes of this type yet, see Database javadoc for info on enabling large index support"); } - updateImpl(); + _pageCache.write(); } /** @@ -455,7 +463,7 @@ public abstract class IndexData { throws IOException { ByteBuffer rootPageBuffer = creator.getPageChannel().createPageBuffer(); - writeDataPage(rootPageBuffer, SimpleIndexData.NEW_ROOT_DATA_PAGE, + writeDataPage(rootPageBuffer, NEW_ROOT_DATA_PAGE, creator.getTdefPageNumber(), creator.getFormat()); for(IndexBuilder idx : creator.getIndexes()) { @@ -855,6 +863,7 @@ public abstract class IndexData { throw new RuntimeException(e); } } + rtn.append("\n").append(_pageCache.toString()); return rtn.toString(); } @@ -865,10 +874,6 @@ public abstract class IndexData { throws IOException { if(dataPage.getCompressedEntrySize() > _maxPageEntrySize) { - if(this instanceof SimpleIndexData) { - throw new UnsupportedOperationException( - "FIXME cannot write large index yet, see Database javadoc for info on enabling large index support"); - } throw new IllegalStateException("data page is too large"); } @@ -1115,30 +1120,24 @@ public abstract class IndexData { return _entryBuffer.toByteArray(); } - - /** - * Writes the current index state to the database. Index has already been - * initialized. - */ - protected abstract void updateImpl() throws IOException; - - /** - * Reads the actual index entries. - */ - protected abstract void readIndexEntries() - throws IOException; /** * Finds the data page for the given entry. */ - protected abstract DataPage findDataPage(Entry entry) - throws IOException; + protected DataPage findDataPage(Entry entry) + throws IOException + { + return _pageCache.findCacheDataPage(entry); + } /** * Gets the data page for the pageNumber. */ - protected abstract DataPage getDataPage(int pageNumber) - throws IOException; + protected DataPage getDataPage(int pageNumber) + throws IOException + { + return _pageCache.getCacheDataPage(pageNumber); + } /** * Flips the first bit in the byte at the given index. @@ -2375,5 +2374,52 @@ public abstract class IndexData { } } + /** + * Simple implementation of a DataPage + */ + private static final class RootDataPage extends DataPage { + + @Override + public int getPageNumber() { return 0; } + + @Override + public boolean isLeaf() { return true; } + @Override + public void setLeaf(boolean isLeaf) { } + + @Override + public int getPrevPageNumber() { return 0; } + @Override + public void setPrevPageNumber(int pageNumber) { } + + @Override + public int getNextPageNumber() { return 0; } + @Override + public void setNextPageNumber(int pageNumber) { } + + @Override + public int getChildTailPageNumber() { return 0; } + @Override + public void setChildTailPageNumber(int pageNumber) { } + + @Override + public int getTotalEntrySize() { return 0; } + @Override + public void setTotalEntrySize(int totalSize) { } + + @Override + public byte[] getEntryPrefix() { return EMPTY_PREFIX; } + @Override + public void setEntryPrefix(byte[] entryPrefix) { } + + @Override + public List getEntries() { return Collections.emptyList(); } + @Override + public void setEntries(List entries) { } + @Override + public void addEntry(int idx, Entry entry) { } + @Override + public void removeEntry(int idx) { } + } } diff --git a/src/java/com/healthmarketscience/jackcess/IndexPageCache.java b/src/java/com/healthmarketscience/jackcess/IndexPageCache.java index 56cb44a..3703c1b 100644 --- a/src/java/com/healthmarketscience/jackcess/IndexPageCache.java +++ b/src/java/com/healthmarketscience/jackcess/IndexPageCache.java @@ -43,7 +43,7 @@ import java.util.RandomAccess; import static com.healthmarketscience.jackcess.IndexData.*; /** - * Manager of the index pages for a BigIndex. + * Manager of the index pages for a IndexData. * @author James Ahlborn */ public class IndexPageCache @@ -53,7 +53,7 @@ public class IndexPageCache } /** the index whose pages this cache is managing */ - private final BigIndexData _indexData; + private final IndexData _indexData; /** the root page for the index */ private DataPageMain _rootPage; /** the currently loaded pages for this index, pageNumber -> page */ @@ -63,11 +63,11 @@ public class IndexPageCache private final List _modifiedPages = new ArrayList(); - public IndexPageCache(BigIndexData indexData) { + public IndexPageCache(IndexData indexData) { _indexData = indexData; } - public BigIndexData getIndexData() { + public IndexData getIndexData() { return _indexData; } diff --git a/src/java/com/healthmarketscience/jackcess/JetFormat.java b/src/java/com/healthmarketscience/jackcess/JetFormat.java index 2a37120..28e618c 100644 --- a/src/java/com/healthmarketscience/jackcess/JetFormat.java +++ b/src/java/com/healthmarketscience/jackcess/JetFormat.java @@ -115,24 +115,24 @@ public abstract class JetFormat { // use nested inner class to avoid problematic static init loops private static final class PossibleFileFormats { - private static final Map POSSIBLE_VERSION_3 = - Collections.singletonMap((String)null, Database.FileFormat.V1997); + private static final Map POSSIBLE_VERSION_3 = + Collections.singletonMap((String)null, DatabaseImpl.FileFormat.V1997); - private static final Map POSSIBLE_VERSION_4 = - new HashMap(); + private static final Map POSSIBLE_VERSION_4 = + new HashMap(); - private static final Map POSSIBLE_VERSION_12 = - Collections.singletonMap((String)null, Database.FileFormat.V2007); + private static final Map POSSIBLE_VERSION_12 = + Collections.singletonMap((String)null, DatabaseImpl.FileFormat.V2007); - private static final Map POSSIBLE_VERSION_14 = - Collections.singletonMap((String)null, Database.FileFormat.V2010); + private static final Map POSSIBLE_VERSION_14 = + Collections.singletonMap((String)null, DatabaseImpl.FileFormat.V2010); - private static final Map POSSIBLE_VERSION_MSISAM = - Collections.singletonMap((String)null, Database.FileFormat.MSISAM); + private static final Map POSSIBLE_VERSION_MSISAM = + Collections.singletonMap((String)null, DatabaseImpl.FileFormat.MSISAM); static { - POSSIBLE_VERSION_4.put(ACCESS_VERSION_2000, Database.FileFormat.V2000); - POSSIBLE_VERSION_4.put(ACCESS_VERSION_2003, Database.FileFormat.V2003); + POSSIBLE_VERSION_4.put(ACCESS_VERSION_2000, DatabaseImpl.FileFormat.V2000); + POSSIBLE_VERSION_4.put(ACCESS_VERSION_2003, DatabaseImpl.FileFormat.V2003); } } @@ -494,7 +494,7 @@ public abstract class JetFormat { protected abstract boolean defineLegacyNumericIndexes(); - protected abstract Map getPossibleFileFormats(); + protected abstract Map getPossibleFileFormats(); protected abstract boolean isSupportedDataType(DataType type); @@ -708,7 +708,7 @@ public abstract class JetFormat { } @Override - protected Map getPossibleFileFormats() + protected Map getPossibleFileFormats() { return PossibleFileFormats.POSSIBLE_VERSION_3; } @@ -926,7 +926,7 @@ public abstract class JetFormat { } @Override - protected Map getPossibleFileFormats() + protected Map getPossibleFileFormats() { return PossibleFileFormats.POSSIBLE_VERSION_4; } @@ -948,7 +948,7 @@ public abstract class JetFormat { } @Override - protected Map getPossibleFileFormats() + protected Map getPossibleFileFormats() { return PossibleFileFormats.POSSIBLE_VERSION_MSISAM; } @@ -973,7 +973,7 @@ public abstract class JetFormat { protected boolean defineLegacyNumericIndexes() { return false; } @Override - protected Map getPossibleFileFormats() { + protected Map getPossibleFileFormats() { return PossibleFileFormats.POSSIBLE_VERSION_12; } @@ -1000,7 +1000,7 @@ public abstract class JetFormat { } @Override - protected Map getPossibleFileFormats() { + protected Map getPossibleFileFormats() { return PossibleFileFormats.POSSIBLE_VERSION_14; } } diff --git a/src/java/com/healthmarketscience/jackcess/MemFileChannel.java b/src/java/com/healthmarketscience/jackcess/MemFileChannel.java index 719a793..503c439 100644 --- a/src/java/com/healthmarketscience/jackcess/MemFileChannel.java +++ b/src/java/com/healthmarketscience/jackcess/MemFileChannel.java @@ -93,7 +93,7 @@ public class MemFileChannel extends FileChannel * affect the original File source. */ public static MemFileChannel newChannel(File file) throws IOException { - return newChannel(file, Database.RW_CHANNEL_MODE); + return newChannel(file, DatabaseImpl.RW_CHANNEL_MODE); } /** @@ -109,7 +109,7 @@ public class MemFileChannel extends FileChannel FileChannel in = null; try { return newChannel(in = new RandomAccessFile( - file, Database.RO_CHANNEL_MODE).getChannel(), + file, DatabaseImpl.RO_CHANNEL_MODE).getChannel(), mode); } finally { if(in != null) { @@ -127,7 +127,7 @@ public class MemFileChannel extends FileChannel * given InputStream. */ public static MemFileChannel newChannel(InputStream in) throws IOException { - return newChannel(in, Database.RW_CHANNEL_MODE); + return newChannel(in, DatabaseImpl.RW_CHANNEL_MODE); } /** @@ -148,7 +148,7 @@ public class MemFileChannel extends FileChannel public static MemFileChannel newChannel(ReadableByteChannel in) throws IOException { - return newChannel(in, Database.RW_CHANNEL_MODE); + return newChannel(in, DatabaseImpl.RW_CHANNEL_MODE); } /** diff --git a/src/java/com/healthmarketscience/jackcess/PageChannel.java b/src/java/com/healthmarketscience/jackcess/PageChannel.java index cd2a03c..fb02d1f 100644 --- a/src/java/com/healthmarketscience/jackcess/PageChannel.java +++ b/src/java/com/healthmarketscience/jackcess/PageChannel.java @@ -99,7 +99,7 @@ public class PageChannel implements Channel, Flushable { /** * Does second-stage initialization, must be called after construction. */ - public void initialize(Database database, CodecProvider codecProvider) + public void initialize(DatabaseImpl database, CodecProvider codecProvider) throws IOException { // initialize page en/decoding support diff --git a/src/java/com/healthmarketscience/jackcess/PropertyMap.java b/src/java/com/healthmarketscience/jackcess/PropertyMap.java index dc25dc0..e6c5b25 100644 --- a/src/java/com/healthmarketscience/jackcess/PropertyMap.java +++ b/src/java/com/healthmarketscience/jackcess/PropertyMap.java @@ -77,7 +77,7 @@ public class PropertyMap implements Iterable * @return the property with the given name, if any */ public Property get(String name) { - return _props.get(Database.toLookupName(name)); + return _props.get(DatabaseImpl.toLookupName(name)); } /** @@ -104,7 +104,7 @@ public class PropertyMap implements Iterable * Puts a property into this map with the given information. */ public void put(String name, DataType type, byte flag, Object value) { - _props.put(Database.toLookupName(name), + _props.put(DatabaseImpl.toLookupName(name), new Property(name, type, flag, value)); } diff --git a/src/java/com/healthmarketscience/jackcess/PropertyMaps.java b/src/java/com/healthmarketscience/jackcess/PropertyMaps.java index 51853ee..c40f1f3 100644 --- a/src/java/com/healthmarketscience/jackcess/PropertyMaps.java +++ b/src/java/com/healthmarketscience/jackcess/PropertyMaps.java @@ -85,7 +85,7 @@ public class PropertyMaps implements Iterable * creating if necessary */ private PropertyMap get(String name, short type) { - String lookupName = Database.toLookupName(name); + String lookupName = DatabaseImpl.toLookupName(name); PropertyMap map = _maps.get(lookupName); if(map == null) { map = new PropertyMap(name, type); @@ -98,7 +98,7 @@ public class PropertyMaps implements Iterable * Adds the given PropertyMap to this group. */ public void put(PropertyMap map) { - _maps.put(Database.toLookupName(map.getName()), map); + _maps.put(DatabaseImpl.toLookupName(map.getName()), map); } public Iterator iterator() { @@ -123,12 +123,12 @@ public class PropertyMaps implements Iterable static final class Handler { /** the current database */ - private final Database _database; + private final DatabaseImpl _database; /** cache of PropColumns used to read/write property values */ private final Map _columns = new HashMap(); - Handler(Database database) { + Handler(DatabaseImpl database) { _database = database; } @@ -305,7 +305,7 @@ public class PropertyMaps implements Iterable private class PropColumn extends Column { @Override - public Database getDatabase() { + public DatabaseImpl getDatabase() { return _database; } } diff --git a/src/java/com/healthmarketscience/jackcess/SimpleIndexData.java b/src/java/com/healthmarketscience/jackcess/SimpleIndexData.java deleted file mode 100644 index 7a662e7..0000000 --- a/src/java/com/healthmarketscience/jackcess/SimpleIndexData.java +++ /dev/null @@ -1,241 +0,0 @@ -/* -Copyright (c) 2008 Health Market Science, Inc. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -USA - -You can contact Health Market Science at info@healthmarketscience.com -or at the following address: - -Health Market Science -2700 Horizon Drive -Suite 200 -King of Prussia, PA 19406 -*/ - -package com.healthmarketscience.jackcess; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; - - -/** - * Simple implementation of an Access table index - * @author Tim McCune - */ -public class SimpleIndexData extends IndexData -{ - - static final DataPage NEW_ROOT_DATA_PAGE = - new SimpleDataPage(0, true, Collections.emptyList()); - - - /** data for the single index page. if this data came from multiple pages, - the index is read-only. */ - private SimpleDataPage _dataPage; - - public SimpleIndexData(Table table, int number, int uniqueEntryCount, - int uniqueEntryCountOffset) - { - super(table, number, uniqueEntryCount, uniqueEntryCountOffset); - } - - @Override - protected void updateImpl() throws IOException { - writeDataPage(_dataPage); - } - - @Override - protected void readIndexEntries() - throws IOException - { - // find first leaf page - int nextPageNumber = getRootPageNumber(); - SimpleDataPage indexPage = null; - while(true) { - indexPage = new SimpleDataPage(nextPageNumber); - readDataPage(indexPage); - - if(!indexPage.isLeaf()) { - // FIXME we can't modify this index at this point in time - setReadOnly(); - - // found another node page - if(!indexPage.getEntries().isEmpty()) { - nextPageNumber = indexPage.getEntries().get(0).getSubPageNumber(); - } else { - // try tail page - nextPageNumber = indexPage.getChildTailPageNumber(); - } - indexPage = null; - } else { - // found first leaf - break; - } - } - - // save the first leaf page - _dataPage = indexPage; - nextPageNumber = indexPage.getNextPageNumber(); - _dataPage.setNextPageNumber(INVALID_INDEX_PAGE_NUMBER); - indexPage = null; - - // read all leaf pages. - while(nextPageNumber != INVALID_INDEX_PAGE_NUMBER) { - - // FIXME we can't modify this index at this point in time - setReadOnly(); - - // found another one - indexPage = new SimpleDataPage(nextPageNumber); - readDataPage(indexPage); - - // since we read all the entries in sort order, we can insert them - // directly into the entries list - _dataPage.getEntries().addAll(indexPage.getEntries()); - int totalSize = (_dataPage.getTotalEntrySize() + - indexPage.getTotalEntrySize()); - _dataPage.setTotalEntrySize(totalSize); - nextPageNumber = indexPage.getNextPageNumber(); - } - - // check the entry order, just to be safe - List entries = _dataPage.getEntries(); - for(int i = 0; i < (entries.size() - 1); ++i) { - Entry e1 = entries.get(i); - Entry e2 = entries.get(i + 1); - if(e1.compareTo(e2) > 0) { - throw new IOException("Unexpected order in index entries, " + - e1 + " is greater than " + e2); - } - } - } - - @Override - protected DataPage findDataPage(Entry entry) - throws IOException - { - return _dataPage; - } - - @Override - protected DataPage getDataPage(int pageNumber) - throws IOException - { - throw new UnsupportedOperationException(); - } - - /** - * Simple implementation of a DataPage - */ - private static final class SimpleDataPage extends DataPage { - private final int _pageNumber; - private boolean _leaf; - private int _nextPageNumber; - private int _totalEntrySize; - private int _childTailPageNumber; - private List _entries; - - private SimpleDataPage(int pageNumber) { - this(pageNumber, false, null); - } - - private SimpleDataPage(int pageNumber, boolean leaf, List entries) - { - _pageNumber = pageNumber; - _leaf = leaf; - _entries = entries; - } - - @Override - public int getPageNumber() { - return _pageNumber; - } - - @Override - public boolean isLeaf() { - return _leaf; - } - @Override - public void setLeaf(boolean isLeaf) { - _leaf = isLeaf; - } - - @Override - public int getPrevPageNumber() { return 0; } - @Override - public void setPrevPageNumber(int pageNumber) { - // ignored - } - @Override - public int getNextPageNumber() { - return _nextPageNumber; - } - @Override - public void setNextPageNumber(int pageNumber) { - _nextPageNumber = pageNumber; - } - @Override - public int getChildTailPageNumber() { - return _childTailPageNumber; - } - @Override - public void setChildTailPageNumber(int pageNumber) { - _childTailPageNumber = pageNumber; - } - - @Override - public int getTotalEntrySize() { - return _totalEntrySize; - } - @Override - public void setTotalEntrySize(int totalSize) { - _totalEntrySize = totalSize; - } - @Override - public byte[] getEntryPrefix() { - return EMPTY_PREFIX; - } - @Override - public void setEntryPrefix(byte[] entryPrefix) { - // ignored - } - - @Override - public List getEntries() { - return _entries; - } - - @Override - public void setEntries(List entries) { - _entries = entries; - } - - @Override - public void addEntry(int idx, Entry entry) { - _entries.add(idx, entry); - _totalEntrySize += entry.size(); - } - - @Override - public void removeEntry(int idx) { - Entry oldEntry = _entries.remove(idx); - _totalEntrySize -= oldEntry.size(); - } - - } - -} diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java index 67b31f9..18303df 100644 --- a/src/java/com/healthmarketscience/jackcess/Table.java +++ b/src/java/com/healthmarketscience/jackcess/Table.java @@ -116,7 +116,7 @@ public class Table }; /** owning database */ - private final Database _database; + private final DatabaseImpl _database; /** additional table flags from the catalog entry */ private int _flags; /** Type of the table (either TYPE_SYSTEM or TYPE_USER) */ @@ -175,8 +175,6 @@ public class Table /** page buffer used to write out-of-line "long value" data */ private final TempPageHolder _longValueBufferH = TempPageHolder.newHolder(TempBufferHolder.Type.SOFT); - /** "big index support" is optional */ - private final boolean _useBigIndex; /** optional error handler to use when row errors are encountered */ private ErrorHandler _tableErrorHandler; /** properties for this table */ @@ -201,7 +199,6 @@ public class Table _database = null; _tableDefPageNumber = PageChannel.INVALID_PAGE_NUMBER; _name = null; - _useBigIndex = true; setColumns(columns); _fkEnforcer = null; } @@ -211,18 +208,15 @@ public class Table * @param tableBuffer Buffer to read the table with * @param pageNumber Page number of the table definition * @param name Table name - * @param useBigIndex whether or not "big index support" should be enabled - * for the table */ - protected Table(Database database, ByteBuffer tableBuffer, - int pageNumber, String name, int flags, boolean useBigIndex) + protected Table(DatabaseImpl database, ByteBuffer tableBuffer, + int pageNumber, String name, int flags) throws IOException { _database = database; _tableDefPageNumber = pageNumber; _name = name; _flags = flags; - _useBigIndex = useBigIndex; readTableDefinition(loadCompleteTableDefinitionBuffer(tableBuffer)); _fkEnforcer = new FKEnforcer(this); } @@ -240,14 +234,7 @@ public class Table * @usage _general_method_ */ public boolean isHidden() { - return((_flags & Database.HIDDEN_OBJECT_FLAG) != 0); - } - - /** - * @usage _advanced_method_ - */ - public boolean doUseBigIndex() { - return _useBigIndex; + return((_flags & DatabaseImpl.HIDDEN_OBJECT_FLAG) != 0); } /** @@ -267,7 +254,7 @@ public class Table /** * @usage _general_method_ */ - public Database getDatabase() { + public DatabaseImpl getDatabase() { return _database; } @@ -1416,7 +1403,7 @@ public class Table * expected to be given in the order that the Columns are listed by the * {@link #getColumns} method. This is by default the storage order of the * Columns in the database, however this order can be influenced by setting - * the ColumnOrder via {@link Database#setColumnOrder} prior to opening the + * the ColumnOrder via {@link DatabaseImpl#setColumnOrder} prior to opening the * Table. The {@link #asRow} method can be used to easily convert a row Map into the * appropriate row array for this Table. *

diff --git a/src/java/com/healthmarketscience/jackcess/TableBuilder.java b/src/java/com/healthmarketscience/jackcess/TableBuilder.java index 51e8697..c1c8496 100644 --- a/src/java/com/healthmarketscience/jackcess/TableBuilder.java +++ b/src/java/com/healthmarketscience/jackcess/TableBuilder.java @@ -56,7 +56,7 @@ public class TableBuilder { _name = name; _escapeIdentifiers = escapeIdentifiers; if(_escapeIdentifiers) { - _name = Database.escapeIdentifier(_name); + _name = DatabaseImpl.escapeIdentifier(_name); } } @@ -66,7 +66,7 @@ public class TableBuilder { */ public TableBuilder addColumn(Column column) { if(_escapeIdentifiers) { - column.setName(Database.escapeIdentifier(column.getName())); + column.setName(DatabaseImpl.escapeIdentifier(column.getName())); } _columns.add(column); return this; @@ -84,9 +84,9 @@ public class TableBuilder { */ public TableBuilder addIndex(IndexBuilder index) { if(_escapeIdentifiers) { - index.setName(Database.escapeIdentifier(index.getName())); + index.setName(DatabaseImpl.escapeIdentifier(index.getName())); for(IndexBuilder.Column col : index.getColumns()) { - col.setName(Database.escapeIdentifier(col.getName())); + col.setName(DatabaseImpl.escapeIdentifier(col.getName())); } } _indexes.add(index); @@ -113,11 +113,11 @@ public class TableBuilder { } /** - * Escapes the new table's name using {@link Database#escapeIdentifier}. + * Escapes the new table's name using {@link DatabaseImpl#escapeIdentifier}. */ public TableBuilder escapeName() { - _name = Database.escapeIdentifier(_name); + _name = DatabaseImpl.escapeIdentifier(_name); return this; } @@ -125,7 +125,7 @@ public class TableBuilder { * Creates a new Table in the given Database with the currently configured * attributes. */ - public Table toTable(Database db) + public Table toTable(DatabaseImpl db) throws IOException { db.createTable(_name, _columns, _indexes); diff --git a/src/java/com/healthmarketscience/jackcess/TableCreator.java b/src/java/com/healthmarketscience/jackcess/TableCreator.java index 75aab7c..bc458de 100644 --- a/src/java/com/healthmarketscience/jackcess/TableCreator.java +++ b/src/java/com/healthmarketscience/jackcess/TableCreator.java @@ -37,7 +37,7 @@ import java.util.Set; */ class TableCreator { - private final Database _database; + private final DatabaseImpl _database; private final String _name; private final List _columns; private final List _indexes; @@ -48,7 +48,7 @@ class TableCreator private int _indexCount; private int _logicalIndexCount; - public TableCreator(Database database, String name, List columns, + public TableCreator(DatabaseImpl database, String name, List columns, List indexes) { _database = database; _name = name; @@ -132,7 +132,7 @@ class TableCreator Table.writeTableDefinition(this); // update the database with the new table info - _database.addNewTable(_name, _tdefPageNumber, Database.TYPE_TABLE, null, null); + _database.addNewTable(_name, _tdefPageNumber, DatabaseImpl.TYPE_TABLE, null, null); } /** @@ -140,7 +140,7 @@ class TableCreator */ private void validate() { - Database.validateIdentifierName( + DatabaseImpl.validateIdentifierName( _name, getFormat().MAX_TABLE_NAME_LENGTH, "table"); if((_columns == null) || _columns.isEmpty()) { diff --git a/src/java/com/healthmarketscience/jackcess/UsageMap.java b/src/java/com/healthmarketscience/jackcess/UsageMap.java index 931891e..920ce25 100644 --- a/src/java/com/healthmarketscience/jackcess/UsageMap.java +++ b/src/java/com/healthmarketscience/jackcess/UsageMap.java @@ -51,7 +51,7 @@ public class UsageMap private static final int INVALID_BIT_INDEX = -1; /** owning database */ - private final Database _database; + private final DatabaseImpl _database; /** Page number of the map table declaration */ private final int _tablePageNum; /** Offset of the data page at which the usage map data starts */ @@ -82,7 +82,7 @@ public class UsageMap * @param pageNum Page number that this usage map is contained in * @param rowStart Offset at which the declaration starts in the buffer */ - private UsageMap(Database database, ByteBuffer tableBuffer, + private UsageMap(DatabaseImpl database, ByteBuffer tableBuffer, int pageNum, short rowStart) throws IOException { @@ -98,7 +98,7 @@ public class UsageMap } } - public Database getDatabase() { + public DatabaseImpl getDatabase() { return _database; } @@ -117,7 +117,7 @@ public class UsageMap * @return Either an InlineUsageMap or a ReferenceUsageMap, depending on * which type of map is found */ - public static UsageMap read(Database database, int pageNum, + public static UsageMap read(DatabaseImpl database, int pageNum, int rowNum, boolean assumeOutOfRangeBitsOn) throws IOException { diff --git a/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java index 0a4b255..21b7b5d 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java @@ -31,7 +31,7 @@ import java.util.Map; import com.healthmarketscience.jackcess.Column; import com.healthmarketscience.jackcess.CursorBuilder; import com.healthmarketscience.jackcess.DataType; -import com.healthmarketscience.jackcess.Database; +import com.healthmarketscience.jackcess.DatabaseImpl; import com.healthmarketscience.jackcess.IndexCursor; import com.healthmarketscience.jackcess.JetFormat; import com.healthmarketscience.jackcess.PageChannel; @@ -108,7 +108,7 @@ public abstract class ComplexColumnInfo int complexTypeId = buffer.getInt( offset + column.getFormat().OFFSET_COLUMN_COMPLEX_ID); - Database db = column.getDatabase(); + DatabaseImpl db = column.getDatabase(); Table complexColumns = db.getSystemComplexColumns(); IndexCursor cursor = IndexCursor.createCursor( complexColumns, complexColumns.getPrimaryKeyIndex()); @@ -162,7 +162,7 @@ public abstract class ComplexColumnInfo return _column; } - public Database getDatabase() { + public DatabaseImpl getDatabase() { return getColumn().getDatabase(); } -- 2.39.5