Search in sources :

Example 1 with SingleCollectionMapping

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;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) MappingCallbacks(org.datanucleus.store.rdbms.mapping.MappingCallbacks) SingleCollectionMapping(org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 2 with SingleCollectionMapping

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());
    }
}
Also used : PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SingleCollectionMapping(org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) ColumnMapping(org.datanucleus.store.rdbms.mapping.column.ColumnMapping) BigDecimal(java.math.BigDecimal)

Example 3 with SingleCollectionMapping

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;
}
Also used : PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) MappingCallbacks(org.datanucleus.store.rdbms.mapping.MappingCallbacks) SingleCollectionMapping(org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 4 with SingleCollectionMapping

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;
}
Also used : PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) MappingCallbacks(org.datanucleus.store.rdbms.mapping.MappingCallbacks) SingleCollectionMapping(org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)4 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)4 SingleCollectionMapping (org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping)4 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)3 MappingCallbacks (org.datanucleus.store.rdbms.mapping.MappingCallbacks)3 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)3 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)3 BigDecimal (java.math.BigDecimal)1 ColumnMapping (org.datanucleus.store.rdbms.mapping.column.ColumnMapping)1 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)1 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)1