Search in sources :

Example 11 with SelectStatement

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

the class FKListStore method listIterator.

/**
 * Accessor for an iterator through the list elements.
 * @param ownerOP ObjectProvider for the owner.
 * @param startIdx The start index in the list (only for indexed lists)
 * @param endIdx The end index in the list (only for indexed lists)
 * @return The List Iterator
 */
protected ListIterator<E> listIterator(ObjectProvider ownerOP, int startIdx, int endIdx) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    Transaction tx = ec.getTransaction();
    if (elementInfo == null || elementInfo.length == 0) {
        return null;
    }
    // Generate the statement. Note that this is not cached since depends on the current FetchPlan and other things
    IteratorStatement iterStmt = getIteratorStatement(ownerOP.getExecutionContext(), ec.getFetchPlan(), true, startIdx, endIdx);
    SelectStatement sqlStmt = iterStmt.getSelectStatement();
    StatementClassMapping resultMapping = iterStmt.getStatementClassMapping();
    // 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);
    }
    if (tx.getSerializeRead() != null && tx.getSerializeRead()) {
        sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
    }
    String stmt = sqlStmt.getSQLText().toSQL();
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            // Create the statement
            PreparedStatement ps = sqlControl.getStatementForQuery(mconn, stmt);
            // Set the owner
            ObjectProvider stmtOwnerOP = BackingStoreHelper.getOwnerObjectProviderForBackingStore(ownerOP);
            int numParams = ownerIdx.getNumberOfParameterOccurrences();
            for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
                ownerIdx.getMapping().setObject(ec, ps, ownerIdx.getParameterPositionsForOccurrence(paramInstance), stmtOwnerOP.getObject());
            }
            try {
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, stmt, ps);
                try {
                    ResultObjectFactory rof = null;
                    if (elementsAreEmbedded || elementsAreSerialised) {
                        throw new NucleusException("Cannot have FK set with non-persistent objects");
                    }
                    rof = new PersistentClassROF(ec, rs, false, resultMapping, elementCmd, clr.classForName(elementType));
                    return new ListStoreIterator(ownerOP, rs, rof, this);
                } finally {
                    rs.close();
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException | MappedDatastoreException e) {
        throw new NucleusDataStoreException(Localiser.msg("056006", stmt), e);
    }
}
Also used : MappedDatastoreException(org.datanucleus.store.rdbms.exceptions.MappedDatastoreException) SQLException(java.sql.SQLException) ResultObjectFactory(org.datanucleus.store.rdbms.query.ResultObjectFactory) PreparedStatement(java.sql.PreparedStatement) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) SQLController(org.datanucleus.store.rdbms.SQLController) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) Transaction(org.datanucleus.Transaction) PersistentClassROF(org.datanucleus.store.rdbms.query.PersistentClassROF) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) ObjectProvider(org.datanucleus.state.ObjectProvider) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 12 with SelectStatement

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

the class FKMapStore method getSQLStatementForGet.

/**
 * Method to return an SQLStatement for retrieving the value for a key.
 * Selects the join table and optionally joins to the value table if it has its own table.
 * @param ownerOP ObjectProvider for the owning object
 * @return The SQLStatement
 */
