use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.
the class FetchRequest method processMembersOfClass.
/**
* Method to process the supplied members of the class, adding to the SQLStatement as required.
* Can recurse if some of the requested fields are persistent objects in their own right, so we
* take the opportunity to retrieve some of their fields.
* @param sqlStatement Statement being built
* @param mmds Meta-data for the required fields/properties
* @param table The table to look for member mappings
* @param sqlTbl The table in the SQL statement to use for selects
* @param mappingDef Mapping definition for the result
* @param fetchCallbacks Any additional required callbacks are added here
* @param clr ClassLoader resolver
* @return Number of fields being fetched
*/
protected int processMembersOfClass(SelectStatement sqlStatement, AbstractMemberMetaData[] mmds, DatastoreClass table, SQLTable sqlTbl, StatementClassMapping mappingDef, Collection fetchCallbacks, ClassLoaderResolver clr) {
int number = 0;
if (mmds != null) {
for (int i = 0; i < mmds.length; i++) {
// Get the mapping (in this table, or super-table)
AbstractMemberMetaData mmd = mmds[i];
JavaTypeMapping mapping = table.getMemberMapping(mmd);
if (mapping != null) {
if (!mmd.isPrimaryKey() && mapping.includeInFetchStatement()) {
// The depth is the number of levels down to load in this statement.
// 0 is to load just this objects fields (as with JPOX, and DataNucleus up to 1.1.3)
int depth = 0;
AbstractMemberMetaData mmdToUse = mmd;
JavaTypeMapping mappingToUse = mapping;
if (mapping instanceof SingleCollectionMapping) {
// Check the wrapped type
mappingToUse = ((SingleCollectionMapping) mapping).getWrappedMapping();
mmdToUse = ((SingleCollectionMapping) mapping).getWrappedMapping().getMemberMetaData();
}
if (mappingToUse instanceof PersistableMapping) {
// Special case of 1-1/N-1 where we know the other side type so know what to join to, hence can load the related object
depth = 1;
if (Modifier.isAbstract(mmdToUse.getType().getModifiers())) {
String typeName = mmdToUse.getTypeName();
DatastoreClass relTable = table.getStoreManager().getDatastoreClass(typeName, clr);
if (relTable != null && relTable.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, false) == null) {
// 1-1 relation to base class with no discriminator and has subclasses
// hence no way of determining the exact type, hence no point in fetching it
String[] subclasses = table.getStoreManager().getMetaDataManager().getSubclassesForClass(typeName, false);
if (subclasses != null && subclasses.length > 0) {
depth = 0;
}
}
}
} else if (mappingToUse instanceof ReferenceMapping) {
ReferenceMapping refMapping = (ReferenceMapping) mappingToUse;
if (refMapping.getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
JavaTypeMapping[] subMappings = refMapping.getJavaTypeMapping();
if (subMappings != null && subMappings.length == 1) {
// Support special case of reference mapping with single implementation possible
depth = 1;
}
}
}
// TODO We should use the actual FetchPlan, and the max fetch depth, so then it can pull in all related objects within reach.
// But this will mean we cannot cache the statement, since it is for a specific ExecutionContext
// TODO If this field is a 1-1 and the other side has a discriminator or version then we really ought to fetch it
SQLStatementHelper.selectMemberOfSourceInStatement(sqlStatement, mappingDef, null, sqlTbl, mmd, clr, depth, null);
number++;
}
if (mapping instanceof MappingCallbacks) {
// TODO Need to add that this mapping is for base object or base.field1, etc
fetchCallbacks.add(mapping);
}
}
}
}
JavaTypeMapping versionMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, true);
if (versionMapping != null) {
// Select version
StatementMappingIndex verMapIdx = new StatementMappingIndex(versionMapping);
SQLTable verSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStatement, sqlTbl, versionMapping);
int[] cols = sqlStatement.select(verSqlTbl, versionMapping, null);
verMapIdx.setColumnPositions(cols);
mappingDef.addMappingForMember(SurrogateColumnType.VERSION.getFieldNumber(), verMapIdx);
}
return number;
}
use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.
the class SQLStatementHelper method applyParametersToStatement.
/**
* Convenience method to apply parameter values to the provided statement.
* @param ps The prepared statement
* @param ec ExecutionContext
* @param parameters The parameters
* @param paramNameByPosition Optional map of parameter names keyed by the position
* @param paramValuesByName Value of parameter keyed by name (or position)
*/
public static void applyParametersToStatement(PreparedStatement ps, ExecutionContext ec, List<SQLStatementParameter> parameters, Map<Integer, String> paramNameByPosition, Map paramValuesByName) {
if (parameters != null) {
int num = 1;
Map<String, Integer> paramNumberByName = null;
int nextParamNumber = 0;
Iterator<SQLStatementParameter> i = parameters.iterator();
while (i.hasNext()) {
SQLStatementParameter param = i.next();
JavaTypeMapping mapping = param.getMapping();
RDBMSStoreManager storeMgr = mapping.getStoreManager();
// Find the overall parameter value for this parameter
Object value = null;
if (paramNumberByName != null) {
// Parameters are numbered but the query has named, so use lookup
Integer position = paramNumberByName.get("" + param.getName());
if (position == null) {
value = paramValuesByName.get(Integer.valueOf(nextParamNumber));
paramNumberByName.put(param.getName(), nextParamNumber);
nextParamNumber++;
} else {
value = paramValuesByName.get(position);
}
} else {
if (paramValuesByName.containsKey(param.getName())) {
// Named parameter has value in the input map
value = paramValuesByName.get(param.getName());
} else {
// Named parameter doesn't have value, so maybe using numbered input params
if (paramNameByPosition != null) {
int paramPosition = -1;
Set<String> paramNamesEncountered = new HashSet<>();
for (Map.Entry<Integer, String> entry : paramNameByPosition.entrySet()) {
String paramName = entry.getValue();
if (!paramNamesEncountered.contains(paramName)) {
paramPosition++;
paramNamesEncountered.add(paramName);
}
if (paramName.equals(param.getName())) {
value = paramValuesByName.get(paramPosition);
break;
}
}
paramNamesEncountered.clear();
paramNamesEncountered = null;
} else {
try {
value = paramValuesByName.get(Integer.valueOf(param.getName()));
} catch (NumberFormatException nfe) {
value = paramValuesByName.get(Integer.valueOf(nextParamNumber));
paramNumberByName = new HashMap<>();
paramNumberByName.put(param.getName(), Integer.valueOf(nextParamNumber));
nextParamNumber++;
}
}
}
}
AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(mapping.getType(), ec.getClassLoaderResolver());
if (param.getColumnNumber() >= 0 && cmd != null) {
// Apply the value for this column of the mapping
Object colValue = null;
if (value != null) {
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
colValue = mapping.getValueForDatastoreMapping(ec.getNucleusContext(), param.getColumnNumber(), value);
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
colValue = getValueForPrimaryKeyIndexOfObjectUsingReflection(value, param.getColumnNumber(), cmd, storeMgr, ec.getClassLoaderResolver());
}
}
mapping.getDatastoreMapping(param.getColumnNumber()).setObject(ps, num, colValue);
} else {
// Apply the value as a whole
if (ec.getApiAdapter().isPersistable(value)) {
if (!ec.getApiAdapter().isPersistent(value) && !ec.getApiAdapter().isDetached(value)) {
// Transient persistable object passed in as query parameter! We cannot simply use mapping.setObject since it will PERSIST the object
// See also JDO TCK Assertion ID: A14.6.2-44 "Comparisons between persistent and non-persistent instances return not equal"
boolean supported = false;
if (!supported) {
// Transient persistable object, so don't use (use null instead) since would cause its persistence
NucleusLogger.QUERY.warn("Attempt to use transient object as parameter in query. Not supported, so using NULL for parameter value");
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), null);
}
} else if (ec.getApiAdapter().isDetached(value)) {
// Detached, so avoid re-attaching
Object id = ec.getApiAdapter().getIdForObject(value);
PersistableIdMapping idMapping = new PersistableIdMapping((PersistableMapping) mapping);
idMapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, idMapping), id);
} else {
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
}
} else {
if (mapping.getNumberOfDatastoreMappings() == 1) {
// Set whole object and only 1 column
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
} else if (mapping.getNumberOfDatastoreMappings() > 1 && param.getColumnNumber() == (mapping.getNumberOfDatastoreMappings() - 1)) {
// Set whole object and this is the last parameter entry for it, so set now
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num - mapping.getNumberOfDatastoreMappings() + 1, mapping), value);
}
}
}
num++;
}
}
}
use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.
the class ObjectExpression method is.
/**
* An "is" (instanceOf) expression, providing a BooleanExpression whether this expression is an instanceof the provided type.
* @param expr The expression representing the type
* @param not Whether the operator is "!instanceof"
* @return Whether this expression is an instance of the provided type
*/
public BooleanExpression is(SQLExpression expr, boolean not) {
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
ClassLoaderResolver clr = stmt.getClassLoaderResolver();
// Extract instanceOf type
String instanceofClassName = null;
SQLExpression classExpr = expr;
if (expr instanceof TypeConverterLiteral) {
// For some reason the user has input "TYPE(field) = :param" and param is a type-converted value
classExpr = ((TypeConverterLiteral) expr).getDelegate();
}
if (classExpr instanceof StringLiteral) {
instanceofClassName = (String) ((StringLiteral) classExpr).getValue();
} else if (classExpr instanceof CollectionLiteral) {
// "a instanceof (b1,b2,b3)"
CollectionLiteral typesLiteral = (CollectionLiteral) classExpr;
Collection values = (Collection) typesLiteral.getValue();
if (values.size() == 1) {
Object value = values.iterator().next();
String valueStr = null;
if (value instanceof Class) {
valueStr = ((Class) value).getCanonicalName();
} else if (value instanceof String) {
valueStr = (String) value;
} else {
throw new NucleusUserException("Do not support CollectionLiteral of element type " + value.getClass().getName());
}
return is(new StringLiteral(stmt, typesLiteral.getJavaTypeMapping(), valueStr, typesLiteral.getParameterName()), not);
}
List<BooleanExpression> listExp = new LinkedList<>();
for (Object value : values) {
String valueStr = null;
if (value instanceof Class) {
valueStr = ((Class) value).getCanonicalName();
} else if (value instanceof String) {
valueStr = (String) value;
} else {
throw new NucleusUserException("Do not support CollectionLiteral of element type " + value.getClass().getName());
}
listExp.add(is(new StringLiteral(stmt, typesLiteral.getJavaTypeMapping(), valueStr, typesLiteral.getParameterName()), false));
}
BooleanExpression result = null;
for (BooleanExpression sqlExpression : listExp) {
result = result == null ? sqlExpression : result.ior(sqlExpression);
}
if (result != null) {
return not ? result.not() : result;
}
} else {
throw new NucleusUserException("Do not currently support `instanceof` with class expression of type " + classExpr);
}
Class type = null;
try {
type = stmt.getQueryGenerator().resolveClass(instanceofClassName);
} catch (ClassNotResolvedException cnre) {
type = null;
}
if (type == null) {
throw new NucleusUserException(Localiser.msg("037016", instanceofClassName));
}
// Extract type of member and check obvious conditions
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
Class memberType = clr.classForName(mapping.getType());
if (!memberType.isAssignableFrom(type) && !type.isAssignableFrom(memberType)) {
// Member type and instanceof type are totally incompatible, so just return false
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, not));
} else if (memberType == type) {
// instanceof type is the same as the member type therefore must comply (can't store supertypes)
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, !not));
}
if (mapping instanceof EmbeddedMapping) {
// Don't support embedded instanceof expressions
AbstractClassMetaData fieldCmd = storeMgr.getMetaDataManager().getMetaDataForClass(mapping.getType(), clr);
if (fieldCmd.hasDiscriminatorStrategy()) {
// Embedded field with inheritance so add discriminator restriction
JavaTypeMapping discMapping = ((EmbeddedMapping) mapping).getDiscriminatorMapping();
AbstractClassMetaData typeCmd = storeMgr.getMetaDataManager().getMetaDataForClass(type, clr);
SQLExpression discExpr = stmt.getSQLExpressionFactory().newExpression(stmt, table, discMapping);
SQLExpression discValExpr = stmt.getSQLExpressionFactory().newLiteral(stmt, discMapping, typeCmd.getDiscriminatorValue());
BooleanExpression typeExpr = (not ? discExpr.ne(discValExpr) : discExpr.eq(discValExpr));
Iterator<String> subclassIter = storeMgr.getSubClassesForClass(type.getName(), true, clr).iterator();
while (subclassIter.hasNext()) {
String subclassName = subclassIter.next();
AbstractClassMetaData subtypeCmd = storeMgr.getMetaDataManager().getMetaDataForClass(subclassName, clr);
Object subtypeDiscVal = subtypeCmd.getDiscriminatorValue();
discValExpr = stmt.getSQLExpressionFactory().newLiteral(stmt, discMapping, subtypeDiscVal);
BooleanExpression subtypeExpr = (not ? discExpr.ne(discValExpr) : discExpr.eq(discValExpr));
if (not) {
typeExpr = typeExpr.and(subtypeExpr);
} else {
typeExpr = typeExpr.ior(subtypeExpr);
}
}
return typeExpr;
}
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, not));
} else if (mapping instanceof PersistableMapping || mapping instanceof ReferenceMapping) {
// Field has its own table, so join to it
AbstractClassMetaData memberCmd = storeMgr.getMetaDataManager().getMetaDataForClass(mapping.getType(), clr);
DatastoreClass memberTable = null;
if (memberCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
// Field is a PC class that uses "subclass-table" inheritance strategy (and so has multiple possible tables to join to)
AbstractClassMetaData[] cmds = storeMgr.getClassesManagingTableForClass(memberCmd, clr);
if (cmds != null) {
// TODO Allow for all possible tables. Can we do an OR of the tables ? How ?
if (cmds.length > 1) {
NucleusLogger.QUERY.warn(Localiser.msg("037006", mapping.getMemberMetaData().getFullFieldName(), cmds[0].getFullClassName()));
}
memberTable = storeMgr.getDatastoreClass(cmds[0].getFullClassName(), clr);
} else {
// No subclasses with tables to join to, so throw a user error
throw new NucleusUserException(Localiser.msg("037005", mapping.getMemberMetaData().getFullFieldName()));
}
} else {
// Class of the field will have its own table
memberTable = storeMgr.getDatastoreClass(mapping.getType(), clr);
}
DiscriminatorMetaData dismd = memberTable.getDiscriminatorMetaData();
DiscriminatorMapping discMapping = (DiscriminatorMapping) memberTable.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, false);
if (discMapping != null) {
SQLTable targetSqlTbl = null;
if (mapping.getTable() != memberTable) {
// FK is on source table so inner join to target table (holding the discriminator)
targetSqlTbl = stmt.getTable(memberTable, null);
if (targetSqlTbl == null) {
targetSqlTbl = stmt.join(JoinType.INNER_JOIN, getSQLTable(), mapping, memberTable, null, memberTable.getIdMapping(), null, null);
}
} else {
// FK is on target side and already joined
targetSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, getSQLTable(), discMapping);
}
// Add restrict to discriminator for the instanceOf type and subclasses
SQLTable discSqlTbl = targetSqlTbl;
BooleanExpression discExpr = null;
if (!Modifier.isAbstract(type.getModifiers())) {
discExpr = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, type.getName(), dismd, discMapping, discSqlTbl, clr);
}
Iterator<String> subclassIter = storeMgr.getSubClassesForClass(type.getName(), true, clr).iterator();
boolean multiplePossibles = false;
while (subclassIter.hasNext()) {
String subclassName = subclassIter.next();
Class subclass = clr.classForName(subclassName);
if (Modifier.isAbstract(subclass.getModifiers())) {
continue;
}
BooleanExpression discExprSub = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, subclassName, dismd, discMapping, discSqlTbl, clr);
if (discExpr != null) {
multiplePossibles = true;
discExpr = discExpr.ior(discExprSub);
} else {
discExpr = discExprSub;
}
}
if (multiplePossibles && discExpr != null) {
discExpr.encloseInParentheses();
}
return ((not && discExpr != null) ? discExpr.not() : discExpr);
}
// No discriminator, so the following is likely incomplete.
// Join to member table
DatastoreClass table = null;
if (memberCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
// Field is a PC class that uses "subclass-table" inheritance strategy (and so has multiple possible tables to join to)
AbstractClassMetaData[] cmds = storeMgr.getClassesManagingTableForClass(memberCmd, clr);
if (cmds != null) {
// TODO Allow for all possible tables. Can we do an OR of the tables ? How ?
if (cmds.length > 1) {
NucleusLogger.QUERY.warn(Localiser.msg("037006", mapping.getMemberMetaData().getFullFieldName(), cmds[0].getFullClassName()));
}
table = storeMgr.getDatastoreClass(cmds[0].getFullClassName(), clr);
} else {
// No subclasses with tables to join to, so throw a user error
throw new NucleusUserException(Localiser.msg("037005", mapping.getMemberMetaData().getFullFieldName()));
}
} else {
// Class of the field will have its own table
table = storeMgr.getDatastoreClass(mapping.getType(), clr);
}
if (table.managesClass(type.getName())) {
// This type is managed in this table so must be an instance TODO Is this correct, what if member is using discrim?
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, !not));
}
if (table == stmt.getPrimaryTable().getTable()) {
// This is member table, so just need to restrict to the instanceof type now
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
if (stmt instanceof SelectStatement) {
SelectStatement selectStmt = (SelectStatement) stmt;
if (selectStmt.getNumberOfUnions() == 0) {
// No UNIONs so just check the main statement and return according to whether it is allowed
Class mainCandidateCls = clr.classForName(stmt.getCandidateClassName());
if (type.isAssignableFrom(mainCandidateCls) == not) {
SQLExpression returnExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
return (BooleanExpression) returnExpr;
}
SQLExpression returnExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true));
return (BooleanExpression) returnExpr;
}
NucleusLogger.QUERY.warn("TYPE/INSTANCEOF operator for class=" + memberCmd.getFullClassName() + " on table=" + memberTable + " for type=" + instanceofClassName + " but there is no discriminator and using UNIONs. Any subsequent handling is likely incorrect TODO");
// a). we have unions for the member, so restrict to just the applicable unions
// Note that this is only really valid is wanting "a instanceof SUB1".
// It fails when we want to do "a instanceof SUB1 || a instanceof SUB2"
// TODO What if this "OP_IS" is in the SELECT clause??? Need to update QueryToSQLMapper.compileResult
Class mainCandidateCls = clr.classForName(stmt.getCandidateClassName());
if (type.isAssignableFrom(mainCandidateCls) == not) {
SQLExpression unionClauseExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
stmt.whereAnd((BooleanExpression) unionClauseExpr, false);
}
List<SelectStatement> unionStmts = selectStmt.getUnions();
for (SelectStatement unionStmt : unionStmts) {
Class unionCandidateCls = clr.classForName(unionStmt.getCandidateClassName());
if (type.isAssignableFrom(unionCandidateCls) == not) {
SQLExpression unionClauseExpr = exprFactory.newLiteral(unionStmt, m, true).eq(exprFactory.newLiteral(unionStmt, m, false));
// TODO Avoid using whereAnd
unionStmt.whereAnd((BooleanExpression) unionClauseExpr, false);
}
}
// Just return true since we applied the condition direct to the unions
SQLExpression returnExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true));
return (BooleanExpression) returnExpr;
}
// b). The member table doesn't manage the instanceof type, so do inner join to
// the table of the instanceof to impose the instanceof condition
DatastoreClass instanceofTable = storeMgr.getDatastoreClass(type.getName(), clr);
stmt.join(JoinType.INNER_JOIN, this.table, this.table.getTable().getIdMapping(), instanceofTable, null, instanceofTable.getIdMapping(), null, this.table.getGroupName());
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, !not));
}
// Do inner join to this table to impose the instanceOf
DatastoreClass instanceofTable = storeMgr.getDatastoreClass(type.getName(), clr);
stmt.join(JoinType.INNER_JOIN, this.table, this.table.getTable().getIdMapping(), instanceofTable, null, instanceofTable.getIdMapping(), null, this.table.getGroupName());
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, !not));
} else {
// TODO Implement instanceof for other types
throw new NucleusException("Dont currently support " + this + " instanceof " + type.getName());
}
}
use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.
the class ObjectExpression method eq.
/**
* Equals operator. Called when the query contains "obj == value" where "obj" is this object.
* @param expr The expression we compare with (the right-hand-side in the query)
* @return Boolean expression representing the comparison.
*/
public BooleanExpression eq(SQLExpression expr) {
addSubexpressionsToRelatedExpression(expr);
// TODO Implement checks
if (mapping instanceof PersistableIdMapping) {
// Special Case : OID comparison ("id == val")
if (expr instanceof StringLiteral) {
String oidString = (String) ((StringLiteral) expr).getValue();
if (oidString != null) {
AbstractClassMetaData cmd = stmt.getRDBMSManager().getMetaDataManager().getMetaDataForClass(mapping.getType(), stmt.getQueryGenerator().getClassLoaderResolver());
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
try {
Object id = stmt.getRDBMSManager().getNucleusContext().getIdentityManager().getDatastoreId(oidString);
if (id == null) {
// TODO Implement this comparison with the key value
}
} catch (IllegalArgumentException iae) {
NucleusLogger.QUERY.info("Attempted comparison of " + this + " and " + expr + " where the former is a datastore-identity and the latter is of incorrect form (" + oidString + ")");
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, false).eq(exprFactory.newLiteral(stmt, m, true));
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
// TODO Implement comparison with PK field(s)
}
}
}
}
if (mapping instanceof ReferenceMapping && expr.mapping instanceof PersistableMapping) {
return processComparisonOfImplementationWithReference(this, expr, false);
} else if (mapping instanceof PersistableMapping && expr.mapping instanceof ReferenceMapping) {
return processComparisonOfImplementationWithReference(expr, this, false);
}
BooleanExpression bExpr = null;
if (isParameter() || expr.isParameter()) {
if (subExprs != null && subExprs.size() > 1) {
for (int i = 0; i < subExprs.size(); i++) {
BooleanExpression subexpr = subExprs.getExpression(i).eq(((ObjectExpression) expr).subExprs.getExpression(i));
bExpr = (bExpr == null ? subexpr : bExpr.and(subexpr));
}
return bExpr;
}
// Comparison with parameter, so just give boolean compare
return new BooleanExpression(this, Expression.OP_EQ, expr);
} else if (expr instanceof NullLiteral) {
if (subExprs != null) {
for (int i = 0; i < subExprs.size(); i++) {
BooleanExpression subexpr = expr.eq(subExprs.getExpression(i));
bExpr = (bExpr == null ? subexpr : bExpr.and(subexpr));
}
}
return bExpr;
} else if (literalIsValidForSimpleComparison(expr)) {
if (subExprs != null && subExprs.size() > 1) {
// More than 1 value to compare with a simple literal!
return super.eq(expr);
}
// Just do a direct comparison with the basic literals
return new BooleanExpression(this, Expression.OP_EQ, expr);
} else if (expr instanceof ObjectExpression) {
return ExpressionUtils.getEqualityExpressionForObjectExpressions(this, (ObjectExpression) expr, true);
} else {
if (subExprs == null) {
// ObjectExpression for a function call
return new BooleanExpression(this, Expression.OP_EQ, expr);
}
return super.eq(expr);
}
}
use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping 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 + ")");
}
Aggregations