From 99f648a340dd45967550a511f8a27a16c2c5b5f3 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Fri, 31 May 2013 03:49:51 +0000 Subject: [PATCH] add more methods to Database for retrieving Relationships git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@732 f203690c-595d-4dc9-a70b-905162fa7fd2 --- src/changes/changes.xml | 3 + .../jackcess/Database.java | 124 ++++++++++++++---- .../jackcess/RelationshipTest.java | 60 +++++++-- 3 files changed, 157 insertions(+), 30 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 260f266..c5b9575 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -9,6 +9,9 @@ Fix partial page updates when using CodecHandlers which can only do full page encoding. + + Add more methods to Database for retrieving Relationships. + diff --git a/src/java/com/healthmarketscience/jackcess/Database.java b/src/java/com/healthmarketscience/jackcess/Database.java index 2867587..3a720b2 100644 --- a/src/java/com/healthmarketscience/jackcess/Database.java +++ b/src/java/com/healthmarketscience/jackcess/Database.java @@ -1524,14 +1524,6 @@ public class Database public List getRelationships(Table table1, Table table2) throws IOException { - // the relationships table does not get loaded until first accessed - if(_relationships == null) { - _relationships = getSystemTable(TABLE_SYSTEM_RELATIONSHIPS); - if(_relationships == null) { - throw new IOException("Could not find system relationships table"); - } - } - int nameCmp = table1.getName().compareTo(table2.getName()); if(nameCmp == 0) { throw new IllegalArgumentException("Must provide two different tables"); @@ -1544,15 +1536,79 @@ public class Database table1 = table2; table2 = tmp; } + + return getRelationshipsImpl(table1, table2, true); + } + /** + * Finds all the relationships in the database for the given table. + * @usage _intermediate_method_ + */ + public List getRelationships(Table table) + throws IOException + { + if(table == null) { + throw new IllegalArgumentException("Must provide a table"); + } + // since we are getting relationships specific to certain table include + // all tables + return getRelationshipsImpl(table, null, true); + } + + /** + * Finds all the relationships in the database in non-system tables. + *

+ * Warning, this may load all the Tables (metadata, not data) in the + * database which could cause memory issues. + * @usage _intermediate_method_ + */ + public List getRelationships() + throws IOException + { + return getRelationshipsImpl(null, null, false); + } + + /** + * Finds all the relationships in the database, including system + * tables. + *

+ * Warning, this may load all the Tables (metadata, not data) in the + * database which could cause memory issues. + * @usage _intermediate_method_ + */ + public List getSystemRelationships() + throws IOException + { + return getRelationshipsImpl(null, null, true); + } + + private List getRelationshipsImpl(Table table1, Table table2, + boolean includeSystemTables) + throws IOException + { + // the relationships table does not get loaded until first accessed + if(_relationships == null) { + _relationships = getSystemTable(TABLE_SYSTEM_RELATIONSHIPS); + if(_relationships == null) { + throw new IOException("Could not find system relationships table"); + } + } List relationships = new ArrayList(); - Cursor cursor = createCursorWithOptionalIndex( - _relationships, REL_COL_FROM_TABLE, table1.getName()); - collectRelationships(cursor, table1, table2, relationships); - cursor = createCursorWithOptionalIndex( - _relationships, REL_COL_TO_TABLE, table1.getName()); - collectRelationships(cursor, table2, table1, relationships); + + if(table1 != null) { + Cursor cursor = createCursorWithOptionalIndex( + _relationships, REL_COL_FROM_TABLE, table1.getName()); + collectRelationships(cursor, table1, table2, relationships, + includeSystemTables); + cursor = createCursorWithOptionalIndex( + _relationships, REL_COL_TO_TABLE, table1.getName()); + collectRelationships(cursor, table2, table1, relationships, + includeSystemTables); + } else { + collectRelationships(new CursorBuilder(_relationships).toCursor(), + null, null, relationships, includeSystemTables); + } return relationships; } @@ -1760,17 +1816,22 @@ public class Database * Finds the relationships matching the given from and to tables from the * given cursor and adds them to the given list. */ - private static void collectRelationships( + private void collectRelationships( Cursor cursor, Table fromTable, Table toTable, - List relationships) + List relationships, boolean includeSystemTables) + throws IOException { + String fromTableName = ((fromTable != null) ? fromTable.getName() : null); + String toTableName = ((toTable != null) ? toTable.getName() : null); + for(Map row : cursor) { String fromName = (String)row.get(REL_COL_FROM_TABLE); String toName = (String)row.get(REL_COL_TO_TABLE); - if(fromTable.getName().equalsIgnoreCase(fromName) && - toTable.getName().equalsIgnoreCase(toName)) - { + if(((fromTableName == null) || + fromTableName.equalsIgnoreCase(fromName)) && + ((toTableName == null) || + toTableName.equalsIgnoreCase(toName))) { String relName = (String)row.get(REL_COL_NAME); @@ -1784,20 +1845,39 @@ public class Database } } + Table relFromTable = fromTable; + if(relFromTable == null) { + relFromTable = getTable(fromName, includeSystemTables, + defaultUseBigIndex()); + if(relFromTable == null) { + // invalid table or ignoring system tables, just ignore + continue; + } + } + Table relToTable = toTable; + if(relToTable == null) { + relToTable = getTable(toName, includeSystemTables, + defaultUseBigIndex()); + if(relToTable == null) { + // invalid table or ignoring system tables, just ignore + continue; + } + } + if(rel == null) { // new relationship int numCols = (Integer)row.get(REL_COL_COLUMN_COUNT); int flags = (Integer)row.get(REL_COL_FLAGS); - rel = new Relationship(relName, fromTable, toTable, + rel = new Relationship(relName, relFromTable, relToTable, flags, numCols); relationships.add(rel); } // add column info int colIdx = (Integer)row.get(REL_COL_COLUMN_INDEX); - Column fromCol = fromTable.getColumn( + Column fromCol = relFromTable.getColumn( (String)row.get(REL_COL_FROM_COLUMN)); - Column toCol = toTable.getColumn( + Column toCol = relToTable.getColumn( (String)row.get(REL_COL_TO_COLUMN)); rel.getFromColumns().set(colIdx, fromCol); diff --git a/test/src/java/com/healthmarketscience/jackcess/RelationshipTest.java b/test/src/java/com/healthmarketscience/jackcess/RelationshipTest.java index 4f3175f..e49b9bb 100644 --- a/test/src/java/com/healthmarketscience/jackcess/RelationshipTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/RelationshipTest.java @@ -27,24 +27,32 @@ King of Prussia, PA 19406 package com.healthmarketscience.jackcess; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.List; -import junit.framework.TestCase; - import static com.healthmarketscience.jackcess.DatabaseTest.*; import static com.healthmarketscience.jackcess.JetFormatTest.*; +import junit.framework.TestCase; /** * @author James Ahlborn */ public class RelationshipTest extends TestCase { + private static final Comparator REL_COMP = new Comparator() { + public int compare(Relationship r1, Relationship r2) { + return String.CASE_INSENSITIVE_ORDER.compare(r1.getName(), r2.getName()); + } + }; + public RelationshipTest(String name) throws Exception { super(name); } - public void testSimple() throws Exception { + public void testTwoTables() throws Exception { for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX, true)) { Database db = open(testDB); Table t1 = db.getTable("Table1"); @@ -64,11 +72,11 @@ public class RelationshipTest extends TestCase { assertTrue(rel.hasReferentialIntegrity()); assertEquals(4096, rel.getFlags()); assertTrue(rel.cascadeDeletes()); - assertSameRelationships(rels, db.getRelationships(t2, t1)); + assertSameRelationships(rels, db.getRelationships(t2, t1), true); rels = db.getRelationships(t2, t3); assertTrue(db.getRelationships(t2, t3).isEmpty()); - assertSameRelationships(rels, db.getRelationships(t3, t2)); + assertSameRelationships(rels, db.getRelationships(t3, t2), true); rels = db.getRelationships(t1, t3); assertEquals(1, rels.size()); @@ -83,7 +91,7 @@ public class RelationshipTest extends TestCase { assertTrue(rel.hasReferentialIntegrity()); assertEquals(256, rel.getFlags()); assertTrue(rel.cascadeUpdates()); - assertSameRelationships(rels, db.getRelationships(t3, t1)); + assertSameRelationships(rels, db.getRelationships(t3, t1), true); try { db.getRelationships(t1, t1); @@ -94,10 +102,46 @@ public class RelationshipTest extends TestCase { } } - private void assertSameRelationships( - List expected, List found) + public void testOneTable() throws Exception { + for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX, true)) { + Database db = open(testDB); + Table t1 = db.getTable("Table1"); + Table t2 = db.getTable("Table2"); + Table t3 = db.getTable("Table3"); + + List expected = new ArrayList(); + expected.addAll(db.getRelationships(t1, t2)); + expected.addAll(db.getRelationships(t2, t3)); + + assertSameRelationships(expected, db.getRelationships(t2), false); + + } + } + + public void testNoTables() throws Exception { + for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.INDEX, true)) { + Database db = open(testDB); + Table t1 = db.getTable("Table1"); + Table t2 = db.getTable("Table2"); + Table t3 = db.getTable("Table3"); + + List expected = new ArrayList(); + expected.addAll(db.getRelationships(t1, t2)); + expected.addAll(db.getRelationships(t2, t3)); + expected.addAll(db.getRelationships(t1, t3)); + + assertSameRelationships(expected, db.getRelationships(), false); + } + } + + private static void assertSameRelationships( + List expected, List found, boolean ordered) { assertEquals(expected.size(), found.size()); + if(!ordered) { + Collections.sort(expected, REL_COMP); + Collections.sort(found, REL_COMP); + } for(int i = 0; i < expected.size(); ++i) { Relationship eRel = expected.get(i); Relationship fRel = found.get(i); -- 2.39.5