protected SelectStatement getSQLStatementForGet(ObjectProvider ownerOP) {
    SelectStatement sqlStmt = null;
    ExecutionContext ec = ownerOP.getExecutionContext();
    final ClassLoaderResolver clr = ownerOP.getExecutionContext().getClassLoaderResolver();
    final Class valueCls = clr.classForName(this.valueType);
    if (ownerMemberMetaData.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
        getMappingDef = new StatementClassMapping();
        if (valueTable.getDiscriminatorMetaData() != null && valueTable.getDiscriminatorMetaData().getStrategy() != DiscriminatorStrategy.NONE) {
            // Value class has discriminator
            if (ClassUtils.isReferenceType(valueCls)) {
                String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(valueType, 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, valueCls, true, null, null).getStatement(ec);
            }
            iterateUsingDiscriminator = true;
        } else {
            // Use union to resolve any subclasses of value
            UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, valueCls, true, null, null);
            stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
            getMappingDef.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
            sqlStmt = stmtGen.getStatement(ec);
        }
        // Select the value field(s)
        SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, getMappingDef, ec.getFetchPlan(), sqlStmt.getPrimaryTable(), valueCmd, ec.getFetchPlan().getMaxFetchDepth());
    } else {
        // Value is in key table
        sqlStmt = new SelectStatement(storeMgr, mapTable, null, null);
        sqlStmt.setClassLoaderResolver(clr);
        if (valueCmd != null) {
            // Left outer join to value table (so we allow for null values)
            SQLTable valueSqlTbl = sqlStmt.join(JoinType.LEFT_OUTER_JOIN, sqlStmt.getPrimaryTable(), valueMapping, valueTable, null, valueTable.getIdMapping(), null, null, true);
            // Select the value field(s)
            SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, getMappingDef, ec.getFetchPlan(), valueSqlTbl, valueCmd, ec.getFetchPlan().getMaxFetchDepth());
        } else {
            sqlStmt.select(sqlStmt.getPrimaryTable(), 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 on key
    if (keyMapping instanceof SerialisedMapping) {
        // if the keyMapping contains a BLOB column (or any other column not supported by the database
        // as primary key), uses like instead of the operator OP_EQ (=)
        // in future do not check if the keyMapping is of ObjectMapping, but use the database
        // adapter to check the data types not supported as primary key
        // if object mapping (BLOB) use like
        SQLExpression keyExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), keyMapping);
        SQLExpression keyVal = exprFactory.newLiteralParameter(sqlStmt, keyMapping, null, "KEY");
        sqlStmt.whereAnd(new org.datanucleus.store.rdbms.sql.expression.BooleanExpression(keyExpr, Expression.OP_LIKE, keyVal), true);
    } else {
        SQLExpression keyExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), keyMapping);
        SQLExpression keyVal = exprFactory.newLiteralParameter(sqlStmt, keyMapping, null, "KEY");
        sqlStmt.whereAnd(keyExpr.eq(keyVal), true);
    }
    // Input parameter(s) - owner, key
    int inputParamNum = 1;
    StatementMappingIndex ownerIdx = new StatementMappingIndex(ownerMapping);
    StatementMappingIndex keyIdx = new StatementMappingIndex(keyMapping);
    if (sqlStmt.getNumberOfUnions() > 0) {
        // Add parameter occurrence for each union of statement
        for (int j = 0; j < sqlStmt.getNumberOfUnions() + 1; j++) {
            int[] ownerPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
            for (int k = 0; k < ownerPositions.length; k++) {
                ownerPositions[k] = inputParamNum++;
            }
            ownerIdx.addParameterOccurrence(ownerPositions);
            int[] keyPositions = new int[keyMapping.getNumberOfDatastoreMappings()];
            for (int k = 0; k < keyPositions.length; k++) {
                keyPositions[k] = inputParamNum++;
            }
            keyIdx.addParameterOccurrence(keyPositions);
        }
    } else {
        int[] ownerPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
        for (int k = 0; k < ownerPositions.length; k++) {
            ownerPositions[k] = inputParamNum++;
        }
        ownerIdx.addParameterOccurrence(ownerPositions);
        int[] keyPositions = new int[keyMapping.getNumberOfDatastoreMappings()];
        for (int k = 0; k < keyPositions.length; k++) {
            keyPositions[k] = inputParamNum++;
        }
        keyIdx.addParameterOccurrence(keyPositions);
    }
    getMappingParams = new StatementParameterMapping();
    getMappingParams.addMappingForParameter("owner", ownerIdx);
    getMappingParams.addMappingForParameter("key", keyIdx);
    return sqlStmt;
}
Also used : StatementParameterMapping(org.datanucleus.store.rdbms.query.StatementParameterMapping) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) UnionStatementGenerator(org.datanucleus.store.rdbms.sql.UnionStatementGenerator) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) ExecutionContext(org.datanucleus.ExecutionContext) DiscriminatorStatementGenerator(org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) SerialisedMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedMapping)

Example 13 with SelectStatement

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

the class JoinListStore method listIterator.

