Search in sources :

Example 46 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class MappingManagerImpl method getMapping.

/**
 * Accessor for the mapping for the member of the specified table.
 * Can be used for members of a class, element of a collection of a class, element of an array of a class,
 * keys of a map of a class, values of a map of a class; this is controlled by the role argument.
 * @param table Table to add the mapping to
 * @param mmd MetaData for the member to map
 * @param clr The ClassLoaderResolver
 * @param fieldRole Role that this mapping plays for the field
 * @return The mapping for the member.
 */
@Override
public JavaTypeMapping getMapping(Table table, AbstractMemberMetaData mmd, ClassLoaderResolver clr, FieldRole fieldRole) {
    if (fieldRole == FieldRole.ROLE_COLLECTION_ELEMENT || fieldRole == FieldRole.ROLE_ARRAY_ELEMENT) {
        // Mapping a collection/array element (in a join table)
        return getElementMapping(table, mmd, fieldRole, clr);
    } else if (fieldRole == FieldRole.ROLE_MAP_KEY) {
        // Mapping a map key (in a join table)
        return getKeyMapping(table, mmd, clr);
    } else if (fieldRole == FieldRole.ROLE_MAP_VALUE) {
        // Mapping a map value (in a join table)
        return getValueMapping(table, mmd, clr);
    }
    // Check for use of TypeConverter (either specific, or auto-apply for this type)
    TypeManager typeMgr = table.getStoreManager().getNucleusContext().getTypeManager();
    TypeConverter conv = null;
    if (!mmd.isTypeConversionDisabled()) {
        // User-specified TypeConverter defined for the whole member, or an autoApply is present for this member type
        if (mmd.getTypeConverterName() != null) {
            conv = typeMgr.getTypeConverterForName(mmd.getTypeConverterName());
            if (conv == null) {
                throw new NucleusUserException(Localiser.msg("044062", mmd.getFullFieldName(), mmd.getTypeConverterName()));
            }
        } else {
            TypeConverter autoApplyConv = typeMgr.getAutoApplyTypeConverterForType(mmd.getType());
            if (autoApplyConv != null) {
                conv = autoApplyConv;
            }
        }
        if (conv != null) {
            // Create the mapping of the selected type
            JavaTypeMapping m = null;
            if (conv instanceof MultiColumnConverter) {
                Class mc = TypeConverterMultiMapping.class;
                try {
                    m = (JavaTypeMapping) mc.getDeclaredConstructor().newInstance();
                    m.setRoleForMember(FieldRole.ROLE_FIELD);
                    ((TypeConverterMultiMapping) m).initialize(mmd, table, clr, conv);
                    return m;
                } catch (Exception e) {
                    throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
                }
            }
            Class mc = TypeConverterMapping.class;
            try {
                m = (JavaTypeMapping) mc.getDeclaredConstructor().newInstance();
                m.setRoleForMember(FieldRole.ROLE_FIELD);
                ((TypeConverterMapping) m).initialize(mmd, table, clr, conv);
                return m;
            } catch (Exception e) {
                throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
            }
        }
    }
    AbstractMemberMetaData overrideMmd = null;
    MappingConverterDetails mcd = null;
    Class<? extends JavaTypeMapping> mc = null;
    String userMappingClassName = mmd.getValueForExtension("mapping-class");
    if (userMappingClassName != null) {
        // User has defined their own mapping class for this field so use that
        try {
            mc = clr.classForName(userMappingClassName);
        } catch (NucleusException ne) {
            throw new NucleusUserException(Localiser.msg("041014", mmd.getFullFieldName(), userMappingClassName)).setFatal();
        }
    } else {
        AbstractClassMetaData typeCmd = (mmd.getType().isInterface()) ? storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForInterface(mmd.getType(), clr) : storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
        if (mmd.hasExtension(SerialisedLocalFileMapping.EXTENSION_SERIALIZE_TO_FOLDER) && Serializable.class.isAssignableFrom(mmd.getType())) {
            // Special case : use file serialization mapping
            mc = SerialisedLocalFileMapping.class;
        } else if (mmd.isSerialized()) {
            // Field is marked as serialised then we have no other option - serialise it
            mcd = getMappingClass(mmd.getType(), true, false, null, mmd.getFullFieldName());
        } else if (mmd.getEmbeddedMetaData() != null) {
            // Field has an <embedded> specification so use that
            mcd = getMappingClass(mmd.getType(), false, true, null, mmd.getFullFieldName());
        } else if (typeCmd != null && typeCmd.isEmbeddedOnly()) {
            // Reference type is declared with embedded only
            mcd = getMappingClass(mmd.getType(), false, true, null, mmd.getFullFieldName());
        } else if (// TODO Check this since it will push all basic nonPC fields through here
        mmd.isEmbedded()) {
            // Otherwise, if the field is embedded then we request that it be serialised into the owner table
            // This is particularly for java.lang.Object which should be "embedded" by default, and hence serialised
            mcd = getMappingClass(mmd.getType(), true, false, mmd.getColumnMetaData(), mmd.getFullFieldName());
        } else {
            // Non-embedded/non-serialised - Just get the basic mapping for the type
            Class memberType = mmd.getType();
            mcd = getMappingClass(memberType, false, false, mmd.getColumnMetaData(), mmd.getFullFieldName());
            if (mmd.getParent() instanceof EmbeddedMetaData && mmd.getRelationType(clr) != RelationType.NONE) {
                // See NUCCORE-697 - always need to use the real member metadata for the mapping
                // so that it can find sub-fields when persisting/querying etc
                AbstractClassMetaData cmdForFmd = table.getStoreManager().getMetaDataManager().getMetaDataForClass(mmd.getClassName(), clr);
                overrideMmd = cmdForFmd.getMetaDataForMember(mmd.getName());
            }
        }
    }
    // Create the mapping of the selected type
    if (mcd != null) {
        mc = mcd.mappingClass;
        // Allow override by Oracle
        mc = getOverrideMappingClass(mc, mmd, fieldRole);
    }
    if (mc != null && (mcd == null || mcd.typeConverter == null)) {
        try {
            JavaTypeMapping m = mc.getDeclaredConstructor().newInstance();
            m.setRoleForMember(FieldRole.ROLE_FIELD);
            m.initialize(mmd, table, clr);
            if (overrideMmd != null) {
                // Note cannot just use this overrideMmd in the initialize(...) call above, a test fails.
                m.setMemberMetaData(overrideMmd);
            }
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
        }
    } else if (mcd != null && mcd.typeConverter != null) {
        try {
            JavaTypeMapping m = mcd.mappingClass.getDeclaredConstructor().newInstance();
            m.setRoleForMember(FieldRole.ROLE_FIELD);
            if (m instanceof TypeConverterMapping) {
                ((TypeConverterMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            } else if (m instanceof TypeConverterMultiMapping) {
                ((TypeConverterMultiMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            }
            if (overrideMmd != null) {
                // Note cannot just use this overrideMmd in the initialize(...) call above, a test fails.
                m.setMemberMetaData(overrideMmd);
            }
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
        }
    }
    throw new NucleusException("Unable to create mapping for member at " + mmd.getFullFieldName() + " - no available mapping");
}
Also used : Serializable(java.io.Serializable) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedMetaData(org.datanucleus.metadata.EmbeddedMetaData) MultiColumnConverter(org.datanucleus.store.types.converters.MultiColumnConverter) NucleusException(org.datanucleus.exceptions.NucleusException) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) TypeConverter(org.datanucleus.store.types.converters.TypeConverter) TypeConverterMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMapping) TypeManager(org.datanucleus.store.types.TypeManager) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) TypeConverterMultiMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMultiMapping)

