From 4e5fe7ec04eff9ea4e64a8c6d1e3f7fd51257e06 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Tue, 16 Feb 2016 00:13:01 +0000 Subject: [PATCH] Add Database.getTableMetaData method to enable getting basic info about a Table (by name) without actually loading it. fixes feature request #33 git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@979 f203690c-595d-4dc9-a70b-905162fa7fd2 --- src/changes/changes.xml | 5 ++ .../jackcess/Database.java | 12 +++- .../jackcess/TableMetaData.java | 62 +++++++++++++++++ .../jackcess/impl/DatabaseImpl.java | 68 ++++++++++++++++++- .../jackcess/DatabaseTest.java | 32 ++++++++- 5 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/healthmarketscience/jackcess/TableMetaData.java diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 208fb9c..c683ad9 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -8,6 +8,11 @@ Fix missing column names in AppendQuery SQL strings. + + Add Database.getTableMetaData method to enable getting basic info + about a Table (by name) without actually loading it. + diff --git a/src/main/java/com/healthmarketscience/jackcess/Database.java b/src/main/java/com/healthmarketscience/jackcess/Database.java index 48273ef..42eb216 100644 --- a/src/main/java/com/healthmarketscience/jackcess/Database.java +++ b/src/main/java/com/healthmarketscience/jackcess/Database.java @@ -201,12 +201,20 @@ public interface Database extends Iterable, Closeable, Flushable public TableIterableBuilder newIterable(); /** - * @param name Table name (case-insensitive) - * @return The table, or null if it doesn't exist + * @param name User table name (case-insensitive) + * @return The Table, or null if it doesn't exist (or is a system table) * @usage _general_method_ */ public Table getTable(String name) throws IOException; + /** + * @param name Table name (case-insensitive), may be any table type + * (i.e. includes system or linked tables). + * @return The meta data for the table, or null if it doesn't exist + * @usage _intermediate_method_ + */ + public TableMetaData getTableMetaData(String name) throws IOException; + /** * Finds all the relationships in the database between the given tables. * @usage _intermediate_method_ diff --git a/src/main/java/com/healthmarketscience/jackcess/TableMetaData.java b/src/main/java/com/healthmarketscience/jackcess/TableMetaData.java new file mode 100644 index 0000000..250932b --- /dev/null +++ b/src/main/java/com/healthmarketscience/jackcess/TableMetaData.java @@ -0,0 +1,62 @@ +/* +Copyright (c) 2016 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; + +import java.io.IOException; + +/** + * Basic metadata about a single database Table. This is the top-level + * information stored in a (local) database which can be retrieved without + * attempting to load the Table itself. + * + * @author James Ahlborn + * @usage _intermediate_class_ + */ +public interface TableMetaData +{ + /** + * The name of the table (as it is stored in the database) + */ + public String getName(); + + /** + * {@code true} if this is a linked table, {@code false} otherwise. + */ + public boolean isLinked(); + + /** + * {@code true} if this is a system table, {@code false} otherwise. + */ + public boolean isSystem(); + + /** + * The name of this linked table in the linked database if this is a linked + * table, {@code null} otherwise. + */ + public String getLinkedTableName(); + + /** + * The name of this the linked database if this is a linked table, {@code + * null} otherwise. + */ + public String getLinkedDbName(); + + /** + * Opens this table from the given Database instance. + */ + public Table open(Database db) throws IOException; +} diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java index 490e75f..99500dd 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java @@ -60,6 +60,7 @@ import com.healthmarketscience.jackcess.Relationship; import com.healthmarketscience.jackcess.Row; import com.healthmarketscience.jackcess.RuntimeIOException; import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.TableMetaData; import com.healthmarketscience.jackcess.impl.query.QueryImpl; import com.healthmarketscience.jackcess.query.Query; import com.healthmarketscience.jackcess.util.CaseInsensitiveColumnMatcher; @@ -928,6 +929,10 @@ public class DatabaseImpl implements Database return getTable(name, false); } + public TableMetaData getTableMetaData(String name) throws IOException { + return getTableInfo(name, true); + } + /** * @param tableDefPageNumber the page number of a table definition * @return The table, or null if it doesn't exist @@ -961,16 +966,30 @@ public class DatabaseImpl implements Database */ private TableImpl getTable(String name, boolean includeSystemTables) throws IOException + { + TableInfo tableInfo = getTableInfo(name, includeSystemTables); + return ((tableInfo != null) ? + getTable(tableInfo, includeSystemTables) : null); + } + + private TableInfo getTableInfo(String name, boolean includeSystemTables) + throws IOException { TableInfo tableInfo = lookupTable(name); if ((tableInfo == null) || (tableInfo.pageNumber == null)) { return null; } - if(!includeSystemTables && isSystemObject(tableInfo.flags)) { + if(!includeSystemTables && tableInfo.isSystem()) { return null; } + return tableInfo; + } + + private TableImpl getTable(TableInfo tableInfo, boolean includeSystemTables) + throws IOException + { if(tableInfo.isLinked()) { if(_linkedDbs == null) { @@ -1884,7 +1903,7 @@ public class DatabaseImpl implements Database /** * Utility class for storing table page number and actual name. */ - private static class TableInfo + private static class TableInfo implements TableMetaData { public final Integer pageNumber; public final String tableName; @@ -1896,9 +1915,44 @@ public class DatabaseImpl implements Database flags = newFlags; } + public String getName() { + return tableName; + } + public boolean isLinked() { return false; } + + public boolean isSystem() { + return isSystemObject(flags); + } + + public String getLinkedTableName() { + return null; + } + + public String getLinkedDbName() { + return null; + } + + public Table open(Database db) throws IOException { + return ((DatabaseImpl)db).getTable(this, true); + } + + @Override + public String toString() { + ToStringBuilder sb = CustomToStringStyle.valueBuilder("TableMetaData") + .append("name", getName()); + if(isSystem()) { + sb.append("isSystem", isSystem()); + } + if(isLinked()) { + sb.append("isLinked", isLinked()) + .append("linkedTableName", getLinkedTableName()) + .append("linkedDbName", getLinkedDbName()); + } + return sb.toString(); + } } /** @@ -1921,6 +1975,16 @@ public class DatabaseImpl implements Database public boolean isLinked() { return true; } + + @Override + public String getLinkedTableName() { + return linkedTableName; + } + + @Override + public String getLinkedDbName() { + return linkedDbName; + } } /** diff --git a/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java b/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java index 5b0aff6..60e8bea 100644 --- a/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java @@ -777,6 +777,10 @@ public class DatabaseTest extends TestCase assertNull(db.getSystemTable("MSysBogus")); + TableMetaData tmd = db.getTableMetaData("MSysObjects"); + assertEquals("MSysObjects", tmd.getName()); + assertFalse(tmd.isLinked()); + assertTrue(tmd.isSystem()); db.close(); } @@ -858,6 +862,16 @@ public class DatabaseTest extends TestCase // success } + TableMetaData tmd = db.getTableMetaData("Table2"); + assertEquals("Table2", tmd.getName()); + assertTrue(tmd.isLinked()); + assertFalse(tmd.isSystem()); + assertEquals("Table1", tmd.getLinkedTableName()); + assertEquals("Z:\\jackcess_test\\linkeeTest.accdb", tmd.getLinkedDbName()); + + tmd = db.getTableMetaData("FooTable"); + assertNull(tmd); + assertTrue(db.getLinkedDatabases().isEmpty()); final String linkeeDbName = "Z:\\jackcess_test\\linkeeTest.accdb"; @@ -887,6 +901,13 @@ public class DatabaseTest extends TestCase db.createLinkedTable("FooTable", linkeeDbName, "Table2"); + tmd = db.getTableMetaData("FooTable"); + assertEquals("FooTable", tmd.getName()); + assertTrue(tmd.isLinked()); + assertFalse(tmd.isSystem()); + assertEquals("Table2", tmd.getLinkedTableName()); + assertEquals("Z:\\jackcess_test\\linkeeTest.accdb", tmd.getLinkedDbName()); + Table t3 = db.getTable("FooTable"); assertEquals(1, db.getLinkedDatabases().size()); @@ -899,7 +920,14 @@ public class DatabaseTest extends TestCase assertTable(expectedRows, t3); - Table t1 = db.getTable("Table1"); + tmd = db.getTableMetaData("Table1"); + assertEquals("Table1", tmd.getName()); + assertFalse(tmd.isLinked()); + assertFalse(tmd.isSystem()); + assertNull(tmd.getLinkedTableName()); + assertNull(tmd.getLinkedDbName()); + + Table t1 = tmd.open(db); assertFalse(db.isLinkedTable(null)); assertTrue(db.isLinkedTable(t2)); @@ -933,7 +961,7 @@ public class DatabaseTest extends TestCase assertFalse(tables.contains(t2)); assertFalse(tables.contains(t3)); assertTrue(tables.contains(((DatabaseImpl)db).getSystemCatalog())); - + db.close(); } } -- 2.39.5