Patch from Zell to properly walk the inheritance tree and aggregate all

index-related annotations.
This commit is contained in:
Michael Bayne
2007-08-08 23:58:43 +00:00
parent 30681979ea
commit f9b6414270
@@ -31,7 +31,6 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -489,13 +488,18 @@ public class DepotMarshaller<T extends PersistentRecord>
fm.init(builder);
}
// if we have no table (i.e. we're a computed entity), we have nothing to create
if (getTableName() == null) {
return;
}
// figure out the list of fields that correspond to actual table columns and generate the
// SQL used to create and migrate our table (unless we're a computed entity)
_columnFields = new String[_allFields.length];
String[] declarations = new String[_allFields.length];
int jj = 0;
for (int ii = 0; ii < _allFields.length; ii++) {
@SuppressWarnings("unchecked") FieldMarshaller<T> fm = _fields.get(_allFields[ii]);
FieldMarshaller fm = _fields.get(_allFields[ii]);
// include all persistent non-computed fields
String colDef = fm.getColumnDefinition();
if (colDef != null) {
@@ -507,31 +511,6 @@ public class DepotMarshaller<T extends PersistentRecord>
_columnFields = ArrayUtil.splice(_columnFields, jj);
declarations = ArrayUtil.splice(declarations, jj);
// if we have no table (i.e. we're a computed entity), we have nothing to create
if (getTableName() == null) {
return;
}
// add any additional unique constraints
String[][] uniqueConstraintColumns = null;
Table table = _pclass.getAnnotation(Table.class);
if (table != null) {
UniqueConstraint[] uCons = table.uniqueConstraints();
uniqueConstraintColumns = new String[uCons.length][];
for (int kk = 0; kk < uCons.length; kk ++) {
String[] columns = uCons[kk].fieldNames();
for (int ii = 0; ii < columns.length; ii ++) {
FieldMarshaller fm = getFieldMarshaller(columns[ii]);
if (fm == null) {
throw new IllegalArgumentException(
"Unknown field in @UniqueConstraint: " + columns[ii]);
}
columns[ii] = fm.getColumnName();
}
uniqueConstraintColumns[kk] = columns;
}
}
// if we did not find a schema version field, complain
if (_schemaVersion < 0) {
log.warning("Unable to read " + _pclass.getName() + "." + SCHEMA_VERSION_FIELD +
@@ -558,13 +537,12 @@ public class DepotMarshaller<T extends PersistentRecord>
}
});
final Entity entity = _pclass.getAnnotation(Entity.class);
// compute relevant information from our persistent record, too
final RecordMetaData rMeta = new RecordMetaData(_pclass, _fields);
// if the table does not exist, create it
if (!metaData.tableExists) {
final String[] fDeclarations = declarations;
final String[][] fUniqueConstraintColumns = uniqueConstraintColumns;
ctx.invoke(new Modifier() {
public int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
// create the table
@@ -579,15 +557,19 @@ public class DepotMarshaller<T extends PersistentRecord>
primaryKeyColumns[ii] = _pkColumns.get(ii).getColumnName();
}
}
String[][] uniqueConCols = new String[rMeta.uniqueConstraints.size()][];
int kk = 0;
for (Set<String> colSet : rMeta.uniqueConstraints) {
uniqueConCols[kk++] = colSet.toArray(new String[colSet.size()]);
}
liaison.createTableIfMissing(conn, getTableName(), columns, fDeclarations,
fUniqueConstraintColumns, primaryKeyColumns);
uniqueConCols, primaryKeyColumns);
// add its indexen
if (entity != null) {
for (Index idx : entity.indices()) {
liaison.addIndexToTable(
conn, getTableName(), idx.columns(), idx.name(), idx.unique());
}
for (Index idx : rMeta.indices.values()) {
liaison.addIndexToTable(
conn, getTableName(), idx.columns(),
getTableName() + "_" + idx.name(), idx.unique());
}
if (_keyGenerator != null) {
_keyGenerator.init(conn, liaison);
@@ -708,15 +690,16 @@ public class DepotMarshaller<T extends PersistentRecord>
}
// add any missing indices
for (final Index index : (entity == null ? new Index[0] : entity.indices())) {
if (metaData.indexColumns.containsKey(index.name())) {
metaData.indexColumns.remove(index.name());
for (final Index index : rMeta.indices.values()) {
final String ixName = getTableName() + "_" + index.name();
if (metaData.indexColumns.containsKey(ixName)) {
metaData.indexColumns.remove(ixName);
continue;
}
ctx.invoke(new Modifier() {
public int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
liaison.addIndexToTable(
conn, getTableName(), index.columns(), index.name(), index.unique());
conn, getTableName(), index.columns(), ixName, index.unique());
return 0;
}
});
@@ -725,37 +708,32 @@ public class DepotMarshaller<T extends PersistentRecord>
// to get the @Table(uniqueIndices...) indices, we use our clever set of column name sets
Set<Set<String>> uniqueIndices = new HashSet<Set<String>>(metaData.indexColumns.values());
if (getTableName() != null && table != null) {
for (UniqueConstraint constraint : table.uniqueConstraints()) {
// for each given UniqueConstraint, build a new column set
Set<String> colSet = new HashSet<String>(Arrays.asList(constraint.fieldNames()));
// and check if the table contained this set
if (uniqueIndices.contains(colSet)) {
continue; // good, carry on
}
// else build the index; we'll use mysql's convention of naming it after a column,
// with possible _N disambiguation; luckily we made a copy of the index names!
String indexName = colSet.iterator().next();
if (indicesCopy.contains(indexName)) {
int num = 1;
indexName += "_";
while (indicesCopy.contains(indexName + num)) {
num ++;
}
indexName += num;
}
final String[] colArr = colSet.toArray(new String[colSet.size()]);
final String fName = indexName;
ctx.invoke(new Modifier() {
public int invoke (Connection conn, DatabaseLiaison dl) throws SQLException {
dl.addIndexToTable(conn, getTableName(), colArr, fName, true);
return 0;
}
});
for (Set<String> colSet : rMeta.uniqueConstraints) {
// check if the table contained this set
if (uniqueIndices.contains(colSet)) {
continue; // good, carry on
}
// else build the index; we'll use mysql's convention of naming it after a column,
// with possible _N disambiguation; luckily we made a copy of the index names!
String indexName = colSet.iterator().next();
if (indicesCopy.contains(indexName)) {
int num = 1;
indexName += "_";
while (indicesCopy.contains(indexName + num)) {
num ++;
}
indexName += num;
}
final String[] colArr = colSet.toArray(new String[colSet.size()]);
final String fName = indexName;
ctx.invoke(new Modifier() {
public int invoke (Connection conn, DatabaseLiaison dl) throws SQLException {
dl.addIndexToTable(conn, getTableName(), colArr, fName, true);
return 0;
}
});
}
// we do not auto-remove columns but rather require that EntityMigration.Drop records be
@@ -867,6 +845,51 @@ public class DepotMarshaller<T extends PersistentRecord>
}
}
protected static class RecordMetaData
{
public Map<String, Index> indices = new HashMap<String, Index>();
public Set<Set<String>> uniqueConstraints = new HashSet<Set<String>>();
public RecordMetaData (Class<?> pClass, Map<String, FieldMarshaller> fmap)
{
recurse(pClass, fmap);
}
protected void recurse (Class<?> pClass, Map<String, FieldMarshaller> fmap)
{
// recurse first so subclass definitions overwrite superclass ones
Class<?> superClass = pClass.getSuperclass();
if (PersistentRecord.class.isAssignableFrom(superClass) &&
!PersistentRecord.class.equals(superClass)) {
recurse(superClass, fmap);
}
Table table = pClass.getAnnotation(Table.class);
if (table != null) {
for (UniqueConstraint constraint : table.uniqueConstraints()) {
String[] fields = constraint.fieldNames();
Set<String> colSet = new HashSet<String>();
for (int ii = 0; ii < fields.length; ii ++) {
FieldMarshaller fm = fmap.get(fields[ii]);
if (fm == null) {
throw new IllegalArgumentException(
"Unknown unique constraint field: " + fields[ii]);
}
colSet.add(fm.getColumnName());
}
uniqueConstraints.add(colSet);
}
}
Entity entity = pClass.getAnnotation(Entity.class);
if (entity != null) {
for (Index index : entity.indices()) {
indices.put(index.name(), index);
}
}
}
}
/** The persistent object class that we manage. */
protected Class<T> _pclass;