use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.
the class ObjectLiteral method addSubexpressionsForValue.
/**
* Method to add subExprs for the supplied mapping, consistent with the supplied value.
* The value can be a persistent object, or an identity (datastore/application).
* @param value The value
* @param mapping The mapping
*/
private void addSubexpressionsForValue(Object value, JavaTypeMapping mapping) {
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
ClassLoaderResolver clr = stmt.getClassLoaderResolver();
String objClassName = value.getClass().getName();
if (mapping instanceof PersistableMapping) {
objClassName = mapping.getType();
} else if (IdentityUtils.isDatastoreIdentity(value)) {
objClassName = IdentityUtils.getTargetClassNameForIdentity(value);
}
AbstractClassMetaData cmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(objClassName, clr);
if (cmd != null) {
// Literal representing a persistable object (or its identity)
int numCols = mapping.getNumberOfDatastoreMappings();
for (int i = 0; i < numCols; i++) {
ColumnExpression colExpr = null;
if (parameterName == null && mapping instanceof PersistableMapping) {
// Literal is a persistable object
Object colValue = ((PersistableMapping) mapping).getValueForDatastoreMapping(stmt.getRDBMSManager().getNucleusContext(), i, value);
colExpr = new ColumnExpression(stmt, colValue);
} else {
// Literal is a parameter
colExpr = new ColumnExpression(stmt, parameterName, mapping, value, i);
}
subExprs.addExpression(colExpr);
}
} else {
// TODO Support OID
NucleusLogger.GENERAL.error(">> ObjectLiteral doesn't yet cater for values of type " + StringUtils.toJVMIDString(value));
}
}
use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping 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.getNumberOfDatastoreMappings() == 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.getNumberOfDatastoreMappings() != exprMapping.getNumberOfDatastoreMappings()) {
needsUpdating = true;
} else {
for (int i = 0; i < litMapping.getNumberOfDatastoreMappings(); i++) {
DatastoreMapping colMapping = litMapping.getDatastoreMapping(i);
if (colMapping == null || colMapping.getClass() != exprMapping.getDatastoreMapping(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.PersistableMapping 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.PersistableMapping in project datanucleus-rdbms by datanucleus.
the class ClassTable method initializeIDMapping.
/**
* Initialize the ID Mapping.
* For datastore identity this will be a PCMapping that contains the OIDMapping.
* For application identity this will be a PCMapping that contains the PK mapping(s).
*/
private void initializeIDMapping() {
if (idMapping != null) {
return;
}
final PersistableMapping mapping = new PersistableMapping();
mapping.setTable(this);
mapping.initialize(getStoreManager(), cmd.getFullClassName());
if (getIdentityType() == IdentityType.DATASTORE) {
mapping.addJavaTypeMapping(datastoreIdMapping);
} else if (getIdentityType() == IdentityType.APPLICATION) {
for (int i = 0; i < pkMappings.length; i++) {
mapping.addJavaTypeMapping(pkMappings[i]);
}
} else {
// Nothing to do for nondurable since no identity
}
idMapping = mapping;
}
use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.
the class ElementContainerTable method getExpectedForeignKeys.
/**
* Accessor for the expected foreign keys for this table.
* @param clr The ClassLoaderResolver
* @return The expected foreign keys.
*/
public List getExpectedForeignKeys(ClassLoaderResolver clr) {
assertIsInitialized();
// Find the mode that we're operating in for FK addition
boolean autoMode = false;
if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus")) {
autoMode = true;
}
ArrayList foreignKeys = new ArrayList();
try {
// FK from join table to owner table
DatastoreClass referencedTable = storeMgr.getDatastoreClass(ownerType, clr);
if (referencedTable != null) {
// Single owner table, so add a single FK to the owner as appropriate
ForeignKey fk = getForeignKeyToOwner(referencedTable, autoMode);
if (fk != null) {
foreignKeys.add(fk);
}
} else {
// No single owner so we don't bother with the FK since referential integrity by FK cannot work
// if we don't have a single owner at the other end of the FK(s).
}
// FK from join table to element table(s)
if (elementMapping instanceof SerialisedPCMapping) {
// Do nothing since no element table
} else if (elementMapping instanceof EmbeddedElementPCMapping) {
// Add any FKs for the fields of the (embedded) element
EmbeddedElementPCMapping embMapping = (EmbeddedElementPCMapping) elementMapping;
for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
AbstractMemberMetaData embFmd = embFieldMapping.getMemberMetaData();
if (ClassUtils.isReferenceType(embFmd.getType()) && embFieldMapping instanceof ReferenceMapping) {
// Field is a reference type, so add a FK to the table of the PC for each PC implementation
Collection fks = TableUtils.getForeignKeysForReferenceField(embFieldMapping, embFmd, autoMode, storeMgr, clr);
foreignKeys.addAll(fks);
} else if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(embFmd.getType(), clr) != null && embFieldMapping.getNumberOfDatastoreMappings() > 0 && embFieldMapping instanceof PersistableMapping) {
// Field is for a PC class with the FK at this side, so add a FK to the table of this PC
ForeignKey fk = TableUtils.getForeignKeyForPCField(embFieldMapping, embFmd, autoMode, storeMgr, clr);
if (fk != null) {
foreignKeys.add(fk);
}
}
}
} else if (elementMapping instanceof ReferenceMapping) {
JavaTypeMapping[] implJavaTypeMappings = ((ReferenceMapping) elementMapping).getJavaTypeMapping();
for (int i = 0; i < implJavaTypeMappings.length; i++) {
JavaTypeMapping implMapping = implJavaTypeMappings[i];
if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(implMapping.getType(), clr) != null && implMapping.getNumberOfDatastoreMappings() > 0) {
referencedTable = storeMgr.getDatastoreClass(implMapping.getType(), clr);
if (referencedTable != null) {
ForeignKey fk = getForeignKeyToElement(referencedTable, autoMode, implMapping);
if (fk != null) {
foreignKeys.add(fk);
}
}
}
}
} else {
referencedTable = storeMgr.getDatastoreClass(getElementType(), clr);
if (referencedTable != null) {
ForeignKey fk = getForeignKeyToElement(referencedTable, autoMode, elementMapping);
if (fk != null) {
foreignKeys.add(fk);
}
} else {
// Either no element table or multiple (where the user has element with "subclass-table" strategy, or using "complete-table")
// so do nothing since referential integrity will not allow multiple FKs.
}
}
} catch (NoTableManagedException e) {
// expected when no table exists
}
return foreignKeys;
}
Aggregations