aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2019-02-20 05:43:35 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2019-02-20 05:43:35 +0000
commit1fb85bd37a398ff94abd048bfea0a4ec9c8b86d9 (patch)
tree2b90c51a717b96dc7b103b5ddf96193e63489121
parentcdcd610a9743ed9be8c7865fdaffc5ae5bef5110 (diff)
downloadjackcess-1fb85bd37a398ff94abd048bfea0a4ec9c8b86d9.tar.gz
jackcess-1fb85bd37a398ff94abd048bfea0a4ec9c8b86d9.zip
Add Database.newTableMetaDataIterable() which enables iterating through table names without loading the entire collection into memory at once
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1295 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/changes/changes.xml5
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/Database.java11
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java91
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java48
4 files changed, 144 insertions, 11 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c7a37e0..ca5133f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -9,6 +9,11 @@
Add ColumnFormatter utility which can apply Column "Format" property
for display of column values.
</action>
+ <action dev="jahlborn" type="update">
+ Add Database.newTableMetaDataIterable() which enables iterating
+ through table names without loading the entire collection into memory
+ at once.
+ </action>
</release>
<release version="3.0.0" date="2019-02-08" description="Update to Java 8">
<action dev="jahlborn" type="update">
diff --git a/src/main/java/com/healthmarketscience/jackcess/Database.java b/src/main/java/com/healthmarketscience/jackcess/Database.java
index 4fa8741..7ce5928 100644
--- a/src/main/java/com/healthmarketscience/jackcess/Database.java
+++ b/src/main/java/com/healthmarketscience/jackcess/Database.java
@@ -226,6 +226,17 @@ public interface Database extends Iterable<Table>, Closeable, Flushable
public TableIterableBuilder newIterable();
/**
+ * @return an Iterable which returns an unmodifiable Iterator of the the
+ * TableMetaData for all tables in this Database.
+ * @throws RuntimeIOException 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 _intermediate_method_
+ */
+ public Iterable<TableMetaData> newTableMetaDataIterable();
+
+ /**
* @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_
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
index 1db1c3b..bc3cf80 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
@@ -1051,6 +1051,20 @@ public class DatabaseImpl implements Database, DateTimeContext
}
@Override
+ public Iterable<TableMetaData> newTableMetaDataIterable() {
+ return new Iterable<TableMetaData>() {
+ @Override
+ public Iterator<TableMetaData> iterator() {
+ try {
+ return _tableFinder.iterateTableMetaData();
+ } catch(IOException e) {
+ throw new RuntimeIOException(e);
+ }
+ }
+ };
+ }
+
+ @Override
public TableImpl getTable(String name) throws IOException {
return getTable(name, false);
}
@@ -2426,6 +2440,72 @@ public class DatabaseImpl implements Database, DateTimeContext
return false;
}
+ public int getNextFreeSyntheticId() throws IOException {
+ int maxSynthId = findMaxSyntheticId();
+ if(maxSynthId >= -1) {
+ // bummer, no more ids available
+ throw new IllegalStateException(withErrorContext(
+ "Too many database objects!"));
+ }
+ return maxSynthId + 1;
+ }
+
+ public Iterator<TableMetaData> iterateTableMetaData() throws IOException {
+ return new Iterator<TableMetaData>() {
+ private final Iterator<Row> _iter =
+ getTableNamesCursor().newIterable().setColumnNames(
+ SYSTEM_CATALOG_TABLE_DETAIL_COLUMNS).iterator();
+ private TableMetaData _next;
+
+ @Override
+ public boolean hasNext() {
+ if((_next == null) && _iter.hasNext()) {
+ _next = nextTableMetaData(_iter);
+ }
+ return (_next != null);
+ }
+
+ @Override
+ public TableMetaData next() {
+ if(!hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ TableMetaData next = _next;
+ _next = null;
+ return next;
+ }
+ };
+ }
+
+ private TableMetaData nextTableMetaData(Iterator<Row> detailIter) {
+
+ while(detailIter.hasNext()) {
+ Row row = detailIter.next();
+
+ Short type = row.getShort(CAT_COL_TYPE);
+ if(!isTableType(type)) {
+ continue;
+ }
+
+ int parentId = row.getInt(CAT_COL_PARENT_ID);
+ if(parentId != _tableParentId) {
+ continue;
+ }
+
+ String realName = row.getString(CAT_COL_NAME);
+ Integer pageNumber = row.getInt(CAT_COL_ID);
+ int flags = row.getInt(CAT_COL_FLAGS);
+ String linkedDbName = row.getString(CAT_COL_DATABASE);
+ String linkedTableName = row.getString(CAT_COL_FOREIGN_NAME);
+
+ return createTableInfo(realName, pageNumber, flags, type, linkedDbName,
+ linkedTableName);
+ }
+
+ return null;
+ }
+
protected abstract Cursor findRow(Integer parentId, String name)
throws IOException;
@@ -2438,17 +2518,6 @@ public class DatabaseImpl implements Database, DateTimeContext
throws IOException;
protected abstract int findMaxSyntheticId() throws IOException;
-
- public int getNextFreeSyntheticId() throws IOException
- {
- int maxSynthId = findMaxSyntheticId();
- if(maxSynthId >= -1) {
- // bummer, no more ids available
- throw new IllegalStateException(withErrorContext(
- "Too many database objects!"));
- }
- return maxSynthId + 1;
- }
}
/**
diff --git a/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java b/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java
index 0a33a99..2e5c35e 100644
--- a/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java
@@ -1031,6 +1031,54 @@ public class DatabaseTest extends TestCase
assertEquals("Row[1:1][{id=37,data=<null>}]", row.toString());
}
+ public void testIterateTableNames() throws Exception {
+ for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) {
+ final Database db = open(testDB);
+
+ Set<String> names = new HashSet<>();
+ int sysCount = 0;
+ for(TableMetaData tmd : db.newTableMetaDataIterable()) {
+ if(tmd.isSystem()) {
+ ++sysCount;
+ continue;
+ }
+ assertFalse(tmd.isLinked());
+ assertNull(tmd.getLinkedTableName());
+ assertNull(tmd.getLinkedDbName());
+ names.add(tmd.getName());
+ }
+
+ assertTrue(sysCount > 4);
+ assertEquals(new HashSet<>(Arrays.asList("Table1", "Table2", "Table3",
+ "Table4")),
+ names);
+ }
+
+ for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.LINKED)) {
+ final Database db = open(testDB);
+
+ Set<String> names = new HashSet<>();
+ for(TableMetaData tmd : db.newTableMetaDataIterable()) {
+ if(tmd.isSystem()) {
+ continue;
+ }
+ if("Table1".equals(tmd.getName())) {
+ assertFalse(tmd.isLinked());
+ assertNull(tmd.getLinkedTableName());
+ assertNull(tmd.getLinkedDbName());
+ } else {
+ assertTrue(tmd.isLinked());
+ assertEquals("Table1", tmd.getLinkedTableName());
+ assertEquals("Z:\\jackcess_test\\linkeeTest.accdb", tmd.getLinkedDbName());
+ }
+ names.add(tmd.getName());
+ }
+
+ assertEquals(new HashSet<>(Arrays.asList("Table1", "Table2")),
+ names);
+ }
+ }
+
private static void checkRawValue(String expected, Object val)
{
if(expected != null) {