/**
 * Accessor for an iterator through the list elements.
 * @param ownerOP ObjectProvider for the owner
 * @param startIdx The start point in the list (only for indexed lists).
 * @param endIdx End index in the list (only for indexed lists).
 * @return The List Iterator
 */
protected ListIterator<E> listIterator(ObjectProvider ownerOP, int startIdx, int endIdx) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    Transaction tx = ec.getTransaction();
    // Generate the statement. Note that this is not cached since depends on the current FetchPlan and other things
    IteratorStatement iterStmt = getIteratorStatement(ownerOP.getExecutionContext(), ec.getFetchPlan(), true, startIdx, endIdx);
    SelectStatement sqlStmt = iterStmt.getSelectStatement();
    StatementClassMapping resultMapping = iterStmt.getStatementClassMapping();
    // 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 < paramPositions.length; k++) {
                paramPositions[k] = inputParamNum++;
            }
            ownerIdx.addParameterOccurrence(paramPositions);
        }
    } else {
        int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
        for (int k = 0; k < paramPositions.length; k++) {
            paramPositions[k] = inputParamNum++;
        }
        ownerIdx.addParameterOccurrence(paramPositions);
    }
    if (tx.getSerializeRead() != null && tx.getSerializeRead()) {
        sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
    }
    String stmt = sqlStmt.getSQLText().toSQL();
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            // Create the statement
            PreparedStatement ps = sqlControl.getStatementForQuery(mconn, stmt);
            // Set the owner
            ObjectProvider stmtOwnerOP = BackingStoreHelper.getOwnerObjectProviderForBackingStore(ownerOP);
            int numParams = ownerIdx.getNumberOfParameterOccurrences();
            for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
                ownerIdx.getMapping().setObject(ec, ps, ownerIdx.getParameterPositionsForOccurrence(paramInstance), stmtOwnerOP.getObject());
            }
            try {
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, stmt, ps);
                try {
                    if (elementsAreEmbedded || elementsAreSerialised) {
                        // No ResultObjectFactory needed - handled by SetStoreIterator
                        return new ListStoreIterator(ownerOP, rs, null, this);
                    } else if (elementMapping instanceof ReferenceMapping) {
                        // No ResultObjectFactory needed - handled by SetStoreIterator
                        return new ListStoreIterator(ownerOP, rs, null, this);
                    } else {
                        ResultObjectFactory rof = new PersistentClassROF(ec, rs, false, resultMapping, elementCmd, clr.classForName(elementType));
                        return new ListStoreIterator(ownerOP, rs, rof, this);
                    }
                } finally {
                    rs.close();
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException | MappedDatastoreException e) {
        throw new NucleusDataStoreException(Localiser.msg("056006", stmt), e);
    }
}
Also used : MappedDatastoreException(org.datanucleus.store.rdbms.exceptions.MappedDatastoreException) SQLException(java.sql.SQLException) ResultObjectFactory(org.datanucleus.store.rdbms.query.ResultObjectFactory) PreparedStatement(java.sql.PreparedStatement) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) SQLController(org.datanucleus.store.rdbms.SQLController) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) Transaction(org.datanucleus.Transaction) PersistentClassROF(org.datanucleus.store.rdbms.query.PersistentClassROF) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) ObjectProvider(org.datanucleus.state.ObjectProvider)

Example 14 with SelectStatement

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

the class JoinListStore 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).
 * @param startIdx Start index for the iterator (or -1)
 * @param endIdx End index for the iterator (or -1)
 * @return The SQLStatement and its associated StatementClassMapping
 */
public IteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner, int startIdx, int endIdx) {
    SelectStatement sqlStmt = null;
    StatementClassMapping stmtClassMapping = new StatementClassMapping();
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    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 ListStoreIterator
        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 ListStoreIterator
        sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
    } else {
        // Join to the element table(s)
        if (elementInfo != null) {
            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);
                    stmtClassMapping.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) list. Statement is null");
            }
            // Select the required fields
            SQLTable elementSqlTbl = sqlStmt.getTable(elementInfo[0].getDatastoreClass(), sqlStmt.getPrimaryTable().getGroupName());
            SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, stmtClassMapping, fp, elementSqlTbl, elementCmd, fp.getMaxFetchDepth());
        } else {
            throw new NucleusException("Unable to create SQL statement to retrieve elements of List");
        }
    }
    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 (indexedList) {
        // "Indexed List" so allow restriction on returned indexes
        boolean needsOrdering = true;
        if (startIdx == -1 && endIdx == -1) {
            // Just restrict to >= 0 so we don't get any disassociated elements
            SQLExpression indexExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
            SQLExpression indexVal = exprFactory.newLiteral(sqlStmt, orderMapping, 0);
            sqlStmt.whereAnd(indexExpr.ge(indexVal), true);
        } else if (startIdx >= 0 && endIdx == startIdx) {
            // Particular index required so add restriction
            needsOrdering = false;
            SQLExpression indexExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
            SQLExpression indexVal = exprFactory.newLiteral(sqlStmt, orderMapping, startIdx);
            sqlStmt.whereAnd(indexExpr.eq(indexVal), true);
        } else {
            // Add restrictions on start/end indices as required
            if (startIdx >= 0) {
                SQLExpression indexExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
                SQLExpression indexVal = exprFactory.newLiteral(sqlStmt, orderMapping, startIdx);
                sqlStmt.whereAnd(indexExpr.ge(indexVal), true);
            } else {
                // Just restrict to >= 0 so we don't get any disassociated elements
                SQLExpression indexExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
                SQLExpression indexVal = exprFactory.newLiteral(sqlStmt, orderMapping, 0);
                sqlStmt.whereAnd(indexExpr.ge(indexVal), true);
            }
            if (endIdx >= 0) {
                SQLExpression indexExpr2 = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
                SQLExpression indexVal2 = exprFactory.newLiteral(sqlStmt, orderMapping, endIdx);
                sqlStmt.whereAnd(indexExpr2.lt(indexVal2), true);
            }
        }
        if (needsOrdering) {
            // 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);
        }
    } else {
        if (elementInfo != null) {
            // Apply ordering defined by <order-by>
            DatastoreClass elementTbl = elementInfo[0].getDatastoreClass();
            FieldOrder[] orderComponents = ownerMemberMetaData.getOrderMetaData().getFieldOrders();
            SQLExpression[] orderExprs = new SQLExpression[orderComponents.length];
            boolean[] orderDirs = new boolean[orderComponents.length];
            for (int i = 0; i < orderComponents.length; i++) {
                String fieldName = orderComponents[i].getFieldName();
                JavaTypeMapping fieldMapping = elementTbl.getMemberMapping(elementInfo[0].getAbstractClassMetaData().getMetaDataForMember(fieldName));
                orderDirs[i] = !orderComponents[i].isForward();
                SQLTable fieldSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), fieldMapping);
                orderExprs[i] = exprFactory.newExpression(sqlStmt, fieldSqlTbl, fieldMapping);
            }
            sqlStmt.setOrdering(orderExprs, orderDirs);
        }
    }
    return new IteratorStatement(this, sqlStmt, stmtClassMapping);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) FieldOrder(org.datanucleus.metadata.OrderMetaData.FieldOrder) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) 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) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 15 with SelectStatement

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

the class MapContainsKeyMethod method containsAsSubquery.

/**
 * Method to return an expression for Map.containsKey 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>Map using join table</b>
 * <pre>
 * SELECT 1 FROM JOIN_TBL A0_SUB
 * WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_KEY_ID = {keyExpr}
 * </pre>
 * </li>
 * <li><b>Map with key stored in value</b>
 * <pre>
 * SELECT 1 FROM KEY_TABLE A0_SUB INNER JOIN VALUE_TBL B0 ON ...
 * WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {keyExpr}
 * </pre>
 * </li>
 * <li><b>Map of value stored in key</b>
 * <pre>
 * SELECT 1 FROM KEY_TABLE A0_SUB
 * WHERE A0_SUB.OWN_ID = A0.ID AND A0_SUB.ID = {keyExpr}
 * </pre>
 * </li>
 * </ul>
 * and returns a BooleanSubqueryExpression ("EXISTS (subquery)")
 * @param stmt SQLStatement
 * @param mapExpr Map expression
 * @param keyExpr Expression for the key
 * @return Contains expression
 */
