Search in sources :

Example 21 with SQLTable

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

the class IndexFunction 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 ignore, List args) {
    if (ignore == null) {
        if (args == null || args.size() != 2) {
            throw new NucleusException("INDEX can only be used with 2 arguments - the element expression, and the collection expression");
        }
        SQLExpression elemSqlExpr = (SQLExpression) args.get(0);
        SQLExpression collSqlExpr = (SQLExpression) args.get(1);
        AbstractMemberMetaData mmd = collSqlExpr.getJavaTypeMapping().getMemberMetaData();
        if (!mmd.hasCollection()) {
            throw new NucleusException("INDEX expression for field " + mmd.getFullFieldName() + " does not represent a collection!");
        } else if (!mmd.getOrderMetaData().isIndexedList()) {
            throw new NucleusException("INDEX expression for field " + mmd.getFullFieldName() + " does not represent an indexed list!");
        }
        JavaTypeMapping orderMapping = null;
        SQLTable orderTable = null;
        Table joinTbl = stmt.getRDBMSManager().getTable(mmd);
        if (joinTbl != null) {
            // 1-N via join table
            CollectionTable collTable = (CollectionTable) joinTbl;
            orderTable = stmt.getTableForDatastoreContainer(collTable);
            // TODO If the join table is not yet referenced, or referenced multiple times then fix this
            orderMapping = collTable.getOrderMapping();
        } else {
            // 1-N via FK
            orderTable = elemSqlExpr.getSQLTable();
            orderMapping = ((ClassTable) elemSqlExpr.getSQLTable().getTable()).getExternalMapping(mmd, MappingType.EXTERNAL_INDEX);
        }
        return new NumericExpression(stmt, orderTable, orderMapping);
    }
    throw new NucleusException(Localiser.msg("060002", "INDEX", ignore));
}
Also used : CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) Table(org.datanucleus.store.rdbms.table.Table) ClassTable(org.datanucleus.store.rdbms.table.ClassTable) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 22 with SQLTable

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

the class CollectionContainsMethod method containsAsSubquery.

/**
 * Method to return an expression for Collection.contains using a subquery "EXISTS".
 * This is for use when there are "!contains" or "OR" operations in the filter.
 * Creates the following SQL,
 * <ul>
 * <li><b>Collection of NonPC using join table</b>
 * <pre>
 * SELECT 1 FROM JOIN_TBL A0_SUB
 * WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_ELEM_ID = {elemExpr}
 * </pre>
 * </li>
 * <li><b>Collection of PC using join table</b>
 * <pre>
 * SELECT 1 FROM ELEM_TABLE A0_SUB INNER JOIN JOIN_TBL B0 ON ...
 * WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {elemExpr}
 * </pre>
 * </li>
 * <li><b>Collection of PC using FK</b>
 * <pre>
 * SELECT 1 FROM ELEM_TABLE A0_SUB
 * WHERE A0_SUB.OWN_ID = A0.ID AND A0_SUB.ID = {elemExpr}
 * </pre>
 * </li>
 * </ul>
 * and returns a BooleanSubqueryExpression ("EXISTS (subquery)")
 * @param stmt SQLStatement
 * @param collExpr Collection expression
 * @param elemExpr Expression for the element
 * @return Contains expression
 */
