Browse Source

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
tags/jackcess-3.0.1
James Ahlborn 5 years ago
parent
commit
1fb85bd37a

+ 5
- 0
src/changes/changes.xml View File

Add ColumnFormatter utility which can apply Column "Format" property Add ColumnFormatter utility which can apply Column "Format" property
for display of column values. for display of column values.
</action> </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>
<release version="3.0.0" date="2019-02-08" description="Update to Java 8"> <release version="3.0.0" date="2019-02-08" description="Update to Java 8">
<action dev="jahlborn" type="update"> <action dev="jahlborn" type="update">

+ 11
- 0
src/main/java/com/healthmarketscience/jackcess/Database.java View File

*/ */
public TableIterableBuilder newIterable(); 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) * @param name User table name (case-insensitive)
* @return The Table, or null if it doesn't exist (or is a system table) * @return The Table, or null if it doesn't exist (or is a system table)

+ 80
- 11
src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java View File

return new TableIterableBuilder(this); return new TableIterableBuilder(this);
} }


@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 @Override
public TableImpl getTable(String name) throws IOException { public TableImpl getTable(String name) throws IOException {
return getTable(name, false); return getTable(name, false);
return false; 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) protected abstract Cursor findRow(Integer parentId, String name)
throws IOException; throws IOException;


throws IOException; throws IOException;


protected abstract int findMaxSyntheticId() 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;
}
} }


/** /**

+ 48
- 0
src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java View File

assertEquals("Row[1:1][{id=37,data=<null>}]", row.toString()); 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) private static void checkRawValue(String expected, Object val)
{ {
if(expected != null) { if(expected != null) {

Loading…
Cancel
Save