Search in sources :

Example 11 with PersistableMapping

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));
    }
}
Also used : PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager)

Example 12 with PersistableMapping

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());
    }
}
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) DatastoreMapping(org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping) SingleCollectionMapping(org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) BigDecimal(java.math.BigDecimal)

Example 13 with PersistableMapping

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;
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ExecutionContext(org.datanucleus.ExecutionContext) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 14 with PersistableMapping

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

Example 15 with PersistableMapping

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;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ArrayList(java.util.ArrayList) ForeignKey(org.datanucleus.store.rdbms.key.ForeignKey) EmbeddedElementPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedElementPCMapping) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) Collection(java.util.Collection) SerialisedPCMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedPCMapping) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException)

Aggregations

PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)33 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)27 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)17 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)17 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)16 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)15 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)13 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)10 Collection (java.util.Collection)7 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)7 ArrayList (java.util.ArrayList)6 HashSet (java.util.HashSet)6 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)6 HashMap (java.util.HashMap)5 Iterator (java.util.Iterator)5 List (java.util.List)5 Map (java.util.Map)5 NucleusException (org.datanucleus.exceptions.NucleusException)5 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)5 FetchPlanForClass (org.datanucleus.FetchPlanForClass)4