Merge fixes from Kodo 4.0 line.

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@453796 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2006-10-06 22:31:28 +00:00
parent ac1679d41c
commit 433475f6ad
9 changed files with 108 additions and 52 deletions

View File

@ -1634,7 +1634,7 @@ public abstract class MappingInfo {
if (col.getDefaultString() != null)
copy.setDefaultString(col.getDefaultString());
if (col.isNotNull() && !col.isPrimaryKey()
&& !isPrimitive(col.getJavaType()))
&& (!isPrimitive(col.getJavaType()) || isForeignKey(col)))
copy.setNotNull(true);
// set type name if not default
@ -1674,6 +1674,21 @@ public abstract class MappingInfo {
return copy;
}
/**
* Return whether the given column belongs to a foreign key.
*/
private static boolean isForeignKey(Column col)
{
if (col.getTable() == null)
return false;
ForeignKey[] fks = col.getTable().getForeignKeys();
for (int i = 0; i < fks.length; i++)
if (fks[i].containsColumn(col)
|| fks[i].containsConstantColumn(col))
return true;
return false;
}
/**
* Return true if the given type code represents a primitive.
*/

View File

@ -180,7 +180,7 @@ public class RelationFieldStrategy
OpenJPAStateManager rel = RelationStrategies.getStateManager
(sm.fetchObjectField(field.getIndex()), store.getContext());
if (field.getJoinDirection() == field.JOIN_INVERSE)
updateInverse(sm, rel, store, rm, sm);
updateInverse(sm, rel, store, rm);
else {
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
if (row != null)
@ -198,7 +198,7 @@ public class RelationFieldStrategy
if (field.getJoinDirection() == field.JOIN_INVERSE) {
nullInverse(sm, rm);
updateInverse(sm, rel, store, rm, sm);
updateInverse(sm, rel, store, rm);
} else {
Row row = field.getRow(sm, store, rm, Row.ACTION_UPDATE);
if (row != null)
@ -215,7 +215,7 @@ public class RelationFieldStrategy
if (sm.getLoaded().get(field.getIndex())) {
OpenJPAStateManager rel = RelationStrategies.getStateManager(sm.
fetchObjectField(field.getIndex()), store.getContext());
updateInverse(sm, rel, store, rm, null);
updateInverse(sm, rel, store, rm);
} else
nullInverse(sm, rm);
} else {
@ -241,6 +241,9 @@ public class RelationFieldStrategy
*/
private void nullInverse(OpenJPAStateManager sm, RowManager rm)
throws SQLException {
if (field.getUseClassCriteria())
return;
ForeignKey fk = field.getForeignKey();
ColumnIO io = field.getColumnIO();
if (!io.isAnyUpdatable(fk, true))
@ -260,11 +263,9 @@ public class RelationFieldStrategy
* with the given object.
*/
private void updateInverse(OpenJPAStateManager sm, OpenJPAStateManager rel,
JDBCStore store, RowManager rm, OpenJPAStateManager sm2)
JDBCStore store, RowManager rm)
throws SQLException {
// nothing to do if inverse is null or about to be deleted
//### should we throw an exception if the inverse is null?
if (rel == null || rel.isDeleted())
if (rel == null)
return;
ForeignKey fk = field.getForeignKey();
@ -272,11 +273,17 @@ public class RelationFieldStrategy
int action;
if (rel.isNew() && !rel.isFlushed()) {
if (sm2 == null || !io.isAnyInsertable(fk, false))
if (sm.isDeleted() || !io.isAnyInsertable(fk, false))
return;
action = Row.ACTION_INSERT;
} else if (rel.isDeleted()) {
if (rel.isFlushed() || !sm.isDeleted())
return;
action = Row.ACTION_DELETE;
} else {
if (!io.isAnyUpdatable(fk, sm2 == null))
if (sm.isDeleted())
sm = null;
if (!io.isAnyUpdatable(fk, sm == null))
return;
action = Row.ACTION_UPDATE;
}
@ -306,7 +313,7 @@ public class RelationFieldStrategy
row.wherePrimaryKey(rel);
// update the inverse pointer with our oid value
row.setForeignKey(fk, io, sm2);
row.setForeignKey(fk, io, sm);
}
public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,

View File

@ -216,23 +216,32 @@ public abstract class RelationToManyInverseKeyFieldStrategy
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if (field.getMappedBy() != null
|| field.getElementMapping().getUseClassCriteria())
if (field.getMappedBy() != null)
return;
// if nullable, null any existing inverse columns that refer to this obj
ValueMapping elem = field.getElementMapping();
ColumnIO io = elem.getColumnIO();
ForeignKey fk = elem.getForeignKey();
if (!io.isAnyUpdatable(fk, true))
if (!elem.getUseClassCriteria() && io.isAnyUpdatable(fk, true)) {
assertInversable();
Row row = rm.getAllRows(fk.getTable(), Row.ACTION_UPDATE);
row.setForeignKey(fk, io, null);
row.whereForeignKey(fk, sm);
rm.flushAllRows(row);
return;
}
if (!sm.getLoaded().get(field.getIndex()))
return;
// if the fk doesn't enforce it, null any existing inverse columns
// that refer to this obj
assertInversable();
Row row = rm.getAllRows(fk.getTable(), Row.ACTION_UPDATE);
row.setForeignKey(fk, io, null);
row.whereForeignKey(fk, sm);
rm.flushAllRows(row);
// update fk on each field value row
ClassMapping rel = field.getElementMapping().getTypeMapping();
StoreContext ctx = store.getContext();
Collection objs = toCollection(sm.fetchObject(field.getIndex()));
if (objs != null && !objs.isEmpty())
for (Iterator itr = objs.iterator(); itr.hasNext();)
updateInverse (ctx, itr.next(), rel, rm, sm, 0);
}
/**
@ -244,7 +253,7 @@ public abstract class RelationToManyInverseKeyFieldStrategy
throws SQLException {
OpenJPAStateManager invsm = RelationStrategies.getStateManager(inverse,
ctx);
if (invsm == null || invsm.isDeleted())
if (invsm == null)
return;
ValueMapping elem = field.getElementMapping();
@ -257,12 +266,21 @@ public abstract class RelationToManyInverseKeyFieldStrategy
boolean orderWriteable;
if (invsm.isNew() && !invsm.isFlushed()) {
// no need to null inverse columns of new instance
if (sm == null)
if (sm == null || sm.isDeleted())
return;
writeable = io.isAnyInsertable(fk, false);
orderWriteable = _orderInsert;
action = Row.ACTION_INSERT;
} else if (invsm.isDeleted()) {
// no need to null inverse columns of deleted instance
if (invsm.isFlushed() || sm == null || !sm.isDeleted())
return;
writeable = true;
orderWriteable = false;
action = Row.ACTION_DELETE;
} else {
if (sm != null && sm.isDeleted())
sm = null;
writeable = io.isAnyUpdatable(fk, sm == null);
orderWriteable = field.getOrderColumnIO().isUpdatable
(order, sm == null);

View File

@ -80,7 +80,8 @@ public class ColumnIO {
* Return true if any columns for the given key are insertable.
*/
public boolean isAnyInsertable(ForeignKey fk, boolean nullValue) {
return isAny(fk, _unInsertable, _unNullInsertable, nullValue);
return isAny(fk, _unInsertable, _unNullInsertable, nullValue)
&& (!nullValue || fk.isLogical() || isNullable(fk));
}
/**
@ -101,7 +102,8 @@ public class ColumnIO {
* Return true if all columns for the given key are insertable.
*/
public boolean isAllInsertable(ForeignKey fk, boolean nullValue) {
return isAll(fk, _unInsertable, _unNullInsertable, nullValue);
return isAll(fk, _unInsertable, _unNullInsertable, nullValue)
&& (!nullValue || fk.isLogical() || isNullable(fk));
}
/**
@ -152,7 +154,8 @@ public class ColumnIO {
* Return true if any columns for the given key are updatable.
*/
public boolean isAnyUpdatable(ForeignKey fk, boolean nullValue) {
return isAny(fk, _unUpdatable, _unNullUpdatable, nullValue);
return isAny(fk, _unUpdatable, _unNullUpdatable, nullValue)
&& (!nullValue || fk.isLogical() || isNullable(fk));
}
/**
@ -173,7 +176,8 @@ public class ColumnIO {
* Return true if all columns for the given key are updatable.
*/
public boolean isAllUpdatable(ForeignKey fk, boolean nullValue) {
return isAll(fk, _unUpdatable, _unNullUpdatable, nullValue);
return isAll(fk, _unUpdatable, _unNullUpdatable, nullValue)
&& (!nullValue || fk.isLogical() || isNullable(fk));
}
/**
@ -284,4 +288,15 @@ public class ColumnIO {
return property & ~(2 << col);
return property | (2 << col);
}
/**
* Whether the given foreign key is nullable.
*/
private boolean isNullable(ForeignKey fk) {
Column[] cols = fk.getColumns();
for (int i = 0; i < cols.length; i++)
if (cols[i].isNotNull() || cols[i].isPrimaryKey())
return false;
return true;
}
}

