Search in sources :

Example 26 with AbstractClassMetaData

use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.

the class DiscriminatorStatementGenerator method getStatement.

/**
 * Accessor for the SelectStatement.
 * @param ec ExecutionContext
 * @return The SelectStatement for iterating through objects with a discriminator column
 */
public SelectStatement getStatement(ExecutionContext ec) {
    SelectStatement stmt = null;
    SQLTable discrimSqlTbl = null;
    if (joinTable == null) {
        // Select of candidate table
        stmt = new SelectStatement(parentStmt, storeMgr, candidateTable, candidateTableAlias, candidateTableGroupName);
        stmt.setClassLoaderResolver(clr);
        discrimSqlTbl = stmt.getPrimaryTable();
    } else {
        // Select of join table, with join to element table
        stmt = new SelectStatement(parentStmt, storeMgr, joinTable, joinTableAlias, candidateTableGroupName);
        stmt.setClassLoaderResolver(clr);
        JavaTypeMapping candidateIdMapping = candidateTable.getIdMapping();
        if (hasOption(OPTION_ALLOW_NULLS)) {
            // Put element table in same table group since all relates to the elements
            discrimSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, null, joinElementMapping, candidateTable, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
        } else {
            // Put element table in same table group since all relates to the elements
            discrimSqlTbl = stmt.join(JoinType.INNER_JOIN, null, joinElementMapping, candidateTable, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
        }
    }
    JavaTypeMapping discMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
    if (discMapping != null) {
        // Allow for discriminator being in super-table of the candidate table
        discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, discrimSqlTbl, discMapping);
    }
    DiscriminatorMetaData dismd = discrimSqlTbl.getTable().getDiscriminatorMetaData();
    boolean hasDiscriminator = (discMapping != null && dismd != null && dismd.getStrategy() != DiscriminatorStrategy.NONE);
    // Check if we can omit the discriminator restriction
    boolean restrictDiscriminator = hasOption(OPTION_RESTRICT_DISCRIM);
    if (hasDiscriminator && restrictDiscriminator) {
        // Add the discriminator expression to restrict accepted values
        boolean multipleCandidates = false;
        BooleanExpression discExpr = null;
        if (candidates != null) {
            // Multiple candidates
            if (candidates.length > 1) {
                multipleCandidates = true;
            }
            for (int i = 0; i < candidates.length; i++) {
                if (Modifier.isAbstract(candidates[i].getModifiers())) {
                    // No point selecting this candidate since can't be instantiated
                    continue;
                }
                BooleanExpression discExprCandidate = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, candidates[i].getName(), dismd, discMapping, discrimSqlTbl, clr);
                if (discExpr != null) {
                    discExpr = discExpr.ior(discExprCandidate);
                } else {
                    discExpr = discExprCandidate;
                }
                if (includeSubclasses) {
                    Collection<String> subclassNames = storeMgr.getSubClassesForClass(candidateType.getName(), true, clr);
                    Iterator<String> subclassIter = subclassNames.iterator();
                    if (!multipleCandidates) {
                        multipleCandidates = (subclassNames.size() > 0);
                    }
                    while (subclassIter.hasNext()) {
                        String subclassName = subclassIter.next();
                        BooleanExpression discExprSub = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, subclassName, dismd, discMapping, discrimSqlTbl, clr);
                        discExpr = discExpr.ior(discExprSub);
                    }
                }
            }
        } else {
            // Single candidate
            if (!Modifier.isAbstract(candidateType.getModifiers())) {
                discExpr = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, candidateType.getName(), dismd, discMapping, discrimSqlTbl, clr);
            }
            if (includeSubclasses) {
                Collection<String> subclassNames = storeMgr.getSubClassesForClass(candidateType.getName(), true, clr);
                Iterator<String> subclassIter = subclassNames.iterator();
                multipleCandidates = (subclassNames.size() > 0);
                while (subclassIter.hasNext()) {
                    String subclassName = subclassIter.next();
                    Class subclass = clr.classForName(subclassName);
                    if ((Modifier.isAbstract(subclass.getModifiers()))) {
                        continue;
                    }
                    BooleanExpression discExprCandidate = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, subclassName, dismd, discMapping, discrimSqlTbl, clr);
                    if (discExpr == null) {
                        discExpr = discExprCandidate;
                    } else {
                        discExpr = discExpr.ior(discExprCandidate);
                    }
                }
            }
            if (discExpr == null) {
                // No possible candidates, so set expression as "1=0"
                SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
                JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
                discExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
            }
        }
        if (discExpr != null) {
            if (hasOption(OPTION_ALLOW_NULLS)) {
                // Allow for null value of discriminator
                SQLExpression expr = stmt.getSQLExpressionFactory().newExpression(stmt, discrimSqlTbl, discMapping);
                SQLExpression val = new NullLiteral(stmt, null, null, null);
                BooleanExpression nullDiscExpr = expr.eq(val);
                discExpr = discExpr.ior(nullDiscExpr);
                if (!multipleCandidates) {
                    multipleCandidates = true;
                }
            }
            // Apply the discriminator to the query statement
            if (multipleCandidates) {
                discExpr.encloseInParentheses();
            }
            stmt.whereAnd(discExpr, true);
        }
    }
    JavaTypeMapping multitenancyMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
    if (multitenancyMapping != null) {
        // Multi-tenancy restriction
        AbstractClassMetaData cmd = candidateTable.getClassMetaData();
        SQLTable tenantSqlTbl = stmt.getTable(multitenancyMapping.getTable(), discrimSqlTbl.getGroupName());
        SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, tenantSqlTbl, multitenancyMapping);
        SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, cmd));
        stmt.whereAnd(tenantExpr.eq(tenantVal), true);
    }
    JavaTypeMapping softDeleteMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
    if (softDeleteMapping != null && !hasOption(OPTION_INCLUDE_SOFT_DELETES)) {
        // Soft-delete restriction
        SQLTable softDeleteSqlTbl = stmt.getTable(softDeleteMapping.getTable(), discrimSqlTbl.getGroupName());
        SQLExpression softDeleteExpr = stmt.getSQLExpressionFactory().newExpression(stmt, softDeleteSqlTbl, softDeleteMapping);
        SQLExpression softDeleteVal = stmt.getSQLExpressionFactory().newLiteral(stmt, softDeleteMapping, Boolean.FALSE);
        stmt.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
    }
    return stmt;
}
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) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) NullLiteral(org.datanucleus.store.rdbms.sql.expression.NullLiteral)

