git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1295 f203690c-595d-4dc9-a70b-905162fa7fd2tags/jackcess-3.0.1
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"> |
*/ | */ | ||||
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) |
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; | |||||
} | |||||
} | } | ||||
/** | /** |
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) { |