Example 47 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class MappingManagerImpl method getElementMapping.

/**
 * Convenience accessor for the element mapping for the element of a collection/array of elements.
 * @param table The table
 * @param mmd MetaData for the collection member containing the collection/array of PCs
 * @param fieldRole role of this mapping for this member
 * @param clr ClassLoader resolver
 * @return The mapping
 */
protected JavaTypeMapping getElementMapping(Table table, AbstractMemberMetaData mmd, FieldRole fieldRole, ClassLoaderResolver clr) {
    if (!mmd.hasCollection() && !mmd.hasArray()) {
        // TODO Localise this message
        throw new NucleusException("Attempt to get element mapping for field " + mmd.getFullFieldName() + " that has no collection/array!").setFatal();
    }
    if (mmd.getJoinMetaData() == null) {
        AbstractMemberMetaData[] refMmds = mmd.getRelatedMemberMetaData(clr);
        if (refMmds == null || refMmds.length == 0) {
            // TODO Localise this
            throw new NucleusException("Attempt to get element mapping for field " + mmd.getFullFieldName() + " that has no join table defined for the collection/array").setFatal();
        }
        if (refMmds[0].getJoinMetaData() == null) {
            // TODO Localise this
            throw new NucleusException("Attempt to get element mapping for field " + mmd.getFullFieldName() + " that has no join table defined for the collection/array").setFatal();
        }
    }
    MappingConverterDetails mcd = null;
    Class<? extends JavaTypeMapping> mc = null;
    String userMappingClassName = null;
    String userTypeConverterName = null;
    if (mmd.getElementMetaData() != null) {
        userTypeConverterName = mmd.getElementMetaData().getValueForExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME);
        userMappingClassName = mmd.getElementMetaData().getValueForExtension("mapping-class");
    }
    if (userTypeConverterName != null) {
        TypeConverter conv = storeMgr.getNucleusContext().getTypeManager().getTypeConverterForName(userTypeConverterName);
        if (conv == null) {
            throw new NucleusUserException("Field " + mmd.getFullFieldName() + " ELEMENT has been specified to use type converter " + userTypeConverterName + " but not found!");
        }
        // TODO Could be TypeConverterMultiMapping?
        mcd = new MappingConverterDetails(TypeConverterMapping.class, conv);
    } else if (userMappingClassName != null) {
        // User has defined their own mapping class for this element so use that
        try {
            mc = clr.classForName(userMappingClassName);
        } catch (NucleusException jpe) {
            throw new NucleusUserException(Localiser.msg("041014", userMappingClassName)).setFatal();
        }
    } else {
        boolean serialised = ((mmd.hasCollection() && mmd.getCollection().isSerializedElement()) || (mmd.hasArray() && mmd.getArray().isSerializedElement()));
        boolean embeddedPC = (mmd.hasCollection() && mmd.getCollection().elementIsPersistent() && mmd.getCollection().isEmbeddedElement()) || (mmd.getElementMetaData() != null && mmd.getElementMetaData().getEmbeddedMetaData() != null);
        boolean elementPC = ((mmd.hasCollection() && mmd.getCollection().elementIsPersistent()) || (mmd.hasArray() && mmd.getArray().elementIsPersistent()));
        boolean embedded = true;
        Class elementCls = null;
        if (mmd.hasCollection()) {
            embedded = mmd.getCollection().isEmbeddedElement();
            elementCls = clr.classForName(mmd.getCollection().getElementType());
        } else if (mmd.hasArray()) {
            // Use declared element type rather than any restricted type specified in metadata
            embedded = mmd.getArray().isEmbeddedElement();
            elementCls = mmd.getType().getComponentType();
        }
        boolean elementReference = ClassUtils.isReferenceType(elementCls);
        if (serialised) {
            if (elementPC) {
                // Serialised PC element
                mc = SerialisedElementPCMapping.class;
            } else if (elementReference) {
                // Serialised Reference element
                mc = SerialisedReferenceMapping.class;
            } else {
                // Serialised Non-PC element
                mc = SerialisedMapping.class;
            }
        } else if (embedded) {
            if (embeddedPC) {
                // Embedded PC type
                mc = EmbeddedElementPCMapping.class;
            } else if (elementPC) {
                // "Embedded" PC type but no <embedded> so dont embed for now. Is this correct?
                mc = PersistableMapping.class;
            } else {
                // Embedded Non-PC type
                mcd = getMappingClass(elementCls, serialised, embedded, mmd.getElementMetaData() != null ? mmd.getElementMetaData().getColumnMetaData() : null, mmd.getFullFieldName());
            }
        } else {
            // Normal element mapping
            mcd = getMappingClass(elementCls, serialised, embedded, mmd.getElementMetaData() != null ? mmd.getElementMetaData().getColumnMetaData() : null, mmd.getFullFieldName());
        }
    }
    if (mcd != null && mcd.typeConverter == null) {
        mc = mcd.mappingClass;
    }
    if (mc != null && (mcd == null || mcd.typeConverter == null)) {
        // Create the mapping of the selected type
        JavaTypeMapping m = null;
        try {
            m = mc.getDeclaredConstructor().newInstance();
            m.setRoleForMember(fieldRole);
            m.initialize(mmd, table, clr);
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
        }
    } else if (mcd != null && mcd.typeConverter != null) {
        try {
            JavaTypeMapping m = mcd.mappingClass.getDeclaredConstructor().newInstance();
            m.setRoleForMember(fieldRole);
            if (m instanceof TypeConverterMapping) {
                ((TypeConverterMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            } else if (m instanceof TypeConverterMultiMapping) {
                ((TypeConverterMultiMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            }
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc != null ? mc.getName() : null, e), e).setFatal();
        }
    }
    throw new NucleusException("Unable to create mapping for element of collection/array at " + mmd.getFullFieldName() + " - no available mapping");
}
Also used : SerialisedElementPCMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedElementPCMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) NucleusException(org.datanucleus.exceptions.NucleusException) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) TypeConverter(org.datanucleus.store.types.converters.TypeConverter) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) TypeConverterMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) TypeConverterMultiMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMultiMapping)

