use of org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping 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.SingleCollectionMapping 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.SingleCollectionMapping in project datanucleus-rdbms by datanucleus.
the class FetchRequest method processMemberToFetch.
/**
* Method to process the specified member.
* @param mmd MetaData for the member
* @param fpClass FetchPlan for class
* @param clr ClassLoader resolver
* @param fetchCallbacks Any fetch callbacks to register the mapping with
* @param sqlStmt The SELECT statement
* @param sqlTbl The SQL table (of the candidate)
* @param mappingDef The mapping definition for this statement
* @param store Whether we are just selecting the value of this member for storing (rather than fetching)
* @param memberNumbersToStore List of member numbers that are approved to be stored (any fetched ones will be added if recursionDepth=0)
* @return Whether this member is selected in the statement
*/
boolean processMemberToFetch(AbstractMemberMetaData mmd, FetchPlanForClass fpClass, ClassLoaderResolver clr, Collection fetchCallbacks, SelectStatement sqlStmt, SQLTable sqlTbl, StatementClassMapping mappingDef, List<Integer> memberNumbersToStore) {
boolean selected = false;
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
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();
}
boolean fetchAndSaveFK = false;
if (mappingToUse instanceof PersistableMapping) {
if (RelationType.isRelationSingleValued(mmd.getRelationType(clr)) && fpClass.getRecursionDepthForMember(mmd.getAbsoluteFieldNumber()) == 0) {
// Special case of 1-1/N-1 and recursion-depth set as 0 (just retrieve the FK and don't instantiate the related object in the field)
depth = 0;
fetchAndSaveFK = true;
} else if (mmd.fetchFKOnly()) {
// Special case of 1-1/N-1 and fetch-fk-only extension - same as above
depth = 0;
fetchAndSaveFK = true;
} else {
// Special case of 1-1/N-1 where we know the other side type so know what to join to and 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(sqlStmt, mappingDef, null, sqlTbl, mmd, clr, depth, null);
if (fetchAndSaveFK) {
memberNumbersToStore.add(mmd.getAbsoluteFieldNumber());
}
selected = true;
}
if (mapping instanceof MappingCallbacks) {
// TODO Need to add that this mapping is for base object or base.field1, etc
fetchCallbacks.add(mapping);
}
}
return selected;
}
use of org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping in project datanucleus-rdbms by datanucleus.
the class FetchRequest method processMemberToStore.
/**
* Method to process the specified member.
* @param mmd MetaData for the member
* @param fpClass FetchPlan for class
* @param clr ClassLoader resolver
* @param fetchCallbacks Any fetch callbacks to register the mapping with
* @param sqlStmt The SELECT statement
* @param sqlTbl The SQL table (of the candidate)
* @param mappingDef The mapping definition for this statement
* @param memberNumbersToStore List of member numbers that are approved to be stored
* @return Whether this member is selected in the statement
*/
boolean processMemberToStore(AbstractMemberMetaData mmd, FetchPlanForClass fpClass, ClassLoaderResolver clr, Collection fetchCallbacks, SelectStatement sqlStmt, SQLTable sqlTbl, StatementClassMapping mappingDef, List<Integer> memberNumbersToStore) {
boolean selected = false;
JavaTypeMapping mapping = table.getMemberMapping(mmd);
if (mapping != null) {
if (!mmd.isPrimaryKey() && mapping.includeInFetchStatement()) {
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) {
// TODO Omit members that are compound identity
SQLStatementHelper.selectMemberOfSourceInStatement(sqlStmt, mappingDef, null, sqlTbl, mmdToUse, clr, 0, null);
memberNumbersToStore.add(mmd.getAbsoluteFieldNumber());
selected = true;
}
}
if (mapping instanceof MappingCallbacks) {
// TODO Need to add that this mapping is for base object or base.field1, etc
fetchCallbacks.add(mapping);
}
}
return selected;
}
Aggregations