diff options
5 files changed, 63 insertions, 62 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java index 200a13d..fc70fe4 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java @@ -53,6 +53,7 @@ import com.healthmarketscience.jackcess.CursorBuilder; import com.healthmarketscience.jackcess.DataType; import com.healthmarketscience.jackcess.Database; import com.healthmarketscience.jackcess.DatabaseBuilder; +import com.healthmarketscience.jackcess.Index; import com.healthmarketscience.jackcess.IndexBuilder; import com.healthmarketscience.jackcess.IndexCursor; import com.healthmarketscience.jackcess.PropertyMap; @@ -1171,9 +1172,7 @@ public class DatabaseImpl implements Database { initRelationships(); - String name = findUniqueRelationshipName( - creator.getPrimaryTable().getName() + - creator.getSecondaryTable().getName()); + String name = createRelationshipName(creator); RelationshipImpl newRel = creator.createRelationshipImpl(name); ColumnImpl ccol = _relationships.getColumn(REL_COL_COLUMN_COUNT); @@ -1226,9 +1225,28 @@ public class DatabaseImpl implements Database } } - private String findUniqueRelationshipName(String origName) throws IOException { + private String createRelationshipName(RelationshipCreator creator) + throws IOException + { + // ensure that the final identifier name does not get too long + // - the primary name is limited to ((max / 2) - 3) + // - the total name is limited to (max - 3) + int maxIdLen = getFormat().MAX_INDEX_NAME_LENGTH; + int limit = (maxIdLen / 2) - 3; + String origName = creator.getPrimaryTable().getName(); + if(origName.length() > limit) { + origName = origName.substring(0, limit); + } + limit = maxIdLen - 3; + origName += creator.getSecondaryTable().getName(); + if(origName.length() > limit) { + origName = origName.substring(0, limit); + } + + // now ensure name is unique Set<String> names = new HashSet<String>(); + // collect the names of all relationships for uniqueness check for(Row row : CursorImpl.createCursor(_systemCatalog).newIterable().setColumnNames( SYSTEM_CATALOG_COLUMNS)) @@ -1239,6 +1257,14 @@ public class DatabaseImpl implements Database } } + if(creator.hasReferentialIntegrity()) { + // relationship name will also be index name in secondary table, so must + // check those names as well + for(Index idx : creator.getSecondaryTable().getIndexes()) { + names.add(toLookupName(idx.getName())); + } + } + String baseName = toLookupName(origName); String name = baseName; int i = 0; @@ -1246,8 +1272,6 @@ public class DatabaseImpl implements Database name = baseName + (++i); } - // FIXME, truncate to max identifier length - return ((i == 0) ? origName : (origName + i)); } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/IndexImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/IndexImpl.java index 2d97e75..8cdb54c 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/IndexImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/IndexImpl.java @@ -54,10 +54,9 @@ public class IndexImpl implements Index, Comparable<IndexImpl> private static final byte CASCADE_NULL_FLAG = (byte)2; /** index table type for the "primary" table in a foreign key index */ - static final byte PRIMARY_TABLE_TYPE = (byte)1; - + static final byte FK_PRIMARY_TABLE_TYPE = (byte)1; /** index table type for the "secondary" table in a foreign key index */ - static final byte SECONDARY_TABLE_TYPE = (byte)2; + static final byte FK_SECONDARY_TABLE_TYPE = (byte)2; /** indicate an invalid index number for foreign key field */ private static final int INVALID_INDEX_NUMBER = -1; @@ -434,7 +433,7 @@ public class IndexImpl implements Index, Comparable<IndexImpl> } public boolean isPrimaryTable() { - return(getTableType() == PRIMARY_TABLE_TYPE); + return(getTableType() == FK_PRIMARY_TABLE_TYPE); } public int getOtherIndexNumber() { diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/RelationshipCreator.java b/src/main/java/com/healthmarketscience/jackcess/impl/RelationshipCreator.java index 80c8acf..dcfdf3d 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/RelationshipCreator.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/RelationshipCreator.java @@ -53,16 +53,8 @@ public class RelationshipCreator extends DBMutator private List<ColumnImpl> _primaryCols; private List<ColumnImpl> _secondaryCols; private int _flags; + private String _name; - // - primary table must have unique index - // - primary table index name ".rC", ".rD"... - // - secondary index name "<PTable><STable>" - // - add <name>1, <name>2 after names to make unique (index names and - // relationship names) - // - enforcing rel integrity can't have dupe cols - // FIXME - // - what about index name clashes? - public RelationshipCreator(DatabaseImpl database) { super(database); @@ -76,7 +68,12 @@ public class RelationshipCreator extends DBMutator return _secondaryTable; } + public boolean hasReferentialIntegrity() { + return _relationship.hasReferentialIntegrity(); + } + public RelationshipImpl createRelationshipImpl(String name) { + _name = name; RelationshipImpl newRel = new RelationshipImpl( name, _primaryTable, _secondaryTable, _flags, _primaryCols, _secondaryCols); @@ -105,7 +102,7 @@ public class RelationshipCreator extends DBMutator RelationshipImpl newRel = getDatabase().writeRelationship(this); - if(_relationship.hasReferentialIntegrity()) { + if(hasReferentialIntegrity()) { addPrimaryIndex(); addSecondaryIndex(); } @@ -136,13 +133,13 @@ public class RelationshipCreator extends DBMutator int otherTableNum = 0; int otherIdxNum = 0; if(isPrimary) { - tableType = IndexImpl.PRIMARY_TABLE_TYPE; + tableType = IndexImpl.FK_PRIMARY_TABLE_TYPE; otherTableNum = _secondaryTable.getTableDefPageNumber(); // we create the primary index first, so the secondary index does not // exist yet otherIdxNum = _secondaryTable.getLogicalIndexCount(); } else { - tableType = IndexImpl.SECONDARY_TABLE_TYPE; + tableType = IndexImpl.FK_SECONDARY_TABLE_TYPE; otherTableNum = _primaryTable.getTableDefPageNumber(); // at this point, we've already created the primary index, it's the last // one on the primary table @@ -191,7 +188,7 @@ public class RelationshipCreator extends DBMutator } } - if(!_relationship.hasReferentialIntegrity()) { + if(!hasReferentialIntegrity()) { if((_relationship.getFlags() & CASCADE_FLAGS) != 0) { throw new IllegalArgumentException(withErrorContext( @@ -248,18 +245,15 @@ public class RelationshipCreator extends DBMutator } private IndexBuilder createPrimaryIndex() { - String name = getUniqueIndexName(_primaryTable); - // FIXME? + String name = createPrimaryIndexName(); return createIndex(name, _primaryCols) .setUnique() .setType(IndexImpl.FOREIGN_KEY_INDEX_TYPE); } private IndexBuilder createSecondaryIndex() { - String name = getUniqueIndexName(_secondaryTable); - // FIXME? - - return createIndex(name, _secondaryCols) + // secondary index uses relationship name + return createIndex(_name, _secondaryCols) .setType(IndexImpl.FOREIGN_KEY_INDEX_TYPE); } @@ -271,45 +265,29 @@ public class RelationshipCreator extends DBMutator return idx; } - private String getUniqueIndexName(TableImpl table) { - Set<String> idxNames = TableUpdater.getIndexNames(table, null); + private String createPrimaryIndexName() { + Set<String> idxNames = TableUpdater.getIndexNames(_primaryTable, null); - boolean isPrimary = (table == _primaryTable); - String baseName = null; - String suffix = null; - if(isPrimary) { - // primary naming scheme: ".rB", .rC", ".rD", "rE" ... - baseName = ".r"; - suffix = "B"; - } else { - // secondary naming scheme: "<t1><t2>", "<t1><t2>1", "<t1><t2>2" - baseName = _primaryTable.getName() + _secondaryTable.getName(); - suffix = ""; - } + // primary naming scheme: ".rB", .rC", ".rD", "rE" ... + String baseName = ".r"; + String suffix = "B"; - int count = 0; while(true) { String idxName = baseName + suffix; - if(!idxNames.contains(idxName.toUpperCase())) { + if(!idxNames.contains(DatabaseImpl.toLookupName(idxName))) { return idxName; } - ++count; - if(isPrimary) { - char c = (char)(suffix.charAt(0) + 1); - if(c == '[') { - c = 'a'; - } - suffix = "" + c; - } else { - suffix = "" + count; - } + char c = (char)(suffix.charAt(0) + 1); + if(c == '[') { + c = 'a'; + } + suffix = "" + c; } - - // FIXME, truncate to max index name length } - private static List<ColumnImpl> getColumns(TableImpl table, List<String> colNames) { + private static List<ColumnImpl> getColumns(TableImpl table, + List<String> colNames) { List<ColumnImpl> cols = new ArrayList<ColumnImpl>(); for(String colName : colNames) { cols.add(table.getColumn(colName)); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java b/src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java index 5bc7e11..65bb8dc 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java @@ -63,7 +63,7 @@ public abstract class TableMutator extends DBMutator } column.validate(getFormat()); - if(!colNames.add(column.getName().toUpperCase())) { + if(!colNames.add(DatabaseImpl.toLookupName(column.getName()))) { throw new IllegalArgumentException(withErrorContext( "duplicate column name: " + column.getName())); } @@ -75,7 +75,7 @@ public abstract class TableMutator extends DBMutator boolean[] foundPk, IndexBuilder index) { index.validate(colNames, getFormat()); - if(!idxNames.add(index.getName().toUpperCase())) { + if(!idxNames.add(DatabaseImpl.toLookupName(index.getName()))) { throw new IllegalArgumentException(withErrorContext( "duplicate index name: " + index.getName())); } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/TableUpdater.java b/src/main/java/com/healthmarketscience/jackcess/impl/TableUpdater.java index de208c9..724a1fa 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/TableUpdater.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/TableUpdater.java @@ -240,7 +240,7 @@ public class TableUpdater extends TableMutator private Set<String> getColumnNames() { Set<String> colNames = new HashSet<String>(); for(ColumnImpl column : _table.getColumns()) { - colNames.add(column.getName().toUpperCase()); + colNames.add(DatabaseImpl.toLookupName(column.getName())); } return colNames; } @@ -248,7 +248,7 @@ public class TableUpdater extends TableMutator static Set<String> getIndexNames(TableImpl table, boolean[] foundPk) { Set<String> idxNames = new HashSet<String>(); for(IndexImpl index : table.getIndexes()) { - idxNames.add(index.getName().toUpperCase()); + idxNames.add(DatabaseImpl.toLookupName(index.getName())); if(index.isPrimaryKey() && (foundPk != null)) { foundPk[0] = true; } |