Example 48 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class MapContainsKeyMethod method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List<SQLExpression> args) {
    if (args == null || args.size() == 0 || args.size() > 1) {
        throw new NucleusException(Localiser.msg("060016", "containsKey", "MapExpression", 1));
    }
    MapExpression mapExpr = (MapExpression) expr;
    SQLExpression keyExpr = args.get(0);
    if (keyExpr.isParameter()) {
        // Key is a parameter so make sure its type is set
        AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
        if (mmd != null && mmd.getMap() != null) {
            Class keyCls = stmt.getQueryGenerator().getClassLoaderResolver().classForName(mmd.getMap().getKeyType());
            stmt.getQueryGenerator().bindParameter(keyExpr.getParameterName(), keyCls);
        }
    }
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    if (expr instanceof MapLiteral) {
        // Literal Map
        MapLiteral lit = (MapLiteral) expr;
        Map map = (Map) lit.getValue();
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
        if (map == null || map.size() == 0) {
            return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
        }
        boolean useInExpression = false;
        List<SQLExpression> mapKeyExprs = lit.getKeyLiteral().getKeyExpressions();
        if (mapKeyExprs != null && !mapKeyExprs.isEmpty()) {
            // Make sure the the map key(s) are compatible with the keyExpr
            boolean incompatible = true;
            Class elemtype = clr.classForName(keyExpr.getJavaTypeMapping().getType());
            Iterator<SQLExpression> mapKeyExprIter = mapKeyExprs.iterator();
            while (mapKeyExprIter.hasNext()) {
                SQLExpression mapKeyExpr = mapKeyExprIter.next();
                Class mapKeyType = clr.classForName(mapKeyExpr.getJavaTypeMapping().getType());
                if (keyTypeCompatible(elemtype, mapKeyType)) {
                    incompatible = false;
                    break;
                }
            }
            if (incompatible) {
                // The provided element type isn't assignable to any of the input collection elements!
                return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
            }
            // Check if we should compare using an "IN (...)" expression
            SQLExpression mapKeyExpr = mapKeyExprs.get(0);
            if (mapKeyExpr instanceof StringExpression || mapKeyExpr instanceof NumericExpression || mapKeyExpr instanceof TemporalExpression || mapKeyExpr instanceof CharacterExpression || mapKeyExpr instanceof EnumExpression) {
                useInExpression = true;
            }
        }
        if (useInExpression) {
            // Return "key IN (val1, val2, ...)"
            SQLExpression[] exprs = (mapKeyExprs != null ? mapKeyExprs.toArray(new SQLExpression[mapKeyExprs.size()]) : null);
            return new InExpression(keyExpr, exprs);
        }
        // TODO If keyExpr is a parameter and mapExpr is derived from a parameter ?
        MapKeyLiteral mapKeyLiteral = lit.getKeyLiteral();
        BooleanExpression bExpr = null;
        List<SQLExpression> elementExprs = mapKeyLiteral.getKeyExpressions();
        for (int i = 0; i < elementExprs.size(); i++) {
            if (bExpr == null) {
                bExpr = (elementExprs.get(i)).eq(keyExpr);
            } else {
                bExpr = bExpr.ior((elementExprs.get(i)).eq(keyExpr));
            }
        }
        if (bExpr != null) {
            bExpr.encloseInParentheses();
        }
        return bExpr;
    }
    if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.FILTER) {
        boolean useSubquery = getNeedsSubquery(stmt);
        JoinType joinType = JoinType.INNER_JOIN;
        if (keyExpr instanceof UnboundExpression) {
            // See if the user has defined what should be used
            String varName = ((UnboundExpression) keyExpr).getVariableName();
            String extensionName = "datanucleus.query.jdoql." + varName + ".join";
            String extensionValue = (String) stmt.getQueryGenerator().getValueForExtension(extensionName);
            if (extensionValue != null) {
                if (extensionValue.equalsIgnoreCase("SUBQUERY")) {
                    useSubquery = true;
                } else if (extensionValue.equalsIgnoreCase("INNERJOIN")) {
                    useSubquery = false;
                } else if (extensionValue.equalsIgnoreCase("LEFTOUTERJOIN")) {
                    joinType = JoinType.LEFT_OUTER_JOIN;
                }
            }
        }
        // TODO Check if *this* "containsKey" is negated, not any of them (and remove above check)
        if (useSubquery) {
            return containsAsSubquery(stmt, mapExpr, keyExpr);
        }
        return containsAsJoin(stmt, mapExpr, keyExpr, joinType);
    }
    return containsAsSubquery(stmt, mapExpr, keyExpr);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) InExpression(org.datanucleus.store.rdbms.sql.expression.InExpression) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) MapExpression(org.datanucleus.store.rdbms.sql.expression.MapExpression) TemporalExpression(org.datanucleus.store.rdbms.sql.expression.TemporalExpression) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression) JoinType(org.datanucleus.store.rdbms.sql.SQLJoin.JoinType) EnumExpression(org.datanucleus.store.rdbms.sql.expression.EnumExpression) CharacterExpression(org.datanucleus.store.rdbms.sql.expression.CharacterExpression) MapLiteral(org.datanucleus.store.rdbms.sql.expression.MapLiteral) StringExpression(org.datanucleus.store.rdbms.sql.expression.StringExpression) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) Map(java.util.Map) MapKeyLiteral(org.datanucleus.store.rdbms.sql.expression.MapLiteral.MapKeyLiteral)