Example 27 with AbstractClassMetaData

use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.

the class BaseContainerStore method getComponentInformationForClass.

/**
 * Convenience method to find the element information relating to the element type.
 * Used specifically for the "element-type" of a collection/array to find the elements which have table information.
 * @param componentType Type of the component
 * @param componentCmd Metadata for the root component class TODO Get rid of this
 * @return Element information relating to the element type
 */
protected ComponentInfo[] getComponentInformationForClass(String componentType, AbstractClassMetaData componentCmd) {
    ComponentInfo[] info = null;
    DatastoreClass rootTbl;
    String[] clsNames;
    if (clr.classForName(componentType).isInterface()) {
        // Collection<interface>, so find implementations of the interface
        clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(componentType, clr);
        rootTbl = null;
    } else {
        clsNames = new String[] { componentType };
        rootTbl = storeMgr.getDatastoreClass(componentType, clr);
    }
    if (componentCmd.getBaseAbstractClassMetaData().getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
        // Element uses COMPLETE-TABLE so need an elementInfo for each possible element that has a table
        List<ComponentInfo> infos = new ArrayList<>();
        if (rootTbl != null) {
            infos.add(new ComponentInfo(componentCmd, rootTbl));
        }
        Collection<String> elementSubclassNames = storeMgr.getSubClassesForClass(componentCmd.getFullClassName(), true, clr);
        if (elementSubclassNames != null) {
            for (String elementSubclassName : elementSubclassNames) {
                AbstractClassMetaData elemSubCmd = storeMgr.getMetaDataManager().getMetaDataForClass(elementSubclassName, clr);
                DatastoreClass elemSubTbl = storeMgr.getDatastoreClass(elementSubclassName, clr);
                if (elemSubTbl != null) {
                    infos.add(new ComponentInfo(elemSubCmd, elemSubTbl));
                }
            }
        }
        info = new ComponentInfo[infos.size()];
        int infoNo = 0;
        for (ComponentInfo ci : infos) {
            info[infoNo++] = ci;
        }
    } else {
        if (rootTbl == null) {
            // Root class has no table (abstract, or subclass-table)
            if (clr.classForName(componentType).isInterface()) {
                info = new ComponentInfo[clsNames.length];
                for (int i = 0; i < clsNames.length; i++) {
                    AbstractClassMetaData implCmd = storeMgr.getMetaDataManager().getMetaDataForClass(clsNames[i], clr);
                    DatastoreClass table = storeMgr.getDatastoreClass(clsNames[i], clr);
                    info[i] = new ComponentInfo(implCmd, table);
                }
            } else {
                AbstractClassMetaData[] subclassCmds = storeMgr.getClassesManagingTableForClass(componentCmd, clr);
                info = new ComponentInfo[subclassCmds.length];
                for (int i = 0; i < subclassCmds.length; i++) {
                    DatastoreClass table = storeMgr.getDatastoreClass(subclassCmds[i].getFullClassName(), clr);
                    info[i] = new ComponentInfo(subclassCmds[i], table);
                }
            }
        } else {
            info = new ComponentInfo[clsNames.length];
            for (int i = 0; i < clsNames.length; i++) {
                AbstractClassMetaData cmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(clsNames[i], clr);
                DatastoreClass table = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr);
                info[i] = new ComponentInfo(cmd, table);
            }
        }
    }
    return info;
}
Also used : ArrayList(java.util.ArrayList) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Example 28 with AbstractClassMetaData

