use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class JoinMapStore method getValue.
/**
* Method to retrieve a value from the Map given the key.
* @param ownerSM StateManager for the owner of the map.
* @param key The key to retrieve the value for.
* @return The value for this key
* @throws NoSuchElementException if the value for the key was not found
*/
protected V getValue(DNStateManager ownerSM, Object key) throws NoSuchElementException {
if (!validateKeyForReading(ownerSM, key)) {
return null;
}
ExecutionContext ec = ownerSM.getExecutionContext();
if (getStmtLocked == null) {
synchronized (// Make sure this completes in case another thread needs the same info
this) {
if (getStmtLocked == null) {
// Generate the "get" statement for unlocked and locked situations
SQLStatement sqlStmt = getSQLStatementForGet(ownerSM);
getStmtUnlocked = sqlStmt.getSQLText().toSQL();
sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
getStmtLocked = sqlStmt.getSQLText().toSQL();
}
}
}
Boolean serializeRead = ec.getTransaction().getSerializeRead();
String stmt = (serializeRead != null && serializeRead ? getStmtLocked : getStmtUnlocked);
Object value = null;
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
// Create the statement and supply owner/key params
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, stmt);
StatementMappingIndex ownerIdx = getMappingParams.getMappingForParameter("owner");
int numParams = ownerIdx.getNumberOfParameterOccurrences();
for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
ownerIdx.getMapping().setObject(ec, ps, ownerIdx.getParameterPositionsForOccurrence(paramInstance), ownerSM.getObject());
}
StatementMappingIndex keyIdx = getMappingParams.getMappingForParameter("key");
numParams = keyIdx.getNumberOfParameterOccurrences();
for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
keyIdx.getMapping().setObject(ec, ps, keyIdx.getParameterPositionsForOccurrence(paramInstance), key);
}
try {
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, stmt, ps);
try {
boolean found = rs.next();
if (!found) {
throw new NoSuchElementException();
}
if (valuesAreEmbedded || valuesAreSerialised) {
int[] param = new int[valueMapping.getNumberOfColumnMappings()];
for (int i = 0; i < param.length; ++i) {
param[i] = i + 1;
}
if (valueMapping instanceof SerialisedPCMapping || valueMapping instanceof SerialisedReferenceMapping || valueMapping instanceof EmbeddedKeyPCMapping) {
// Value = Serialised
int ownerFieldNumber = mapTable.getOwnerMemberMetaData().getAbsoluteFieldNumber();
value = valueMapping.getObject(ec, rs, param, ownerSM, ownerFieldNumber);
} else {
// Value = Non-PC
value = valueMapping.getObject(ec, rs, param);
}
} else if (valueMapping instanceof ReferenceMapping) {
// Value = Reference (Interface/Object)
int[] param = new int[valueMapping.getNumberOfColumnMappings()];
for (int i = 0; i < param.length; ++i) {
param[i] = i + 1;
}
value = valueMapping.getObject(ec, rs, param);
} else {
// Value = PC
ResultObjectFactory rof = new PersistentClassROF(ec, rs, false, ec.getFetchPlan(), getMappingDef, valueCmd, clr.classForName(valueType));
value = rof.getObject();
}
JDBCUtils.logWarnings(rs);
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056014", stmt), e);
}
return (V) value;
}
use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class ExpressionUtils method getEqualityExpressionForObjectExpressions.
/**
* Method to generate an equality/inequality expression between two ObjectExpressions.
* Either or both of the expressions can be ObjectLiterals.
* @param expr1 First expression
* @param expr2 Second expression
* @param equals Whether it is equality (otherwise inequality)
* @return The expression
*/
public static BooleanExpression getEqualityExpressionForObjectExpressions(ObjectExpression expr1, ObjectExpression expr2, boolean equals) {
SQLStatement stmt = expr1.stmt;
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
ClassLoaderResolver clr = stmt.getClassLoaderResolver();
ApiAdapter api = storeMgr.getApiAdapter();
if (expr1 instanceof ObjectLiteral && expr2 instanceof ObjectLiteral) {
// ObjectLiterall == ObjectLiteral
ObjectLiteral lit1 = (ObjectLiteral) expr1;
ObjectLiteral lit2 = (ObjectLiteral) expr2;
return new BooleanLiteral(stmt, expr1.mapping, equals ? lit1.getValue().equals(lit2.getValue()) : !lit1.getValue().equals(lit2.getValue()));
} else if (expr1 instanceof ObjectLiteral || expr2 instanceof ObjectLiteral) {
// ObjectExpression == ObjectLiteral, ObjectLiteral == ObjectExpression
BooleanExpression bExpr = null;
boolean secondIsLiteral = (expr2 instanceof ObjectLiteral);
Object value = (!secondIsLiteral ? ((ObjectLiteral) expr1).getValue() : ((ObjectLiteral) expr2).getValue());
if (IdentityUtils.isDatastoreIdentity(value)) {
// Object is an OID
Object valueKey = IdentityUtils.getTargetKeyForDatastoreIdentity(value);
JavaTypeMapping m = storeMgr.getSQLExpressionFactory().getMappingForType(valueKey.getClass(), false);
SQLExpression oidLit = exprFactory.newLiteral(stmt, m, valueKey);
if (equals) {
return (secondIsLiteral ? expr1.subExprs.getExpression(0).eq(oidLit) : expr2.subExprs.getExpression(0).eq(oidLit));
}
return (secondIsLiteral ? expr1.subExprs.getExpression(0).ne(oidLit) : expr2.subExprs.getExpression(0).ne(oidLit));
} else if (IdentityUtils.isSingleFieldIdentity(value)) {
// Object is SingleFieldIdentity
Object valueKey = IdentityUtils.getTargetKeyForSingleFieldIdentity(value);
// This used to use ((SingleFieldId)value).getTargetClass() for some reason, which contradicts the above datastore id method
JavaTypeMapping m = storeMgr.getSQLExpressionFactory().getMappingForType(valueKey.getClass(), false);
SQLExpression oidLit = exprFactory.newLiteral(stmt, m, valueKey);
if (equals) {
return (secondIsLiteral ? expr1.subExprs.getExpression(0).eq(oidLit) : expr2.subExprs.getExpression(0).eq(oidLit));
}
return (secondIsLiteral ? expr1.subExprs.getExpression(0).ne(oidLit) : expr2.subExprs.getExpression(0).ne(oidLit));
} else {
AbstractClassMetaData cmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(value.getClass(), clr);
if (cmd != null) {
// Value is a persistable object
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
// Application identity
if (api.getIdForObject(value) != null) {
// Persistent PC object (FCO)
// Cater for composite PKs and parts of PK being PC mappings, and recursion
ObjectExpression expr = (secondIsLiteral ? expr1 : expr2);
JavaTypeMapping[] pkMappingsApp = new JavaTypeMapping[expr.subExprs.size()];
Object[] pkFieldValues = new Object[expr.subExprs.size()];
int position = 0;
ExecutionContext ec = api.getExecutionContext(value);
JavaTypeMapping thisMapping = expr.mapping;
if (expr.mapping instanceof ReferenceMapping) {
// "InterfaceField == value", so pick an implementation mapping that is castable
thisMapping = null;
ReferenceMapping refMapping = (ReferenceMapping) expr.mapping;
JavaTypeMapping[] implMappings = refMapping.getJavaTypeMapping();
for (int i = 0; i < implMappings.length; i++) {
Class implType = clr.classForName(implMappings[i].getType());
if (implType.isAssignableFrom(value.getClass())) {
thisMapping = implMappings[i];
break;
}
}
}
if (thisMapping == null) {
// Just return a (1=0) since no implementation castable
return exprFactory.newLiteral(stmt, expr1.mapping, false).eq(exprFactory.newLiteral(stmt, expr1.mapping, true));
}
for (int i = 0; i < cmd.getNoOfPrimaryKeyMembers(); i++) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(cmd.getPKMemberPositions()[i]);
Object fieldValue = ExpressionUtils.getValueForMemberOfObject(ec, mmd, value);
JavaTypeMapping mapping = ((PersistableMapping) thisMapping).getJavaTypeMapping()[i];
if (mapping instanceof PersistableMapping) {
position = ExpressionUtils.populatePrimaryKeyMappingsValuesForPCMapping(pkMappingsApp, pkFieldValues, position, (PersistableMapping) mapping, cmd, mmd, fieldValue, storeMgr, clr);
} else {
pkMappingsApp[position] = mapping;
pkFieldValues[position] = fieldValue;
position++;
}
}
for (int i = 0; i < expr.subExprs.size(); i++) {
SQLExpression source = expr.subExprs.getExpression(i);
SQLExpression target = exprFactory.newLiteral(stmt, pkMappingsApp[i], pkFieldValues[i]);
BooleanExpression subExpr = (secondIsLiteral ? source.eq(target) : target.eq(source));
if (bExpr == null) {
bExpr = subExpr;
} else {
bExpr = bExpr.and(subExpr);
}
}
} else {
// PC object with no id (embedded, or transient maybe)
if (secondIsLiteral) {
for (int i = 0; i < expr1.subExprs.size(); i++) {
// Query should return nothing (so just do "(1 = 0)")
NucleusLogger.QUERY.warn(Localiser.msg("037003", value));
bExpr = exprFactory.newLiteral(stmt, expr1.mapping, false).eq(exprFactory.newLiteral(stmt, expr1.mapping, true));
// It is arguable that we should compare the id with null (as below)
/*bExpr = expr.eq(new NullLiteral(qs));*/
}
} else {
for (int i = 0; i < expr2.subExprs.size(); i++) {
// Query should return nothing (so just do "(1 = 0)")
NucleusLogger.QUERY.warn(Localiser.msg("037003", value));
bExpr = exprFactory.newLiteral(stmt, expr2.mapping, false).eq(exprFactory.newLiteral(stmt, expr2.mapping, true));
// It is arguable that we should compare the id with null (as below)
/*bExpr = expr.eq(new NullLiteral(qs));*/
}
}
}
// TODO Allow for !equals
return bExpr;
} else if (cmd.getIdentityType() == IdentityType.DATASTORE) {
// Datastore identity
SQLExpression source = (secondIsLiteral ? expr1.subExprs.getExpression(0) : expr2.subExprs.getExpression(0));
JavaTypeMapping mapping = (secondIsLiteral ? expr1.mapping : expr2.mapping);
Object objectId = api.getIdForObject(value);
if (objectId == null) {
// PC object with no id (embedded, or transient maybe)
// Query should return nothing (so just do "(1 = 0)")
NucleusLogger.QUERY.warn(Localiser.msg("037003", value));
// TODO Allow for !equals
return exprFactory.newLiteral(stmt, mapping, false).eq(exprFactory.newLiteral(stmt, mapping, true));
// It is arguable that we should compare the id with null (as below)
/*bExpr = expr.eq(new NullLiteral(qs));*/
}
Object objectIdKey = IdentityUtils.getTargetKeyForDatastoreIdentity(objectId);
JavaTypeMapping m = storeMgr.getSQLExpressionFactory().getMappingForType(objectIdKey.getClass(), false);
SQLExpression oidExpr = exprFactory.newLiteral(stmt, m, objectIdKey);
if (equals) {
return source.eq(oidExpr);
}
return source.ne(oidExpr);
}
} else {
// No metadata, so we either have an application identity, or any object
String pcClassName = storeMgr.getClassNameForObjectID(value, clr, null);
if (pcClassName != null) {
// Object is an application identity
cmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(pcClassName, clr);
return (secondIsLiteral ? ExpressionUtils.getAppIdEqualityExpression(value, expr1, storeMgr, clr, cmd, null, null) : ExpressionUtils.getAppIdEqualityExpression(value, expr2, storeMgr, clr, cmd, null, null));
// TODO Allow for !equals
}
// Value not persistable nor an identity, so return nothing "(1 = 0)"
return exprFactory.newLiteral(stmt, expr1.mapping, false).eq(exprFactory.newLiteral(stmt, expr1.mapping, true));
// TODO Allow for !equals
}
}
} else {
// ObjectExpression == ObjectExpression
BooleanExpression resultExpr = null;
for (int i = 0; i < expr1.subExprs.size(); i++) {
SQLExpression sourceExpr = expr1.subExprs.getExpression(i);
SQLExpression targetExpr = expr2.subExprs.getExpression(i);
if (resultExpr == null) {
resultExpr = sourceExpr.eq(targetExpr);
} else {
resultExpr = resultExpr.and(sourceExpr.eq(targetExpr));
}
}
if (!equals) {
resultExpr = new BooleanExpression(Expression.OP_NOT, resultExpr != null ? resultExpr.encloseInParentheses() : null);
}
return resultExpr;
}
return null;
}
use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class ExpressionUtils method checkAndCorrectLiteralForConsistentMappingsForBooleanComparison.
protected static void checkAndCorrectLiteralForConsistentMappingsForBooleanComparison(SQLLiteral lit, SQLExpression expr) {
JavaTypeMapping litMapping = ((SQLExpression) lit).getJavaTypeMapping();
JavaTypeMapping exprMapping = expr.getJavaTypeMapping();
if (exprMapping == null || exprMapping.getNumberOfColumnMappings() == 0) {
return;
}
if (litMapping instanceof PersistableMapping && exprMapping instanceof ReferenceMapping) {
// Can compare implementation with reference
return;
}
if (litMapping instanceof SingleCollectionMapping) {
return;
}
boolean needsUpdating = false;
if (litMapping.getNumberOfColumnMappings() != exprMapping.getNumberOfColumnMappings()) {
needsUpdating = true;
} else {
for (int i = 0; i < litMapping.getNumberOfColumnMappings(); i++) {
ColumnMapping colMapping = litMapping.getColumnMapping(i);
if (colMapping == null || colMapping.getClass() != exprMapping.getColumnMapping(i).getClass()) {
needsUpdating = true;
break;
}
}
}
if (needsUpdating) {
// Make sure a change in mapping makes sense
// This embeds some type conversion rules and would be nice to avoid it
Class litMappingCls = litMapping.getJavaType();
Class mappingCls = exprMapping.getJavaType();
if (litMappingCls == Double.class || litMappingCls == Float.class || litMappingCls == BigDecimal.class) {
// Comparison between integral, and floating point parameter, so don't convert the param mapping
if (mappingCls == Integer.class || mappingCls == Long.class || mappingCls == Short.class || mappingCls == BigInteger.class || mappingCls == Byte.class) {
if (litMappingCls == BigDecimal.class) {
// BigDecimal seems to need to have the value put into SQL directly
// (see JDO TCK "Equality" test when comparing with integer-based field).
expr.getSQLStatement().getQueryGenerator().useParameterExpressionAsLiteral(lit);
}
needsUpdating = false;
}
}
if (litMappingCls == Byte.class && mappingCls != Byte.class) {
needsUpdating = false;
}
}
if (needsUpdating) {
NucleusLogger.QUERY.debug("Updating mapping of " + lit + " to be " + expr.getJavaTypeMapping());
((SQLExpression) lit).setJavaTypeMapping(expr.getJavaTypeMapping());
}
}
use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class ResultSetGetter method processSubObjectFields.
private Object processSubObjectFields(JavaTypeMapping mapping, Class fieldType, StatementClassMapping relationMappings) {
ClassLoaderResolver clr = ec.getClassLoaderResolver();
AbstractClassMetaData relatedCmd = ec.getMetaDataManager().getMetaDataForClass(fieldType, clr);
if (mapping instanceof ReferenceMapping) {
// Special case where we have a ReferenceMapping and single implementation with FK
ReferenceMapping refMapping = (ReferenceMapping) mapping;
if (refMapping.getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
JavaTypeMapping[] subMappings = refMapping.getJavaTypeMapping();
if (subMappings != null && subMappings.length == 1) {
relatedCmd = ec.getMetaDataManager().getMetaDataForClass(subMappings[0].getType(), clr);
fieldType = clr.classForName(subMappings[0].getType());
}
}
}
ResultObjectFactory relationROF = new PersistentClassROF(ec, rs, false, ec.getFetchPlan(), relationMappings, relatedCmd, fieldType);
return relationROF.getObject();
}
use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class TableUtils method getForeignKeysForReferenceField.
/**
* Convenience method to add foreign-keys for the specified reference field.
* Adds FKs from the column(s) in this table to the ID column(s) of the PC table of the implementation type.
* @param fieldMapping The field mapping (in this table)
* @param mmd MetaData for this field
* @param autoMode Whether we are in auto-create mode
* @param storeMgr Store Manager
* @param clr ClassLoader resolver
* @return The foreign key(s) created
*/
public static Collection getForeignKeysForReferenceField(JavaTypeMapping fieldMapping, AbstractMemberMetaData mmd, boolean autoMode, RDBMSStoreManager storeMgr, ClassLoaderResolver clr) {
final ReferenceMapping refMapping = (ReferenceMapping) fieldMapping;
JavaTypeMapping[] refJavaTypeMappings = refMapping.getJavaTypeMapping();
List fks = new ArrayList();
for (int i = 0; i < refJavaTypeMappings.length; i++) {
// If the implementation is of a PC class, look to add a FK to the PC class table
final JavaTypeMapping implMapping = refJavaTypeMappings[i];
if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(implMapping.getType(), clr) != null && implMapping.getNumberOfColumnMappings() > 0) {
DatastoreClass referencedTable = storeMgr.getDatastoreClass(implMapping.getType(), clr);
if (referencedTable != null) {
ForeignKeyMetaData fkmd = mmd.getForeignKeyMetaData();
if ((fkmd != null && fkmd.getDeleteAction() != ForeignKeyAction.NONE) || autoMode) {
// Either has been specified by user, or using autoMode, so add FK
ForeignKey fk = new ForeignKey(implMapping, storeMgr.getDatastoreAdapter(), referencedTable, true);
// Does nothing when no FK MetaData
fk.setForMetaData(fkmd);
fks.add(fk);
}
}
}
}
return fks;
}
Aggregations