Search in sources :

Example 66 with SQLExpressionFactory

use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.

the class RDBMSStoreHelper method getClassNameForIdUsingUnion.

/**
 * Utility that does a union candidate query for the specified candidate(s) and subclasses
 * and returns the class name of the instance that has the specified identity (if any).
 * @param storeMgr RDBMS StoreManager
 * @param ec execution context
 * @param id The id
 * @param rootCmds Metadata for the classes at the root
 * @return Name of the class with this identity (or null if none found)
 */
public static String getClassNameForIdUsingUnion(RDBMSStoreManager storeMgr, ExecutionContext ec, Object id, List<AbstractClassMetaData> rootCmds) {
    // Check for input error
    if (rootCmds == null || rootCmds.isEmpty() || id == null) {
        return null;
    }
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    ClassLoaderResolver clr = ec.getClassLoaderResolver();
    // Form a query UNIONing all possible root candidates (and their subclasses)
    Iterator<AbstractClassMetaData> rootCmdIter = rootCmds.iterator();
    // Metadata for sample class in the tree so we can check if needs locking
    AbstractClassMetaData sampleCmd = null;
    SelectStatement sqlStmtMain = null;
    while (rootCmdIter.hasNext()) {
        AbstractClassMetaData rootCmd = rootCmdIter.next();
        DatastoreClass rootTbl = storeMgr.getDatastoreClass(rootCmd.getFullClassName(), clr);
        InheritanceMetaData rootInhmd = rootCmd.getBaseAbstractClassMetaData().getInheritanceMetaData();
        if (rootInhmd.getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
            // COMPLETE TABLE so use one branch of UNION for each possible class
            if (rootTbl != null) {
                UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, clr.classForName(rootCmd.getFullClassName()), false, null, null);
                stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
                if (sqlStmtMain == null) {
                    sampleCmd = rootCmd;
                    sqlStmtMain = stmtGen.getStatement(ec);
                    // WHERE (object id) = ?
                    JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping();
                    JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
                    SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping);
                    SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID");
                    sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true);
                } else {
                    SelectStatement sqlStmt = stmtGen.getStatement(ec);
                    // WHERE (object id) = ?
                    JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
                    JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
                    SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
                    SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
                    sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true);
                    sqlStmtMain.union(sqlStmt);
                }
            }
            Collection<String> rootSubclassNames = storeMgr.getSubClassesForClass(rootCmd.getFullClassName(), true, clr);
            for (String rootSubclassName : rootSubclassNames) {
                AbstractClassMetaData rootSubclassCmd = storeMgr.getMetaDataManager().getMetaDataForClass(rootSubclassName, clr);
                DatastoreClass rootSubclassTbl = storeMgr.getDatastoreClass(rootSubclassCmd.getFullClassName(), clr);
                if (rootSubclassTbl != null) {
                    UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, clr.classForName(rootSubclassCmd.getFullClassName()), false, null, null);
                    stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
                    if (sqlStmtMain == null) {
                        sampleCmd = rootSubclassCmd;
                        sqlStmtMain = stmtGen.getStatement(ec);
                        // WHERE (object id) = ?
                        JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping();
                        JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
                        SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping);
                        SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID");
                        sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true);
                    } else {
                        SelectStatement sqlStmt = stmtGen.getStatement(ec);
                        // WHERE (object id) = ?
                        JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
                        JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
                        SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
                        SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
                        sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true);
                        sqlStmtMain.union(sqlStmt);
                    }
                }
            }
            continue;
        }
        if (rootTbl == null) {
            // Class must be using "subclass-table" (no table of its own) so find where it is
            AbstractClassMetaData[] subcmds = storeMgr.getClassesManagingTableForClass(rootCmd, clr);
            if (subcmds == null || subcmds.length == 0) {
            // No table for this class so ignore
            } else {
                for (int i = 0; i < subcmds.length; i++) {
                    UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, clr.classForName(subcmds[i].getFullClassName()), true, null, null);
                    stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
                    if (sqlStmtMain == null) {
                        sampleCmd = subcmds[i];
                        sqlStmtMain = stmtGen.getStatement(ec);
                        // WHERE (object id) = ?
                        JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping();
                        JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
                        SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping);
                        SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID");
                        sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true);
                    } else {
                        SelectStatement sqlStmt = stmtGen.getStatement(ec);
                        // WHERE (object id) = ?
                        JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
                        JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
                        SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
                        SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
                        sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true);
                        sqlStmtMain.union(sqlStmt);
                    }
                }
            }
        } else {
            UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, clr.classForName(rootCmd.getFullClassName()), true, null, null);
            stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
            if (sqlStmtMain == null) {
                sampleCmd = rootCmd;
                sqlStmtMain = stmtGen.getStatement(ec);
                // WHERE (object id) = ?
                JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping();
                JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
                SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping);
                SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID");
                sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true);
            } else {
                SelectStatement sqlStmt = stmtGen.getStatement(ec);
                // WHERE (object id) = ?
                JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
                JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
                SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
                SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
                sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true);
                sqlStmtMain.union(sqlStmt);
            }
        }
    }
    // Perform the query
    if (sqlStmtMain != null) {
        try {
            ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
            SQLController sqlControl = storeMgr.getSQLController();
            if (sampleCmd != null && ec.getSerializeReadForClass(sampleCmd.getFullClassName())) {
                sqlStmtMain.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
            }
            try {
                PreparedStatement ps = SQLStatementHelper.getPreparedStatementForSQLStatement(sqlStmtMain, ec, mconn, null, null);
                String statement = sqlStmtMain.getSQLText().toSQL();
                try {
                    ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps);
                    try {
                        while (rs.next()) {
                            try {
                                return rs.getString(UnionStatementGenerator.DN_TYPE_COLUMN).trim();
                            } catch (SQLException sqle) {
                            }
                        }
                    } finally {
                        rs.close();
                    }
                } finally {
                    sqlControl.closeStatement(mconn, ps);
                }
            } finally {
                mconn.release();
            }
        } catch (SQLException sqe) {
            NucleusLogger.DATASTORE.error("Exception with UNION statement", sqe);
            throw new NucleusDataStoreException(sqe.toString());
        }
    }
    return null;
}
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) SQLException(java.sql.SQLException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) PreparedStatement(java.sql.PreparedStatement) PersistableIdMapping(org.datanucleus.store.rdbms.mapping.java.PersistableIdMapping) InheritanceMetaData(org.datanucleus.metadata.InheritanceMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) UnionStatementGenerator(org.datanucleus.store.rdbms.sql.UnionStatementGenerator) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass)