View File

@ -203,7 +203,7 @@ public class ForeignKey
seen.add(this);
for (int i = 0; i < cols.length; i++) {
for (int j = 0; j < fks.length; j++) {
if (fks[j].getPrimaryKeyColumn(cols[i]) == null)
if (!fks[j].containsColumn(cols[i]))
continue;
if (!seen.contains(fks[j])
&& fks[j].isPrimaryKeyAutoAssigned(seen)) {

View File

@ -390,10 +390,11 @@ public class PCEnhancer {
setter = _pc.getDeclaredMethod(getSetterName(fmds[i]),
new Class[]{ fmds[i].getDeclaredType() });
if (setter == null) {
if (returned == null)
if (returned == null) {
addViolation("property-no-setter",
new Object[]{ fmds[i] }, true);
else {
continue;
} else {
// create synthetic setter
setter = _pc.declareMethod(getSetterName(fmds[i]),
void.class, new Class[]{ fmds[i].getDeclaredType() });
@ -419,10 +420,9 @@ public class PCEnhancer {
_backingFields.put(setter.getName(), assigned.getName());
if (assigned != returned)
addViolation("property-setter-getter-mismatch",
new Object[]{ fmds[i], assigned.getName(),
(returned == null) ? null : returned.getName() },
false);
addViolation("property-setter-getter-mismatch", new Object[]
{ fmds[i], assigned.getName(), (returned == null)
? null : returned.getName() }, false);
}
}
}

View File

@ -1928,8 +1928,7 @@ public class BrokerImpl
exceps = add(exceps,
newFlushException(_store.flush(transactional)));
}
}
finally {
} finally {
_flags &= ~FLAG_STORE_FLUSHING;
if (reason == FLUSH_ROLLBACK)
@ -1942,21 +1941,24 @@ public class BrokerImpl
StateManagerImpl sm;
for (Iterator itr = transactional.iterator(); itr.hasNext();) {
sm = (StateManagerImpl) itr.next();
try {
// the state may have become transient, such as if
// it is embedded and the owner has been deleted during
// this flush process; bug #1100
if (sm.getPCState() == PCState.TRANSIENT)
continue;
// the state may have become transient, such as if
// it is embedded and the owner has been deleted during
// this flush process; bug #1100
if (sm.getPCState() == PCState.TRANSIENT)
continue;
sm.afterFlush(reason);
if (reason == FLUSH_INC) {
// if not about to clear trans cache for commit anyway,
// re-cache dirty objects with default soft refs; we
// don't need hard refs now that the changes have been
// flushed
sm.proxyFields(true, false);
_transCache.flushed(sm);
sm.afterFlush(reason);
if (reason == FLUSH_INC) {
// if not about to clear trans cache for commit
// anyway, re-cache dirty objects with default soft
// refs; we don't need hard refs now that the
// changes have been flushed
sm.proxyFields(true, false);
_transCache.flushed(sm);
}
} catch (Exception e) {
exceps = add(exceps, e);
}
}
}

View File

@ -194,7 +194,7 @@ public class DetachManager
* needed. Return true if flushed/stored, false otherwise.
*/
private static boolean flushDirty(StateManagerImpl sm) {
if (!sm.isDirty())
if (!sm.isDirty() || !sm.getBroker().isActive())
return false;
// only flush if there are actually any dirty non-flushed fields

View File

@ -332,7 +332,6 @@ public abstract class XMLMetaDataParser extends DefaultHandler
// even if we want to validate, specify that it won't happen
// if we have neither a DocType not a Schema
Object schemaSource = getSchemaSource();
if (schemaSource != null && _schemaBug) {
if (_log != null && _log.isInfoEnabled())
_log.info(_loc.get("parser-schema-bug"));