use of org.datanucleus.ClassLoaderResolver in project datanucleus-rdbms by datanucleus.
the class ObjectExpression method cast.
/**
* Cast operator. Called when the query contains "(type)obj" where "obj" is this object.
* @param expr Expression representing the type to cast to
* @return Scalar expression representing the cast object.
*/
public SQLExpression cast(SQLExpression expr) {
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
ClassLoaderResolver clr = stmt.getClassLoaderResolver();
// Extract cast type
String castClassName = (String) ((StringLiteral) expr).getValue();
Class type = null;
try {
type = stmt.getQueryGenerator().resolveClass(castClassName);
} catch (ClassNotResolvedException cnre) {
type = null;
}
if (type == null) {
throw new NucleusUserException(Localiser.msg("037017", castClassName));
}
// Extract type of this object and check obvious conditions
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
Class memberType = clr.classForName(mapping.getType());
if (!memberType.isAssignableFrom(type) && !type.isAssignableFrom(memberType)) {
// object type and cast type are totally incompatible, so just return false
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, false).eq(exprFactory.newLiteral(stmt, m, true));
} else if (memberType == type) {
// Just return this expression since it is already castable
return this;
}
if (mapping instanceof EmbeddedMapping) {
// Don't support embedded casts
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, false).eq(exprFactory.newLiteral(stmt, m, true));
} else if (mapping instanceof ReferenceMapping) {
// This expression will be for the table containing the reference so need to join now
ReferenceMapping refMapping = (ReferenceMapping) mapping;
if (refMapping.getMappingStrategy() != ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
throw new NucleusUserException("Impossible to do cast of interface to " + type.getName() + " since interface is persisted as embedded String." + " Use per-implementation mapping to allow this query");
}
JavaTypeMapping[] implMappings = refMapping.getJavaTypeMapping();
for (int i = 0; i < implMappings.length; i++) {
Class implType = clr.classForName(implMappings[i].getType());
if (type.isAssignableFrom(implType)) {
DatastoreClass castTable = storeMgr.getDatastoreClass(type.getName(), clr);
SQLTable castSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, table, implMappings[i], refMapping, castTable, null, castTable.getIdMapping(), null, null, null, true, null);
return exprFactory.newExpression(stmt, castSqlTbl, castTable.getIdMapping());
}
}
// No implementation matching this cast type, so return false
NucleusLogger.QUERY.warn("Unable to process cast of interface field to " + type.getName() + " since it has no implementations that match that type");
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, false).eq(exprFactory.newLiteral(stmt, m, true));
} else if (mapping instanceof PersistableMapping) {
// Check if there is already the cast table in the current table group
DatastoreClass castTable = storeMgr.getDatastoreClass(type.getName(), clr);
SQLTable castSqlTbl = stmt.getTable(castTable, table.getGroupName());
if (castSqlTbl == null) {
// Join not present, so join to the cast table
castSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, table, table.getTable().getIdMapping(), castTable, null, castTable.getIdMapping(), null, table.getGroupName());
}
if (castSqlTbl == table) {
AbstractClassMetaData castCmd = storeMgr.getMetaDataManager().getMetaDataForClass(type, clr);
if (castCmd.hasDiscriminatorStrategy()) {
// TODO How do we handle this? If this is part of the filter then need to hang a BooleanExpression off the ObjectExpression and apply later.
// If this is part of the result, do we just return null when this is not the right type?
NucleusLogger.QUERY.warn(">> Currently do not support adding restriction on discriminator for table=" + table + " to " + type);
}
}
// Return an expression based on the cast table
return exprFactory.newExpression(stmt, castSqlTbl, castTable.getIdMapping());
} else {
// TODO Handle other casts
}
// TODO Implement cast (left outer join to table of type, then return new ObjectExpression)
throw new NucleusUserException("Dont currently support ObjectExpression.cast(" + type + ")");
}
use of org.datanucleus.ClassLoaderResolver 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.getNumberOfColumnMappings();
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).getValueForColumnMapping(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.ClassLoaderResolver 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.ClassLoaderResolver in project datanucleus-rdbms by datanucleus.
the class SQLText method applyParametersToStatement.
/**
* Method to set the parameters in the supplied PreparedStatement using their mappings and
* provided values.
* @param ec execution context
* @param ps The PreparedStatement
*/
public void applyParametersToStatement(ExecutionContext ec, PreparedStatement ps) {
if (parameters != null) {
int num = 1;
Iterator<SQLStatementParameter> i = parameters.iterator();
while (i.hasNext()) {
SQLStatementParameter param = i.next();
JavaTypeMapping mapping = param.getMapping();
if (mapping != null) {
Object value = param.getValue();
if (param.getColumnNumber() >= 0) {
Object colValue = null;
if (value != null) {
// Parameter is for a particular column of the overall object/mapping
// so assume that the object is persistable (or id of persistable)
ClassLoaderResolver clr = ec.getClassLoaderResolver();
AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(mapping.getType(), clr);
RDBMSStoreManager storeMgr = mapping.getStoreManager();
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
colValue = mapping.getValueForColumnMapping(ec.getNucleusContext(), param.getColumnNumber(), value);
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
colValue = SQLStatementHelper.getValueForPrimaryKeyIndexOfObjectUsingReflection(value, param.getColumnNumber(), cmd, storeMgr, clr);
}
}
mapping.getColumnMapping(param.getColumnNumber()).setObject(ps, num, colValue);
num++;
} else {
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
if (mapping.getNumberOfColumnMappings() > 0) {
num += mapping.getNumberOfColumnMappings();
} else {
num += 1;
}
}
}
}
}
}
use of org.datanucleus.ClassLoaderResolver in project datanucleus-core by datanucleus.
the class MetaDataManagerImpl method loadMetadataFiles.
/* (non-Javadoc)
* @see org.datanucleus.metadata.MetaDataManager#loadMetadataFiles(java.lang.String[], java.lang.ClassLoader)
*/
@Override
public FileMetaData[] loadMetadataFiles(String[] metadataFiles, ClassLoader loader) {
if (!allowMetaDataLoad) {
return null;
}
boolean originatingLoadCall = false;
if (listenersLoadedMetaData == null && listeners != null) {
originatingLoadCall = true;
listenersLoadedMetaData = new ArrayList<AbstractClassMetaData>();
}
try {
if (originatingLoadCall) {
updateLock.lock();
}
if (NucleusLogger.METADATA.isDebugEnabled()) {
NucleusLogger.METADATA.debug(Localiser.msg("044005", StringUtils.objectArrayToString(metadataFiles)));
}
// Load MetaData files - will throw NucleusUserException if problems found
ClassLoaderResolver clr = nucleusContext.getClassLoaderResolver(loader);
Collection fileMetaData = loadFiles(metadataFiles, clr);
if (!fileMetaData.isEmpty()) {
// Populate/Initialise all loaded FileMetaData
initialiseFileMetaDataForUse(fileMetaData, clr);
}
if (NucleusLogger.METADATA.isDebugEnabled()) {
NucleusLogger.METADATA.debug(Localiser.msg("044010"));
}
if (originatingLoadCall) {
processListenerLoadingCall();
}
return (FileMetaData[]) fileMetaData.toArray(new FileMetaData[fileMetaData.size()]);
} finally {
if (originatingLoadCall) {
updateLock.unlock();
}
}
}
Aggregations