Example 67 with SQLExpressionFactory

use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.

the class FKSetStore method getIteratorStatement.

/**
 * Method to return the SQLStatement and mapping for an iterator for this backing store.
 * Create a statement of the form
 * <pre>
 * SELECT ELEM_COLS
 * FROM ELEM_TBL
 * [WHERE]
 *   [ELEM_TBL.OWNER_ID = {value}] [AND]
 *   [ELEM_TBL.DISCRIM = {discrimValue}]
 * [ORDER BY {orderClause}]
 * </pre>
 * @param ec ExecutionContext
 * @param fp FetchPlan to use in determining which fields of element to select
 * @param addRestrictionOnOwner Whether to restrict to a particular owner (otherwise functions as bulk fetch for many owners).
 * @return The SQLStatement and its associated StatementClassMapping
 */
public IteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner) {
    SelectStatement sqlStmt = null;
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    StatementClassMapping iteratorMappingClass = new StatementClassMapping();
    if (elementInfo[0].getDatastoreClass().getDiscriminatorMetaData() != null && elementInfo[0].getDatastoreClass().getDiscriminatorMetaData().getStrategy() != DiscriminatorStrategy.NONE) {
        // TODO Only caters for one elementInfo, but with subclass-table we can have multiple
        String elementType = ownerMemberMetaData.getCollection().getElementType();
        if (ClassUtils.isReferenceType(clr.classForName(elementType))) {
            String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(elementType, clr);
            Class[] cls = new Class[clsNames.length];
            for (int i = 0; i < clsNames.length; i++) {
                cls[i] = clr.classForName(clsNames[i]);
            }
            sqlStmt = new DiscriminatorStatementGenerator(storeMgr, clr, cls, true, null, null).getStatement(ec);
        } else {
            sqlStmt = new DiscriminatorStatementGenerator(storeMgr, clr, clr.classForName(elementInfo[0].getClassName()), true, null, null).getStatement(ec);
        }
        iterateUsingDiscriminator = true;
        // TODO Cater for having all possible subclasses stored in the same table (so we can select their fields too)
        // String[] elemSubclasses = op.getExecutionContext().getMetaDataManager().getSubclassesForClass(emd.getFullClassName(), false);
        // NucleusLogger.GENERAL.info(">> FKSetStore.iter iterMapDef=" + iteratorMappingDef + " table=" + sqlStmt.getPrimaryTable() +
        // " emd=" + emd.getFullClassName() + " elem.subclasses=" + StringUtils.objectArrayToString(elemSubclasses));
        // Select the required fields (of the element class)
        SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingClass, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
    } else {
        boolean selectFetchPlan = true;
        Class elementTypeCls = clr.classForName(elementType);
        if (elementTypeCls.isInterface() && elementInfo.length > 1) {
            // Multiple implementations of an interface, so assume the FetchPlan differs between implementation
            selectFetchPlan = false;
        }
        // TODO This only works if the different elementInfos have the same number of PK fields (otherwise get SQL error in UNION)
        for (int i = 0; i < elementInfo.length; i++) {
            final Class elementCls = clr.classForName(this.elementInfo[i].getClassName());
            UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, elementCls, true, null, null);
            stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
            iteratorMappingClass.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
            SelectStatement subStmt = stmtGen.getStatement(ec);
            if (selectFetchPlan) {
                // Select the FetchPlan fields (of the element class)
                if (sqlStmt == null) {
                    SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(subStmt, iteratorMappingClass, fp, subStmt.getPrimaryTable(), elementInfo[i].getAbstractClassMetaData(), fp.getMaxFetchDepth());
                } else {
                    SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(subStmt, null, fp, subStmt.getPrimaryTable(), elementInfo[i].getAbstractClassMetaData(), fp.getMaxFetchDepth());
                }
            } else {
                // Select the candidate id of the element class only
                if (sqlStmt == null) {
                    SQLStatementHelper.selectIdentityOfCandidateInStatement(subStmt, iteratorMappingClass, elementInfo[i].getAbstractClassMetaData());
                } else {
                    SQLStatementHelper.selectIdentityOfCandidateInStatement(subStmt, null, elementInfo[i].getAbstractClassMetaData());
                }
            }
            if (sqlStmt == null) {
                sqlStmt = subStmt;
            } else {
                sqlStmt.union(subStmt);
            }
        }
        if (sqlStmt == null) {
            throw new NucleusException("Unable to generate iterator statement for field " + getOwnerMemberMetaData().getFullFieldName());
        }
    }
    if (addRestrictionOnOwner) {
        // Apply condition to filter by owner
        // TODO If ownerMapping is not for containerTable then do JOIN to ownerTable in the FROM clause (or find if already done)
        SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
        SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
        SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
        sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
    }
    if (relationDiscriminatorMapping != null) {
        // Apply condition on distinguisher field to filter by distinguisher (when present)
        SQLTable distSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), relationDiscriminatorMapping);
        SQLExpression distExpr = exprFactory.newExpression(sqlStmt, distSqlTbl, relationDiscriminatorMapping);
        SQLExpression distVal = exprFactory.newLiteral(sqlStmt, relationDiscriminatorMapping, relationDiscriminatorValue);
        sqlStmt.whereAnd(distExpr.eq(distVal), true);
    }
    if (orderMapping != null) {
        // Order by the ordering column, when present
        SQLTable orderSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
        SQLExpression[] orderExprs = new SQLExpression[orderMapping.getNumberOfDatastoreMappings()];
        boolean[] descendingOrder = new boolean[orderMapping.getNumberOfDatastoreMappings()];
        orderExprs[0] = exprFactory.newExpression(sqlStmt, orderSqlTbl, orderMapping);
        sqlStmt.setOrdering(orderExprs, descendingOrder);
    }
    return new IteratorStatement(this, sqlStmt, iteratorMappingClass);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) UnionStatementGenerator(org.datanucleus.store.rdbms.sql.UnionStatementGenerator) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) DiscriminatorStatementGenerator(org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 68 with SQLExpressionFactory

use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.

the class JoinArrayStore method getIteratorStatement.

/**
 * Method to return the SQLStatement and mapping for an iterator for this backing store.
 * Create a statement of the form
 * <pre>
 * SELECT ELEM_COLS
 * FROM JOIN_TBL
 *   [JOIN ELEM_TBL ON ELEM_TBL.ID = JOIN_TBL.ELEM_ID]
 * [WHERE]
 *   [JOIN_TBL.OWNER_ID = {value}] [AND]
 *   [JOIN_TBL.DISCRIM = {discrimValue}]
 * [ORDER BY {orderClause}]
 * </pre>
 * @param ec ExecutionContext
 * @param fp FetchPlan to use in determing which fields of element to select
 * @param addRestrictionOnOwner Whether to restrict to a particular owner (otherwise functions as bulk fetch for many owners).
 * @return The SQLStatement and its associated StatementClassMapping
 */
public IteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner) {
    SelectStatement sqlStmt = null;
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    StatementClassMapping iteratorMappingClass = null;
    if (elementsAreEmbedded || elementsAreSerialised) {
        // Element = embedded, serialised (maybe Non-PC)
        // Just select the join table since we're going to return the embedded/serialised columns from it
        sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
        sqlStmt.setClassLoaderResolver(clr);
        // Select the element column - first select is assumed by SetStoreIterator
        sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
    // TODO If embedded element and it includes 1-1/N-1 in FetchPlan then select its fields also
    } else if (elementMapping instanceof ReferenceMapping) {
        // Element = Reference type (interface/Object)
        // Just select the join table since we're going to return the implementation id columns only
        sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
        sqlStmt.setClassLoaderResolver(clr);
        // Select the reference column(s) - first select is assumed by SetStoreIterator
        sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
    } else {
        // Element = PC
        // Join to the element table(s)
        iteratorMappingClass = new StatementClassMapping();
        for (int i = 0; i < elementInfo.length; i++) {
            // TODO This will only work if all element types have a discriminator
            final int elementNo = i;
            final Class elementCls = clr.classForName(elementInfo[elementNo].getClassName());
            SelectStatement elementStmt = null;
            if (elementInfo[elementNo].getDiscriminatorStrategy() != null && elementInfo[elementNo].getDiscriminatorStrategy() != DiscriminatorStrategy.NONE) {
                // The element uses a discriminator so just use that in the SELECT
                String elementType = ownerMemberMetaData.getCollection().getElementType();
                if (ClassUtils.isReferenceType(clr.classForName(elementType))) {
                    String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(elementType, clr);
                    Class[] cls = new Class[clsNames.length];
                    for (int j = 0; j < clsNames.length; j++) {
                        cls[j] = clr.classForName(clsNames[j]);
                    }
                    SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, cls, true, null, null, containerTable, null, elementMapping);
                    if (allowNulls) {
                        stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
                    }
                    elementStmt = stmtGen.getStatement(ec);
                } else {
                    SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
                    if (allowNulls) {
                        stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
                    }
                    elementStmt = stmtGen.getStatement(ec);
                }
                iterateUsingDiscriminator = true;
            } else {
                // No discriminator, but subclasses so use UNIONs
                SelectStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
                stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
                if (allowNulls) {
                    stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
                }
                iteratorMappingClass.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
                elementStmt = stmtGen.getStatement(ec);
            }
            if (sqlStmt == null) {
                sqlStmt = elementStmt;
            } else {
                sqlStmt.union(elementStmt);
            }
        }
        if (sqlStmt == null) {
            throw new NucleusException("Error in generation of SQL statement for iterator over (Join) array. Statement is null");
        }
        // Select the required fields
        SQLTable elementSqlTbl = sqlStmt.getTable(elementInfo[0].getDatastoreClass(), sqlStmt.getPrimaryTable().getGroupName());
        SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingClass, fp, elementSqlTbl, elementCmd, fp.getMaxFetchDepth());
    }
    if (addRestrictionOnOwner) {
        // Apply condition on join-table owner field to filter by owner
        SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
        SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
        SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
        sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
    }
    if (relationDiscriminatorMapping != null) {
        // Apply condition on distinguisher field to filter by distinguisher (when present)
        SQLTable distSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), relationDiscriminatorMapping);
        SQLExpression distExpr = exprFactory.newExpression(sqlStmt, distSqlTbl, relationDiscriminatorMapping);
        SQLExpression distVal = exprFactory.newLiteral(sqlStmt, relationDiscriminatorMapping, relationDiscriminatorValue);
        sqlStmt.whereAnd(distExpr.eq(distVal), true);
    }
    if (orderMapping != null) {
        // Order by the ordering column, when present
        SQLTable orderSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
        SQLExpression[] orderExprs = new SQLExpression[orderMapping.getNumberOfDatastoreMappings()];
        boolean[] descendingOrder = new boolean[orderMapping.getNumberOfDatastoreMappings()];
        orderExprs[0] = exprFactory.newExpression(sqlStmt, orderSqlTbl, orderMapping);
        sqlStmt.setOrdering(orderExprs, descendingOrder);
    }
    return new IteratorStatement(this, sqlStmt, iteratorMappingClass);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) UnionStatementGenerator(org.datanucleus.store.rdbms.sql.UnionStatementGenerator) SelectStatementGenerator(org.datanucleus.store.rdbms.sql.SelectStatementGenerator) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) DiscriminatorStatementGenerator(org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 69 with SQLExpressionFactory

use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.

the class JoinSetStore method getIteratorStatement.

/**
 * Method to return the SQLStatement and mapping for an iterator for this backing store.
 * Create a statement of the form
 * <pre>
 * SELECT ELEM_COLS
 * FROM JOIN_TBL
 *   [JOIN ELEM_TBL ON ELEM_TBL.ID = JOIN_TBL.ELEM_ID]
 * [WHERE]
 *   [JOIN_TBL.OWNER_ID = {value}] [AND]
 *   [JOIN_TBL.DISCRIM = {discrimValue}]
 * [ORDER BY {orderClause}]
 * </pre>
 * @param ec ExecutionContext
 * @param fp FetchPlan to use in determining which fields of element to select
 * @param addRestrictionOnOwner Whether to restrict to a particular owner (otherwise functions as bulk fetch for many owners).
 * @return The SQLStatement and its associated StatementClassMapping
 */
public IteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner) {
    SelectStatement sqlStmt = null;
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    StatementClassMapping iteratorMappingClass = null;
    if (elementsAreEmbedded || elementsAreSerialised) {
        // Element = embedded, serialised (maybe Non-PC)
        // Just select the join table since we're going to return the embedded/serialised columns from it
        sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
        sqlStmt.setClassLoaderResolver(clr);
        // Select the element column - first select is assumed by SetStoreIterator
        sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
    // TODO If embedded element and it includes 1-1/N-1 in FetchPlan then select its fields also
    } else if (elementMapping instanceof ReferenceMapping) {
        // Element = Reference type (interface/Object)
        // Just select the join table since we're going to return the implementation id columns only
        sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
        sqlStmt.setClassLoaderResolver(clr);
        // Select the reference column(s) - first select is assumed by SetStoreIterator
        sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
    } else {
        // Element = PC
        // Join to the element table(s)
        iteratorMappingClass = new StatementClassMapping();
        for (int i = 0; i < elementInfo.length; i++) {
            final int elementNo = i;
            final Class elementCls = clr.classForName(elementInfo[elementNo].getClassName());
            SelectStatement elementStmt = null;
            if (elementInfo[elementNo].getDiscriminatorStrategy() != null && elementInfo[elementNo].getDiscriminatorStrategy() != DiscriminatorStrategy.NONE) {
                // The element uses a discriminator so just use that in the SELECT
                String elementType = ownerMemberMetaData.getCollection().getElementType();
                if (ClassUtils.isReferenceType(clr.classForName(elementType))) {
                    String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(elementType, clr);
                    Class[] cls = new Class[clsNames.length];
                    for (int j = 0; j < clsNames.length; j++) {
                        cls[j] = clr.classForName(clsNames[j]);
                    }
                    SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, cls, true, null, null, containerTable, null, elementMapping);
                    if (allowNulls) {
                        stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
                    }
                    elementStmt = stmtGen.getStatement(ec);
                } else {
                    SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
                    if (allowNulls) {
                        stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
                    }
                    elementStmt = stmtGen.getStatement(ec);
                }
                iterateUsingDiscriminator = true;
            } else {
                // No discriminator, but subclasses so use UNIONs
                SelectStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
                stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
                iteratorMappingClass.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
                elementStmt = stmtGen.getStatement(ec);
            }
            // TODO What if the first elementInfo has fields selected in one order and then the second in a different order?
            if (sqlStmt == null) {
                sqlStmt = elementStmt;
                // Select the required fields
                SQLTable elementSqlTbl = sqlStmt.getTable(elementInfo[i].getDatastoreClass(), sqlStmt.getPrimaryTable().getGroupName());
                SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingClass, fp, elementSqlTbl, elementCmd, fp.getMaxFetchDepth());
            } else {
                // Select the required fields
                SQLTable elementSqlTbl = elementStmt.getTable(elementInfo[i].getDatastoreClass(), elementStmt.getPrimaryTable().getGroupName());
                SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(elementStmt, iteratorMappingClass, fp, elementSqlTbl, elementCmd, fp.getMaxFetchDepth());
                sqlStmt.union(elementStmt);
            }
        }
    }
    if (sqlStmt == null) {
        throw new NucleusException("Error in generation of SQL statement for iterator over (Join) set. Statement is null");
    }
    if (addRestrictionOnOwner) {
        // Apply condition on join-table owner field to filter by owner
        SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
        SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
        SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
        sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
    }
    if (relationDiscriminatorMapping != null) {
        // Apply condition on distinguisher field to filter by distinguisher (when present)
        SQLTable distSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), relationDiscriminatorMapping);
        SQLExpression distExpr = exprFactory.newExpression(sqlStmt, distSqlTbl, relationDiscriminatorMapping);
        SQLExpression distVal = exprFactory.newLiteral(sqlStmt, relationDiscriminatorMapping, relationDiscriminatorValue);
        sqlStmt.whereAnd(distExpr.eq(distVal), true);
    }
    if (orderMapping != null) {
        // TODO If we have multiple roots then cannot allow this
        // Order by the ordering column, when present
        SQLTable orderSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
        SQLExpression[] orderExprs = new SQLExpression[orderMapping.getNumberOfDatastoreMappings()];
        boolean[] descendingOrder = new boolean[orderMapping.getNumberOfDatastoreMappings()];
        orderExprs[0] = exprFactory.newExpression(sqlStmt, orderSqlTbl, orderMapping);
        sqlStmt.setOrdering(orderExprs, descendingOrder);
    }
    return new IteratorStatement(this, sqlStmt, iteratorMappingClass);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) UnionStatementGenerator(org.datanucleus.store.rdbms.sql.UnionStatementGenerator) SelectStatementGenerator(org.datanucleus.store.rdbms.sql.SelectStatementGenerator) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) DiscriminatorStatementGenerator(org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 70 with SQLExpressionFactory

use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.

the class MapEntrySetStore method getSQLStatementForIterator.

/**
 * Method to generate an SQLStatement for iterating through entries of the map.
 * Creates a statement that selects the table holding the map definition (key/value mappings).
 * Adds a restriction on the ownerMapping of the containerTable so we can restrict to the owner object.
 * Adds a restriction on the keyMapping not being null.
 * <pre>
 * SELECT KEY, VALUE FROM MAP_TABLE WHERE OWNER_ID=? AND KEY IS NOT NULL
 * </pre>
 * @param ownerOP ObjectProvider for the owner object
 * @return The SQLStatement
 */
protected SQLStatement getSQLStatementForIterator(ObjectProvider ownerOP) {
    SelectStatement sqlStmt = new SelectStatement(storeMgr, mapTable, null, null);
    sqlStmt.setClassLoaderResolver(clr);
    // Select the key mapping
    // TODO If key is persistable and has inheritance also select a discriminator to get the type
    SQLTable entrySqlTblForKey = sqlStmt.getPrimaryTable();
    if (keyMapping.getTable() != mapTable) {
        entrySqlTblForKey = sqlStmt.getTableForDatastoreContainer(keyMapping.getTable());
        if (entrySqlTblForKey == null) {
            // Add join to key table
            entrySqlTblForKey = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), sqlStmt.getPrimaryTable().getTable().getIdMapping(), keyMapping.getTable(), null, keyMapping.getTable().getIdMapping(), null, null, true);
        }
    }
    iteratorKeyResultCols = sqlStmt.select(entrySqlTblForKey, keyMapping, null);
    // Select the value mapping
    // TODO If value is persistable and has inheritance also select a discriminator to get the type
    SQLTable entrySqlTblForVal = sqlStmt.getPrimaryTable();
    if (valueMapping.getTable() != mapTable) {
        entrySqlTblForVal = sqlStmt.getTableForDatastoreContainer(valueMapping.getTable());
        if (entrySqlTblForVal == null) {
            // Add join to key table
            entrySqlTblForVal = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), sqlStmt.getPrimaryTable().getTable().getIdMapping(), valueMapping.getTable(), null, valueMapping.getTable().getIdMapping(), null, null, true);
        }
    }
    iteratorValueResultCols = sqlStmt.select(entrySqlTblForVal, valueMapping, null);
    // Apply condition on owner field to filter by owner
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
    SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
    SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
    sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
    // Apply condition that key is not null
    SQLExpression keyExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), keyMapping);
    SQLExpression nullExpr = exprFactory.newLiteral(sqlStmt, null, null);
    sqlStmt.whereAnd(keyExpr.ne(nullExpr), true);
    // Input parameter(s) - the owner
    int inputParamNum = 1;
    StatementMappingIndex ownerIdx = new StatementMappingIndex(ownerMapping);
    if (sqlStmt.getNumberOfUnions() > 0) {
        // Add parameter occurrence for each union of statement
        for (int j = 0; j < sqlStmt.getNumberOfUnions() + 1; j++) {
            int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
            for (int k = 0; k < ownerMapping.getNumberOfDatastoreMappings(); k++) {
                paramPositions[k] = inputParamNum++;
            }
            ownerIdx.addParameterOccurrence(paramPositions);
        }
    } else {
        int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
        for (int k = 0; k < ownerMapping.getNumberOfDatastoreMappings(); k++) {
            paramPositions[k] = inputParamNum++;
        }
        ownerIdx.addParameterOccurrence(paramPositions);
    }
    iteratorMappingParams = new StatementParameterMapping();
    iteratorMappingParams.addMappingForParameter("owner", ownerIdx);
    return sqlStmt;
}
Also used : StatementParameterMapping(org.datanucleus.store.rdbms.query.StatementParameterMapping) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex)

Aggregations

SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)111 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)98 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)81 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)49 NucleusException (org.datanucleus.exceptions.NucleusException)42 NumericExpression (org.datanucleus.store.rdbms.sql.expression.NumericExpression)40 ArrayList (java.util.ArrayList)39 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)38 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)35 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)31 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)30 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)28 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)23 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)22 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)20 IntegerLiteral (org.datanucleus.store.rdbms.sql.expression.IntegerLiteral)20 NullLiteral (org.datanucleus.store.rdbms.sql.expression.NullLiteral)19 SQLLiteral (org.datanucleus.store.rdbms.sql.expression.SQLLiteral)17 BigInteger (java.math.BigInteger)16 StringLiteral (org.datanucleus.store.rdbms.sql.expression.StringLiteral)16