git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/mutateops@1012 f203690c-595d-4dc9-a70b-905162fa7fd2tags/jackcess-2.1.5
@@ -123,6 +123,14 @@ public class IndexBuilder | |||
return setUnique(); | |||
} | |||
/** | |||
* @usage _advanced_method_ | |||
*/ | |||
public IndexBuilder setType(byte type) { | |||
_type = type; | |||
return this; | |||
} | |||
/** | |||
* Sets this index to enforce uniqueness. | |||
*/ |
@@ -1170,8 +1170,9 @@ public class DatabaseImpl implements Database | |||
{ | |||
initRelationships(); | |||
String name = creator.getPrimaryTable().getName() + | |||
creator.getSecondaryTable().getName(); // FIXME make unique | |||
String name = findUniqueRelationshipName( | |||
creator.getPrimaryTable().getName() + | |||
creator.getSecondaryTable().getName()); | |||
RelationshipImpl newRel = creator.createRelationshipImpl(name); | |||
ColumnImpl ccol = _relationships.getColumn(REL_COL_COLUMN_COUNT); | |||
@@ -1222,6 +1223,29 @@ public class DatabaseImpl implements Database | |||
_relationships = getRequiredSystemTable(TABLE_SYSTEM_RELATIONSHIPS); | |||
} | |||
} | |||
private String findUniqueRelationshipName(String origName) throws IOException { | |||
Set<String> names = new HashSet<String>(); | |||
for(Row row : | |||
CursorImpl.createCursor(_systemCatalog).newIterable().setColumnNames( | |||
SYSTEM_CATALOG_COLUMNS)) | |||
{ | |||
String name = row.getString(CAT_COL_NAME); | |||
if (name != null && TYPE_RELATIONSHIP.equals(row.get(CAT_COL_TYPE))) { | |||
names.add(toLookupName(name)); | |||
} | |||
} | |||
String baseName = toLookupName(origName); | |||
String name = baseName; | |||
int i = 0; | |||
while(names.contains(name)) { | |||
name = baseName + (++i); | |||
} | |||
return ((i == 0) ? origName : (origName + i)); | |||
} | |||
public List<Query> getQueries() throws IOException | |||
{ |
@@ -360,12 +360,34 @@ public class IndexImpl implements Index, Comparable<IndexImpl> | |||
buffer.putInt(TableImpl.MAGIC_TABLE_NUMBER); // seemingly constant magic value which matches the table def | |||
buffer.putInt(idx.getIndexNumber()); // index num | |||
buffer.putInt(idxDataState.getIndexDataNumber()); // index data num | |||
buffer.put((byte)0); // related table type | |||
buffer.putInt(INVALID_INDEX_NUMBER); // related index num | |||
buffer.putInt(0); // related table definition page number | |||
buffer.put((byte)0); // cascade updates flag | |||
buffer.put((byte)0); // cascade deletes flag | |||
buffer.put(idx.getType()); // index type flags | |||
byte idxType = idx.getType(); | |||
if(idxType != FOREIGN_KEY_INDEX_TYPE) { | |||
buffer.put((byte)0); // related table type | |||
buffer.putInt(INVALID_INDEX_NUMBER); // related index num | |||
buffer.putInt(0); // related table definition page number | |||
buffer.put((byte)0); // cascade updates flag | |||
buffer.put((byte)0); // cascade deletes flag | |||
} else { | |||
ForeignKeyReference reference = mutator.getForeignKey(idx); | |||
buffer.put(reference.getTableType()); // related table type | |||
buffer.putInt(reference.getOtherIndexNumber()); // related index num | |||
buffer.putInt(reference.getOtherTablePageNumber()); // related table definition page number | |||
byte updateFlags = 0; | |||
if(reference.isCascadeUpdates()) { | |||
updateFlags |= CASCADE_UPDATES_FLAG; | |||
} | |||
byte deleteFlags = 0; | |||
if(reference.isCascadeDeletes()) { | |||
deleteFlags |= CASCADE_DELETES_FLAG; | |||
} | |||
if(reference.isCascadeNullOnDelete()) { | |||
deleteFlags |= CASCADE_NULL_FLAG; | |||
} | |||
buffer.put(updateFlags); // cascade updates flag | |||
buffer.put(deleteFlags); // cascade deletes flag | |||
} | |||
buffer.put(idxType); // index type flags | |||
buffer.putInt(0); // unknown | |||
} | |||
@@ -50,8 +50,7 @@ public class RelationshipCreator extends DBMutator | |||
// - secondary index name "<PTable><STable>" | |||
// - add <name>1, <name>2 after names to make unique (index names and | |||
// relationship names) | |||
// FIXME | |||
// - relationships also have entry in MSysObjects table | |||
// - enforcing rel integrity can't have dupe cols | |||
public RelationshipCreator(DatabaseImpl database) | |||
{ | |||
@@ -148,6 +147,9 @@ public class RelationshipCreator extends DBMutator | |||
return; | |||
} | |||
// for now, we will require the unique index on the primary table (just | |||
// like access does). we could just create it auto-magically... | |||
// FIXME | |||
// - same number cols | |||
@@ -227,8 +229,8 @@ public class RelationshipCreator extends DBMutator | |||
return cols; | |||
} | |||
private static Collection<String> getColumnNames( | |||
List<ColumnImpl> cols, Collection<String> colNames) { | |||
private static List<String> getColumnNames(List<ColumnImpl> cols) { | |||
List<String> colNames = new ArrayList<String>(); | |||
for(ColumnImpl col : cols) { | |||
colNames.add(col.getName()); | |||
} | |||
@@ -239,12 +241,12 @@ public class RelationshipCreator extends DBMutator | |||
// a relationship is one to one if the two sides of the relationship have | |||
// unique indexes on the relevant columns | |||
IndexImpl idx = _primaryTable.findIndexForColumns( | |||
getColumnNames(_primaryCols, new HashSet<String>()), true); | |||
getColumnNames(_primaryCols), true); | |||
if(idx == null) { | |||
return false; | |||
} | |||
idx = _secondaryTable.findIndexForColumns( | |||
getColumnNames(_secondaryCols, new HashSet<String>()), true); | |||
getColumnNames(_secondaryCols), true); | |||
return (idx != null); | |||
} | |||
@@ -255,7 +257,7 @@ public class RelationshipCreator extends DBMutator | |||
tableName = table.getName(); | |||
} | |||
if(cols != null) { | |||
colNames = getColumnNames(cols, new ArrayList<String>()); | |||
colNames = getColumnNames(cols); | |||
} | |||
return CustomToStringStyle.valueBuilder(tableName) |
@@ -333,7 +333,8 @@ public class TableCreator extends TableMutator | |||
(col1.getFlags() == col2.getFlags())); | |||
} | |||
private String withErrorContext(String msg) { | |||
@Override | |||
protected String withErrorContext(String msg) { | |||
return msg + "(Table=" + getName() + ")"; | |||
} | |||
} |
@@ -50,18 +50,22 @@ public abstract class TableMutator extends DBMutator | |||
return _colOffsets; | |||
} | |||
public IndexImpl.ForeignKeyReference getForeignKey(IndexBuilder idx) { | |||
return null; | |||
} | |||
protected void validateColumn(Set<String> colNames, ColumnBuilder column) { | |||
// FIXME for now, we can't create complex columns | |||
if(column.getType() == DataType.COMPLEX_TYPE) { | |||
throw new UnsupportedOperationException( | |||
"Complex column creation is not yet implemented"); | |||
throw new UnsupportedOperationException(withErrorContext( | |||
"Complex column creation is not yet implemented")); | |||
} | |||
column.validate(getFormat()); | |||
if(!colNames.add(column.getName().toUpperCase())) { | |||
throw new IllegalArgumentException("duplicate column name: " + | |||
column.getName()); | |||
throw new IllegalArgumentException(withErrorContext( | |||
"duplicate column name: " + column.getName())); | |||
} | |||
setColumnSortOrder(column); | |||
@@ -72,26 +76,31 @@ public abstract class TableMutator extends DBMutator | |||
index.validate(colNames, getFormat()); | |||
if(!idxNames.add(index.getName().toUpperCase())) { | |||
throw new IllegalArgumentException("duplicate index name: " + | |||
index.getName()); | |||
throw new IllegalArgumentException(withErrorContext( | |||
"duplicate index name: " + index.getName())); | |||
} | |||
if(index.isPrimaryKey()) { | |||
if(foundPk[0]) { | |||
throw new IllegalArgumentException( | |||
"found second primary key index: " + index.getName()); | |||
throw new IllegalArgumentException(withErrorContext( | |||
"found second primary key index: " + index.getName())); | |||
} | |||
foundPk[0] = true; | |||
} else if(index.getType() == IndexImpl.FOREIGN_KEY_INDEX_TYPE) { | |||
if(getForeignKey(index) == null) { | |||
throw new IllegalArgumentException(withErrorContext( | |||
"missing foreign key info for " + index.getName())); | |||
} | |||
} | |||
} | |||
protected static void validateAutoNumberColumn(Set<DataType> autoTypes, | |||
ColumnBuilder column) | |||
protected void validateAutoNumberColumn(Set<DataType> autoTypes, | |||
ColumnBuilder column) | |||
{ | |||
if(!column.getType().isMultipleAutoNumberAllowed() && | |||
!autoTypes.add(column.getType())) { | |||
throw new IllegalArgumentException( | |||
throw new IllegalArgumentException(withErrorContext( | |||
"Can have at most one AutoNumber column of type " + column.getType() + | |||
" per table"); | |||
" per table")); | |||
} | |||
} | |||
@@ -112,6 +121,8 @@ public abstract class TableMutator extends DBMutator | |||
public abstract IndexDataState getIndexDataState(IndexBuilder idx); | |||
protected abstract String withErrorContext(String msg); | |||
/** | |||
* Maintains additional state used during column writing. | |||
* @usage _advanced_class_ |
@@ -45,6 +45,7 @@ public class TableUpdater extends TableMutator | |||
private List<Integer> _nextPages = new ArrayList<Integer>(1); | |||
private ColumnState _colState; | |||
private IndexDataState _idxDataState; | |||
private IndexImpl.ForeignKeyReference _fkReference; | |||
public TableUpdater(TableImpl table) { | |||
super(table.getDatabase()); | |||
@@ -89,6 +90,15 @@ public class TableUpdater extends TableMutator | |||
return ((idx == _index) ? _idxDataState : null); | |||
} | |||
void setForeignKey(IndexImpl.ForeignKeyReference fkReference) { | |||
_fkReference = fkReference; | |||
} | |||
@Override | |||
public IndexImpl.ForeignKeyReference getForeignKey(IndexBuilder idx) { | |||
return ((idx == _index) ? _fkReference : null); | |||
} | |||
int getAddedTdefLen() { | |||
return _addedTdefLen; | |||
} | |||
@@ -294,7 +304,8 @@ public class TableUpdater extends TableMutator | |||
(col2.getFlags() | ignoreColFlags))); | |||
} | |||
private String withErrorContext(String msg) { | |||
@Override | |||
protected String withErrorContext(String msg) { | |||
String objStr = ""; | |||
if(_column != null) { | |||
objStr = ";Column=" + _column.getName(); |