use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.

the class SQLText method applyParametersToStatement.

/**
 * Method to set the parameters in the supplied PreparedStatement using their mappings and
 * provided values.
 * @param ec execution context
 * @param ps The PreparedStatement
 */
public void applyParametersToStatement(ExecutionContext ec, PreparedStatement ps) {
    if (parameters != null) {
        int num = 1;
        Iterator<SQLStatementParameter> i = parameters.iterator();
        while (i.hasNext()) {
            SQLStatementParameter param = i.next();
            JavaTypeMapping mapping = param.getMapping();
            if (mapping != null) {
                Object value = param.getValue();
                if (param.getColumnNumber() >= 0) {
                    Object colValue = null;
                    if (value != null) {
                        // Parameter is for a particular column of the overall object/mapping
                        // so assume that the object is persistable (or id of persistable)
                        ClassLoaderResolver clr = ec.getClassLoaderResolver();
                        AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(mapping.getType(), clr);
                        RDBMSStoreManager storeMgr = mapping.getStoreManager();
                        if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                            colValue = mapping.getValueForDatastoreMapping(ec.getNucleusContext(), param.getColumnNumber(), value);
                        } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                            colValue = SQLStatementHelper.getValueForPrimaryKeyIndexOfObjectUsingReflection(value, param.getColumnNumber(), cmd, storeMgr, clr);
                        }
                    }
                    mapping.getDatastoreMapping(param.getColumnNumber()).setObject(ps, num, colValue);
                    num++;
                } else {
                    mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
                    if (mapping.getNumberOfDatastoreMappings() > 0) {
                        num += mapping.getNumberOfDatastoreMappings();
                    } else {
                        num += 1;
                    }
                }
            }
        }
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager)

Example 29 with AbstractClassMetaData

use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.

the class UnionStatementGenerator method getStatement.

/**
 * Accessor for the SelectStatement for the candidate [+ subclasses].
 * @param ec ExecutionContext
 * @return The SelectStatement returning objects with a UNION statement.
 */
