Browse Source

ensure unique rel name and limit total length

git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/mutateops@1027 f203690c-595d-4dc9-a70b-905162fa7fd2
tags/jackcess-2.1.5
James Ahlborn 7 years ago
parent
commit
c41e88f465

+ 30
- 6
src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java View File

@@ -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));
}

+ 3
- 4
src/main/java/com/healthmarketscience/jackcess/impl/IndexImpl.java View File

@@ -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() {

+ 26
- 48
src/main/java/com/healthmarketscience/jackcess/impl/RelationshipCreator.java View File

@@ -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));

+ 2
- 2
src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java View File

@@ -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()));
}

+ 2
- 2
src/main/java/com/healthmarketscience/jackcess/impl/TableUpdater.java View File

@@ -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;
}

Loading…
Cancel
Save