Example 49 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class MapGetMethod method getAsInnerJoin.

/**
 * Implementation of Map.get() using an inner join to the table representing the map, adding a condition on the key and returning the value.
 * @param stmt SQLStatement
 * @param mapExpr The map expression
 * @param keyValExpr The key value expression
 * @return The value expression
 */
protected SQLExpression getAsInnerJoin(SQLStatement stmt, MapExpression mapExpr, SQLExpression keyValExpr) {
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    JavaTypeMapping m = mapExpr.getJavaTypeMapping();
    AbstractMemberMetaData mmd = m.getMemberMetaData();
    if (mmd != null) {
        MapMetaData mapmd = mmd.getMap();
        if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
            MapTable joinTbl = (MapTable) stmt.getRDBMSManager().getTable(mmd);
            // Add join to join table
            SQLTable joinSqlTbl = stmt.join(JoinType.INNER_JOIN, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null);
            // Add condition on key
            SQLExpression keyExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getKeyMapping());
            stmt.whereAnd(keyExpr.eq(keyValExpr), true);
            // Return value expression
            if (mapmd.getValueClassMetaData(clr) != null) {
                // Persistable value so join to its table
                DatastoreClass valTable = stmt.getRDBMSManager().getDatastoreClass(mapmd.getValueType(), clr);
                SQLTable valueSqlTbl = stmt.join(JoinType.INNER_JOIN, joinSqlTbl, joinTbl.getValueMapping(), valTable, null, valTable.getIdMapping(), null, null);
                return exprFactory.newExpression(stmt, valueSqlTbl, valTable.getIdMapping());
            }
            // Return mapping for the value in the join table
            SQLExpression valueExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getValueMapping());
            return valueExpr;
        } else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
            // Key stored in value table, so join to value table
            DatastoreClass valTable = stmt.getRDBMSManager().getDatastoreClass(mapmd.getValueType(), clr);
            AbstractClassMetaData valCmd = mapmd.getValueClassMetaData(clr);
            JavaTypeMapping mapTblOwnerMapping;
            if (mmd.getMappedBy() != null) {
                mapTblOwnerMapping = valTable.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
            } else {
                mapTblOwnerMapping = valTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
            }
            SQLTable valSqlTbl = stmt.join(JoinType.INNER_JOIN, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), valTable, null, mapTblOwnerMapping, null, null);
            // Add condition on key
            JavaTypeMapping keyMapping = valTable.getMemberMapping(valCmd.getMetaDataForMember(mmd.getKeyMetaData().getMappedBy()));
            SQLExpression keyExpr = exprFactory.newExpression(stmt, valSqlTbl, keyMapping);
            stmt.whereAnd(keyExpr.eq(keyValExpr), true);
            // Return value expression
            SQLExpression valueExpr = exprFactory.newExpression(stmt, valSqlTbl, valTable.getIdMapping());
            return valueExpr;
        } else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
            // Value stored in key table, so join to key table
            DatastoreClass keyTable = stmt.getRDBMSManager().getDatastoreClass(mapmd.getKeyType(), clr);
            AbstractClassMetaData keyCmd = mapmd.getKeyClassMetaData(clr);
            JavaTypeMapping mapTblOwnerMapping;
            if (mmd.getMappedBy() != null) {
                mapTblOwnerMapping = keyTable.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
            } else {
                mapTblOwnerMapping = keyTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
            }
            SQLTable keySqlTbl = stmt.join(JoinType.INNER_JOIN, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), keyTable, null, mapTblOwnerMapping, null, null);
            // Add condition on key
            SQLExpression keyExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTable.getIdMapping());
            stmt.whereAnd(keyExpr.eq(keyValExpr), true);
            // Return value expression
            JavaTypeMapping valueMapping = keyTable.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getValueMetaData().getMappedBy()));
            SQLExpression valueExpr = exprFactory.newExpression(stmt, keySqlTbl, valueMapping);
            return valueExpr;
        }
    }
    throw new NucleusException("Map.get() for the filter is not supported for " + mapExpr + " with an argument of " + keyValExpr + ". Why not contribute support for it?");
}
Also used : MapTable(org.datanucleus.store.rdbms.table.MapTable) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) MapMetaData(org.datanucleus.metadata.MapMetaData) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Example 50 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class ListGetMethod method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List<SQLExpression> args) {
    if (args == null || args.size() == 0 || args.size() > 1) {
        throw new NucleusException(Localiser.msg("060016", "get", "CollectionExpression", 1));
    }
    CollectionExpression listSqlExpr = (CollectionExpression) expr;
    AbstractMemberMetaData mmd = listSqlExpr.getJavaTypeMapping().getMemberMetaData();
    if (mmd == null) {
        // TODO Cater for the List being an input parameter
        throw new NucleusException(Localiser.msg("060020", "indexOf", listSqlExpr.getClass().getName()));
    }
    if (!List.class.isAssignableFrom(mmd.getType())) {
        throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the field is not a List!");
    } else if (mmd.getOrderMetaData() != null && !mmd.getOrderMetaData().isIndexedList()) {
        throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the field is not an 'indexed' List!");
    }
    SQLExpression idxExpr = args.get(0);
    if (idxExpr instanceof SQLLiteral) {
        if (!(((SQLLiteral) idxExpr).getValue() instanceof Number)) {
            throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the index is not a numeric literal so not yet supported");
        }
    } else {
        throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the index is not a numeric literal so not yet supported");
    }
    if (listSqlExpr instanceof CollectionLiteral && idxExpr instanceof SQLLiteral) {
        CollectionLiteral lit = (CollectionLiteral) expr;
        if (lit.getValue() == null) {
            return new NullLiteral(stmt, null, null, null);
        }
        return lit.invoke("get", args);
    }
    if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.FILTER) {
        return getAsInnerJoin(stmt, listSqlExpr, idxExpr);
    } else if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.ORDERING || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.RESULT || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.HAVING) {
        return getAsSubquery(stmt, listSqlExpr, idxExpr);
    }
    throw new NucleusException("List.get() is not supported for " + listSqlExpr + " with argument " + idxExpr + " for query component " + stmt.getQueryGenerator().getCompilationComponent());
}
Also used : CollectionLiteral(org.datanucleus.store.rdbms.sql.expression.CollectionLiteral) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) SQLLiteral(org.datanucleus.store.rdbms.sql.expression.SQLLiteral) List(java.util.List) CollectionExpression(org.datanucleus.store.rdbms.sql.expression.CollectionExpression) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) NullLiteral(org.datanucleus.store.rdbms.sql.expression.NullLiteral)

Aggregations

NucleusException (org.datanucleus.exceptions.NucleusException)326 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)71 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)67 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)62 ParameterExpression (org.datanucleus.query.expression.ParameterExpression)53 PrimaryExpression (org.datanucleus.query.expression.PrimaryExpression)52 ArrayList (java.util.ArrayList)48 Literal (org.datanucleus.query.expression.Literal)47 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)44 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)43 InvokeExpression (org.datanucleus.query.expression.InvokeExpression)40 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)37 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)36 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)35 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)35 Expression (org.datanucleus.query.expression.Expression)32 HashMap (java.util.HashMap)31 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)31 VariableExpression (org.datanucleus.query.expression.VariableExpression)26 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)26