protected SQLExpression containsAsSubquery(SQLStatement stmt, MapExpression mapExpr, SQLExpression keyExpr) {
    boolean keyIsUnbound = (keyExpr instanceof UnboundExpression);
    String varName = null;
    if (keyIsUnbound) {
        varName = ((UnboundExpression) keyExpr).getVariableName();
        NucleusLogger.QUERY.debug("map.containsKey binding unbound variable " + varName + " using SUBQUERY");
    // TODO What if the variable is declared as a subtype, handle this see CollectionContainsMethod
    }
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
    AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr);
    MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
    SelectStatement subStmt = null;
    if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
        // JoinTable Map
        if (keyCmd == null) {
            // Map<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 map owner
            JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (keyIsUnbound) {
                // Bind the variable in the QueryGenerator
                keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getKeyMapping());
                stmt.getQueryGenerator().bindVariable(varName, null, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
            } else {
                // Add restrict to key
                SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getKeyMapping());
                subStmt.whereAnd(elemIdExpr.eq(keyExpr), true);
            }
        } else {
            // Map<PC, ?>
            DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
            subStmt = new SelectStatement(stmt, storeMgr, keyTbl, 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(), keyTbl.getIdMapping(), joinTbl, null, joinTbl.getKeyMapping(), null, null, true);
            // Restrict to map owner
            JavaTypeMapping ownerMapping = joinTbl.getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (keyIsUnbound) {
                // Bind the variable in the QueryGenerator
                keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
                stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
            } else {
                // Add restrict to key
                SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
                subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
            }
        }
    } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
        // Key stored in value table
        AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr);
        DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = valTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        AbstractMemberMetaData valKeyMmd = valCmd.getMetaDataForMember(mmd.getKeyMetaData().getMappedBy());
        if (keyCmd == null) {
            subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Restrict to map owner (on value table)
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (keyIsUnbound) {
                // Bind the variable in the QueryGenerator
                keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getMemberMapping(valKeyMmd));
                stmt.getQueryGenerator().bindVariable(varName, null, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
            } else {
                // Add restrict to key
                JavaTypeMapping keyMapping = valTbl.getMemberMapping(valKeyMmd);
                SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyMapping);
                subStmt.whereAnd(elemIdExpr.eq(keyExpr), true);
            }
        } else {
            DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
            subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Join to value table
            SQLTable valSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), keyTbl.getIdMapping(), valTbl, null, valTbl.getMemberMapping(valKeyMmd), null, null, true);
            // Restrict to map owner (on value table)
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, valSqlTbl, ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (keyIsUnbound) {
                // Bind the variable in the QueryGenerator
                keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
                stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
            } else {
                // Add restrict to key
                SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
                subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
            }
        }
    } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
        DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = keyTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
        subStmt.setClassLoaderResolver(clr);
        JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
        subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
        // Restrict to map owner (on key table)
        SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
        SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
        subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
        if (keyIsUnbound) {
            // Bind the variable in the QueryGenerator
            keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
            stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
        } else {
            // Add restrict to key
            JavaTypeMapping keyMapping = keyTbl.getIdMapping();
            SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyMapping);
            subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
        }
    }
    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) MapTable(org.datanucleus.store.rdbms.table.MapTable) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) JoinTable(org.datanucleus.store.rdbms.table.JoinTable)

Aggregations

SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)49 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)36 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)31 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)30 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)27 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)25 NucleusException (org.datanucleus.exceptions.NucleusException)25 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)24 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)19 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)19 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)19 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)16 ExecutionContext (org.datanucleus.ExecutionContext)14 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)14 UnionStatementGenerator (org.datanucleus.store.rdbms.sql.UnionStatementGenerator)12 DiscriminatorStatementGenerator (org.datanucleus.store.rdbms.sql.DiscriminatorStatementGenerator)11 PreparedStatement (java.sql.PreparedStatement)10 ResultSet (java.sql.ResultSet)10 SQLException (java.sql.SQLException)10 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)10