protected SQLExpression containsAsSubquery(SQLStatement stmt, CollectionExpression collExpr, SQLExpression elemExpr) {
    boolean elemIsUnbound = (elemExpr instanceof UnboundExpression);
    String varName = null;
    if (elemIsUnbound) {
        varName = ((UnboundExpression) elemExpr).getVariableName();
        NucleusLogger.QUERY.debug("collection.contains(" + elemExpr + ") binding unbound variable " + varName + " using SUBQUERY");
    }
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    AbstractMemberMetaData mmd = collExpr.getJavaTypeMapping().getMemberMetaData();
    AbstractClassMetaData elemCmd = mmd.getCollection().getElementClassMetaData(clr);
    CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(mmd);
    String elemType = mmd.getCollection().getElementType();
    if (elemIsUnbound) {
        Class varType = stmt.getQueryGenerator().getTypeOfVariable(varName);
        if (varType != null) {
            elemType = varType.getName();
            elemCmd = storeMgr.getMetaDataManager().getMetaDataForClass(elemType, clr);
        }
    }
    SelectStatement subStmt = null;
    if (joinTbl != null) {
        // JoinTable Collection
        if (elemCmd == null) {
            // Collection<Non-PC>
            subStmt = new SelectStatement(stmt, storeMgr, joinTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Restrict to collection owner
            JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getElementMapping());
            if (elemIsUnbound) {
                // Bind the variable in the QueryGenerator
                stmt.getQueryGenerator().bindVariable(varName, null, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
            } else {
                // Add restrict to element
                addRestrictionOnElement(subStmt, elemIdExpr, elemExpr);
            }
        } else {
            // Collection<PC>
            DatastoreClass elemTbl = storeMgr.getDatastoreClass(elemType, clr);
            subStmt = new SelectStatement(stmt, storeMgr, elemTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Join to join table
            SQLTable joinSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), elemTbl.getIdMapping(), joinTbl, null, joinTbl.getElementMapping(), null, null, true, null);
            // Restrict to collection owner
            JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), elemTbl.getIdMapping());
            if (elemIsUnbound) {
                // Bind the variable in the QueryGenerator
                stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
            } else {
                // Add restrict to element
                addRestrictionOnElement(subStmt, elemIdExpr, elemExpr);
            }
        }
    } else {
        // FK Collection
        DatastoreClass elemTbl = storeMgr.getDatastoreClass(mmd.getCollection().getElementType(), clr);
        subStmt = new SelectStatement(stmt, storeMgr, elemTbl, null, null);
        subStmt.setClassLoaderResolver(clr);
        JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
        subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
        // Restrict to collection owner
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = elemTbl.getMemberMapping(mmd.getRelatedMemberMetaData(clr)[0]);
        } else {
            ownerMapping = elemTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
        SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping());
        subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
        if (elemIsUnbound) {
            SQLExpression elemIdExpr = null;
            if (!elemType.equals(mmd.getCollection().getElementType())) {
                // Variable is defined as a subclass of the declared type so add extra join to variable type
                DatastoreClass varTbl = storeMgr.getDatastoreClass(elemType, clr);
                SQLTable varSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), elemTbl.getIdMapping(), null, varTbl, null, varTbl.getIdMapping(), null, null, null, true, null);
                elemIdExpr = exprFactory.newExpression(subStmt, varSqlTbl, varTbl.getIdMapping());
            } else {
                elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), elemTbl.getIdMapping());
            }
            // Bind the variable in the QueryGenerator
            stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
        } else {
            // Add restrict to element
            SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), elemTbl.getIdMapping());
            addRestrictionOnElement(subStmt, elemIdExpr, elemExpr);
        }
    }
    return new BooleanSubqueryExpression(stmt, "EXISTS", subStmt);
}
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) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) JoinTable(org.datanucleus.store.rdbms.table.JoinTable)

Example 23 with SQLTable

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

the class RDBMSStoreHelper method getClassNameForIdUsingDiscriminator.

/**
 * Utility that does a discriminator candidate query for the specified candidate 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 cmd Metadata for the root candidate class
 * @return Name of the class with this identity (or null if none found)
 */
public static String getClassNameForIdUsingDiscriminator(RDBMSStoreManager storeMgr, ExecutionContext ec, Object id, AbstractClassMetaData cmd) {
    // Check for input error
    if (cmd == null || id == null) {
        return null;
    }
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    ClassLoaderResolver clr = ec.getClassLoaderResolver();
    DatastoreClass primaryTable = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr);
    // Form the query to find which one of these classes has the instance with this id
    DiscriminatorStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, clr.classForName(cmd.getFullClassName()), true, null, null);
    stmtGen.setOption(SelectStatementGenerator.OPTION_RESTRICT_DISCRIM);
    SelectStatement sqlStmt = stmtGen.getStatement(ec);
    // Select the discriminator
    JavaTypeMapping discrimMapping = primaryTable.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
    SQLTable discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), discrimMapping);
    sqlStmt.select(discrimSqlTbl, discrimMapping, null);
    // Restrict to this id
    JavaTypeMapping idMapping = primaryTable.getIdMapping();
    JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
    SQLExpression sqlFldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
    SQLExpression sqlFldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
    sqlStmt.whereAnd(sqlFldExpr.eq(sqlFldVal), true);
    // Perform the query
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        if (ec.getSerializeReadForClass(cmd.getFullClassName())) {
            sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
        }
        try {
            PreparedStatement ps = SQLStatementHelper.getPreparedStatementForSQLStatement(sqlStmt, ec, mconn, null, null);
            String statement = sqlStmt.getSQLText().toSQL();
            try {
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps);
                try {
                    while (rs.next()) {
                        DiscriminatorMetaData dismd = discrimMapping.getTable().getDiscriminatorMetaData();
                        return RDBMSQueryUtils.getClassNameFromDiscriminatorResultSetRow(discrimMapping, dismd, rs, ec);
                    }
                } finally {
                    rs.close();
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException sqe) {
        NucleusLogger.DATASTORE.error("Exception thrown on querying of discriminator for id", sqe);
        throw new NucleusDataStoreException(sqe.toString(), sqe);
    }
    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) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) DiscriminatorStatementGenerator(org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass)

Example 24 with SQLTable

use of org.datanucleus.store.rdbms.sql.SQLTable 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 25 with SQLTable

use of org.datanucleus.store.rdbms.sql.SQLTable 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)

Aggregations

SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)39 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)34 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)31 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)30 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)26 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)20 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)20 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)20 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)19 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)17 NucleusException (org.datanucleus.exceptions.NucleusException)16 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)12 MapTable (org.datanucleus.store.rdbms.table.MapTable)12 UnboundExpression (org.datanucleus.store.rdbms.sql.expression.UnboundExpression)11 DiscriminatorStatementGenerator (org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator)10 UnionStatementGenerator (org.datanucleus.store.rdbms.sql.UnionStatementGenerator)10 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)9 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)8 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)8 CollectionTable (org.datanucleus.store.rdbms.table.CollectionTable)7