public SelectStatement getStatement(ExecutionContext ec) {
    // Find set of possible candidates (including subclasses of subclasses)
    Collection<String> candidateClassNames = new ArrayList<>();
    AbstractClassMetaData acmd = storeMgr.getMetaDataManager().getMetaDataForClass(candidateType, clr);
    candidateClassNames.add(acmd.getFullClassName());
    if (includeSubclasses) {
        Collection<String> subclasses = storeMgr.getSubClassesForClass(candidateType.getName(), true, clr);
        candidateClassNames.addAll(subclasses);
    }
    // Eliminate any classes that are not instantiable
    Iterator<String> iter = candidateClassNames.iterator();
    while (iter.hasNext()) {
        String className = iter.next();
        try {
            Class cls = clr.classForName(className);
            if (Modifier.isAbstract(cls.getModifiers())) {
                // Remove since abstract hence not instantiable
                iter.remove();
            }
        } catch (Exception e) {
            // Remove since class not found
            iter.remove();
        }
    }
    if (hasOption(OPTION_SELECT_DN_TYPE)) {
        // Get the length of the longest class name
        iter = candidateClassNames.iterator();
        while (iter.hasNext()) {
            String className = iter.next();
            if (className.length() > maxClassNameLength) {
                maxClassNameLength = className.length();
            }
        }
    }
    if (candidateClassNames.isEmpty()) {
        // Either passed invalid classes, or no concrete classes with available tables present!
        throw new NucleusException("Attempt to generate SQL statement using UNIONs for " + candidateType.getName() + " yet there are no concrete classes with their own table available");
    }
    SelectStatement stmt = null;
    for (String candidateClassName : candidateClassNames) {
        SelectStatement candidateStmt = null;
        if (joinTable == null) {
            // Select of candidate table
            candidateStmt = getSelectStatementForCandidate(candidateClassName, ec);
        } else {
            // Select of join table and join to element
            candidateStmt = getSQLStatementForCandidateViaJoin(candidateClassName);
        }
        if (candidateStmt != null) {
            if (stmt == null) {
                stmt = candidateStmt;
            } else {
                stmt.union(candidateStmt);
            }
        }
    }
    return stmt;
}
Also used : ArrayList(java.util.ArrayList) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 30 with AbstractClassMetaData

use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.

the class SQLStatementHelper method getDiscriminatorValuesForMember.

/**
 * Method to return all possible discriminator values for the supplied class and its subclasses.
 * @param className Name of the class
 * @param discMapping The discriminator mapping
 * @param storeMgr StoreManager
 * @param clr ClassLoader resolver
 * @return The possible discriminator values
 */
public static List getDiscriminatorValuesForMember(String className, JavaTypeMapping discMapping, RDBMSStoreManager storeMgr, ClassLoaderResolver clr) {
    List discrimValues = new ArrayList();
    DiscriminatorStrategy strategy = discMapping.getTable().getDiscriminatorMetaData().getStrategy();
    if (strategy != DiscriminatorStrategy.NONE) {
        MetaDataManager mmgr = storeMgr.getMetaDataManager();
        AbstractClassMetaData cmd = mmgr.getMetaDataForClass(className, clr);
        discrimValues.add(cmd.getDiscriminatorValue());
        Collection<String> subclasses = storeMgr.getSubClassesForClass(className, true, clr);
        if (subclasses != null && subclasses.size() > 0) {
            Iterator<String> subclassesIter = subclasses.iterator();
            while (subclassesIter.hasNext()) {
                String subclassName = subclassesIter.next();
                AbstractClassMetaData subclassCmd = mmgr.getMetaDataForClass(subclassName, clr);
                discrimValues.add(subclassCmd.getDiscriminatorValue());
            }
        }
    }
    return discrimValues;
}
Also used : DiscriminatorStrategy(org.datanucleus.metadata.DiscriminatorStrategy) ArrayList(java.util.ArrayList) MetaDataManager(org.datanucleus.metadata.MetaDataManager) List(java.util.List) ArrayList(java.util.ArrayList) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Aggregations

AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)204 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)90 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)69 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)59 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)55 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)42 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)42 NucleusException (org.datanucleus.exceptions.NucleusException)37 MetaDataManager (org.datanucleus.metadata.MetaDataManager)37 ArrayList (java.util.ArrayList)31 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)26 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)23 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)22 ClassLoaderResolverImpl (org.datanucleus.ClassLoaderResolverImpl)19 MapTable (org.datanucleus.store.rdbms.table.MapTable)18 List (java.util.List)16 ObjectProvider (org.datanucleus.state.ObjectProvider)16 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)16 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)16 Iterator (java.util.Iterator)15