Search in sources :

Example 26 with StatementClassMapping

use of org.datanucleus.store.rdbms.query.StatementClassMapping in project datanucleus-rdbms by datanucleus.

the class SQLStatementHelper method selectFetchPlanFieldsOfFKRelatedObject.

/**
 * Convenience method to join to and select all required FP fields of a related object where linked via an FK at this side.
 * @return Whether the caller should select the FK themselves (i.e we haven't selected anything)
 */
private static boolean selectFetchPlanFieldsOfFKRelatedObject(SelectStatement stmt, StatementClassMapping mappingDefinition, FetchPlan fetchPlan, SQLTable sourceSqlTbl, AbstractMemberMetaData mmd, ClassLoaderResolver clr, int maxFetchPlanLimit, JavaTypeMapping m, String tableGroupName, StatementMappingIndex stmtMapping, SQLTable sqlTbl, JoinType inputJoinType) {
    boolean selectFK = true;
    if (mmd.fetchFKOnly()) {
    // Only want FK fetching, and not the fields of the object (so avoid the join)
    } else {
        RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
        Class type = mmd.isSingleCollection() ? clr.classForName(mmd.getCollection().getElementType()) : mmd.getType();
        if (m instanceof ReferenceMapping) {
            ReferenceMapping refMapping = (ReferenceMapping) m;
            if (refMapping.getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING && refMapping.getJavaTypeMapping().length == 1) {
                JavaTypeMapping[] subMappings = refMapping.getJavaTypeMapping();
                if (subMappings != null && subMappings.length == 1) {
                    // Special case of reference mapping with single FK implementation
                    type = clr.classForName(refMapping.getJavaTypeMapping()[0].getType());
                }
            }
        }
        // select fetch plan fields of this object
        AbstractClassMetaData relatedCmd = storeMgr.getMetaDataManager().getMetaDataForClass(type, clr);
        if (relatedCmd != null) {
            if (relatedCmd.isEmbeddedOnly()) {
                return true;
            }
            if (relatedCmd.getBaseAbstractClassMetaData().getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
                // Related object uses complete-table
                Collection<String> relSubclassNames = storeMgr.getSubClassesForClass(relatedCmd.getFullClassName(), true, clr);
                if (relatedCmd.isMappedSuperclass() && relSubclassNames.size() > 1) {
                    // Multiple possible related types and we don't have the FK so omit
                    return true;
                } else if (!relatedCmd.isMappedSuperclass() && relSubclassNames.size() > 0) {
                    // Multiple possible related types and we don't have the FK so omit
                    return true;
                }
            // TODO Maybe do a LEFT OUTER JOIN to each possible?
            }
            // Find the table of the related class
            DatastoreClass relatedTbl = storeMgr.getDatastoreClass(relatedCmd.getFullClassName(), clr);
            if (relatedTbl == null) {
                // Class doesn't have its own table (subclass-table) so find where it persists
                AbstractClassMetaData[] ownerParentCmds = storeMgr.getClassesManagingTableForClass(relatedCmd, clr);
                if (ownerParentCmds.length > 1) {
                    NucleusLogger.QUERY.info("Relation (" + mmd.getFullFieldName() + ") with multiple related tables (using subclass-table). Not supported so selecting FK of related object only");
                    return true;
                }
                relatedTbl = storeMgr.getDatastoreClass(ownerParentCmds[0].getFullClassName(), clr);
            }
            String requiredGroupName = null;
            if (sourceSqlTbl.getGroupName() != null) {
                // JPQL will have table groups defined already, named as per "alias.fieldName"
                requiredGroupName = sourceSqlTbl.getGroupName() + "." + mmd.getName();
            }
            SQLTable relatedSqlTbl = stmt.getTable(relatedTbl, requiredGroupName);
            if (relatedSqlTbl == null) {
                // Join the 1-1 relation
                JoinType joinType = getJoinTypeForOneToOneRelationJoin(m, sqlTbl, inputJoinType);
                if (joinType == JoinType.LEFT_OUTER_JOIN || joinType == JoinType.RIGHT_OUTER_JOIN) {
                    inputJoinType = joinType;
                }
                relatedSqlTbl = addJoinForOneToOneRelation(stmt, m, sqlTbl, relatedTbl.getIdMapping(), relatedTbl, null, null, tableGroupName, joinType);
            }
            StatementClassMapping subMappingDefinition = new StatementClassMapping(mmd.getClassName(), mmd.getName());
            selectFetchPlanOfSourceClassInStatement(stmt, subMappingDefinition, fetchPlan, relatedSqlTbl, relatedCmd, maxFetchPlanLimit - 1, inputJoinType);
            if (mappingDefinition != null) {
                if (relatedCmd.getIdentityType() == IdentityType.APPLICATION) {
                    int[] pkFields = relatedCmd.getPKMemberPositions();
                    int[] pkCols = new int[m.getNumberOfDatastoreMappings()];
                    int pkColNo = 0;
                    for (int pkField : pkFields) {
                        StatementMappingIndex pkIdx = subMappingDefinition.getMappingForMemberPosition(pkField);
                        int[] pkColNumbers = pkIdx.getColumnPositions();
                        for (int pkColNumber : pkColNumbers) {
                            pkCols[pkColNo] = pkColNumber;
                            pkColNo++;
                        }
                    }
                    selectFK = false;
                    stmtMapping.setColumnPositions(pkCols);
                } else if (relatedCmd.getIdentityType() == IdentityType.DATASTORE) {
                    StatementMappingIndex pkIdx = subMappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
                    selectFK = false;
                    stmtMapping.setColumnPositions(pkIdx.getColumnPositions());
                }
                mappingDefinition.addMappingDefinitionForMember(mmd.getAbsoluteFieldNumber(), subMappingDefinition);
            }
        } else {
        // TODO 1-1 interface relation
        }
    }
    return selectFK;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) JoinType(org.datanucleus.store.rdbms.sql.SQLJoin.JoinType) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass)

Example 27 with StatementClassMapping

use of org.datanucleus.store.rdbms.query.StatementClassMapping in project datanucleus-rdbms by datanucleus.

the class LocateBulkRequest method getStatement.

protected String getStatement(DatastoreClass table, ObjectProvider[] ops, boolean lock) {
    RDBMSStoreManager storeMgr = table.getStoreManager();
    ClassLoaderResolver clr = storeMgr.getNucleusContext().getClassLoaderResolver(null);
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    cmd = storeMgr.getMetaDataManager().getMetaDataForClass(table.getType(), clr);
    ExecutionContext ec = ops[0].getExecutionContext();
    SelectStatement sqlStatement = new SelectStatement(storeMgr, table, null, null);
    // SELECT fields we require
    resultMapping = new StatementClassMapping();
    // a). PK fields
    if (table.getIdentityType() == IdentityType.DATASTORE) {
        JavaTypeMapping datastoreIdMapping = table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
        SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), datastoreIdMapping);
        int[] cols = sqlStatement.select(expr, null);
        StatementMappingIndex datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
        datastoreIdx.setColumnPositions(cols);
        resultMapping.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
    } else if (table.getIdentityType() == IdentityType.APPLICATION) {
        int[] pkNums = cmd.getPKMemberPositions();
        for (int i = 0; i < pkNums.length; i++) {
            AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[i]);
            JavaTypeMapping pkMapping = table.getMemberMappingInDatastoreClass(mmd);
            if (pkMapping == null) {
                pkMapping = table.getMemberMapping(mmd);
            }
            SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), pkMapping);
            int[] cols = sqlStatement.select(expr, null);
            StatementMappingIndex pkIdx = new StatementMappingIndex(pkMapping);
            pkIdx.setColumnPositions(cols);
            resultMapping.addMappingForMember(mmd.getAbsoluteFieldNumber(), pkIdx);
        }
    } else {
        throw new NucleusUserException("Cannot locate objects using nondurable identity");
    }
    JavaTypeMapping verMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, false);
    if (verMapping != null) {
        VersionMetaData currentVermd = table.getVersionMetaData();
        if (currentVermd != null && currentVermd.getFieldName() == null) {
            // Surrogate version column
            SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), verMapping);
            int[] cols = sqlStatement.select(expr, null);
            StatementMappingIndex mapIdx = new StatementMappingIndex(verMapping);
            mapIdx.setColumnPositions(cols);
            resultMapping.addMappingForMember(SurrogateColumnType.VERSION.getFieldNumber(), mapIdx);
        }
    }
    int[] nonPkFieldNums = cmd.getNonPKMemberPositions();
    if (nonPkFieldNums != null) {
        for (int i = 0; i < nonPkFieldNums.length; i++) {
            AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(nonPkFieldNums[i]);
            JavaTypeMapping mapping = table.getMemberMapping(mmd);
            if (mapping != null && mapping.includeInFetchStatement()) {
                if (mapping instanceof PersistableMapping) {
                    // Ignore 1-1/N-1 for now
                    continue;
                }
                SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), mapping);
                int[] cols = sqlStatement.select(expr, null);
                StatementMappingIndex mapIdx = new StatementMappingIndex(mapping);
                mapIdx.setColumnPositions(cols);
                resultMapping.addMappingForMember(mmd.getAbsoluteFieldNumber(), mapIdx);
            }
        }
    }
    JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
    if (multitenancyMapping != null) {
        // Add WHERE clause restricting to tenant
        SQLExpression tenantExpr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), multitenancyMapping);
        SQLExpression tenantVal = exprFactory.newLiteral(sqlStatement, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, cmd));
        sqlStatement.whereAnd(tenantExpr.eq(tenantVal), true);
    }
    JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
    if (softDeleteMapping != null) {
        // Add WHERE clause restricting to soft-delete unset
        SQLExpression softDeleteExpr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), softDeleteMapping);
        SQLExpression softDeleteVal = exprFactory.newLiteral(sqlStatement, softDeleteMapping, Boolean.FALSE);
        sqlStatement.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
    }
    // Add WHERE clause restricting to the identities of the objects
    mappingDefinitions = new StatementClassMapping[ops.length];
    int inputParamNum = 1;
    for (int i = 0; i < ops.length; i++) {
        mappingDefinitions[i] = new StatementClassMapping();
        if (table.getIdentityType() == IdentityType.DATASTORE) {
            // Datastore identity value for input
            JavaTypeMapping datastoreIdMapping = table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
            SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), datastoreIdMapping);
            SQLExpression val = exprFactory.newLiteralParameter(sqlStatement, datastoreIdMapping, null, "ID");
            sqlStatement.whereOr(expr.eq(val), true);
            StatementMappingIndex datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
            mappingDefinitions[i].addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
            datastoreIdx.addParameterOccurrence(new int[] { inputParamNum++ });
        } else if (table.getIdentityType() == IdentityType.APPLICATION) {
            // Application identity value(s) for input
            BooleanExpression pkExpr = null;
            int[] pkNums = cmd.getPKMemberPositions();
            for (int j = 0; j < pkNums.length; j++) {
                AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[j]);
                JavaTypeMapping pkMapping = table.getMemberMappingInDatastoreClass(mmd);
                if (pkMapping == null) {
                    pkMapping = table.getMemberMapping(mmd);
                }
                SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), pkMapping);
                SQLExpression val = exprFactory.newLiteralParameter(sqlStatement, pkMapping, null, "PK" + j);
                BooleanExpression fieldEqExpr = expr.eq(val);
                if (pkExpr == null) {
                    pkExpr = fieldEqExpr;
                } else {
                    pkExpr = pkExpr.and(fieldEqExpr);
                }
                StatementMappingIndex pkIdx = new StatementMappingIndex(pkMapping);
                mappingDefinitions[i].addMappingForMember(mmd.getAbsoluteFieldNumber(), pkIdx);
                int[] inputParams = new int[pkMapping.getNumberOfDatastoreMappings()];
                for (int k = 0; k < pkMapping.getNumberOfDatastoreMappings(); k++) {
                    inputParams[k] = inputParamNum++;
                }
                pkIdx.addParameterOccurrence(inputParams);
            }
            if (pkExpr == null) {
                throw new NucleusException("Unable to generate PK expression for WHERE clause of locate statement");
            }
            pkExpr = (BooleanExpression) pkExpr.encloseInParentheses();
            sqlStatement.whereOr(pkExpr, true);
        }
    }
    // Generate the appropriate JDBC statement allowing for locking
    if (lock) {
        sqlStatement.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, Boolean.TRUE);
        return sqlStatement.getSQLText().toSQL();
    }
    return sqlStatement.getSQLText().toSQL();
}
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) VersionMetaData(org.datanucleus.metadata.VersionMetaData) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) ExecutionContext(org.datanucleus.ExecutionContext) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 28 with StatementClassMapping

use of org.datanucleus.store.rdbms.query.StatementClassMapping in project datanucleus-rdbms by datanucleus.

the class JoinMapStore 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();
    Class valueCls = clr.classForName(this.valueType);
    if (valuesAreEmbedded || valuesAreSerialised) {
        // Value is stored in join table
        sqlStmt = new SelectStatement(storeMgr, mapTable, null, null);
        sqlStmt.setClassLoaderResolver(clr);
        sqlStmt.select(sqlStmt.getPrimaryTable(), valueMapping, null);
    } else {
        // Value is stored in own table
        getMappingDef = new StatementClassMapping();
        if (!valueCmd.getFullClassName().equals(valueCls.getName())) {
            valueCls = clr.classForName(valueCmd.getFullClassName());
        }
        UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, valueCls, true, null, null, mapTable, null, valueMapping);
        stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
        getMappingDef.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
        sqlStmt = stmtGen.getStatement(ec);
        // Select the value field(s)
        SQLTable valueSqlTbl = sqlStmt.getTable(valueTable, sqlStmt.getPrimaryTable().getGroupName());
        if (valueSqlTbl == null) {
            // Root value candidate has no table, so try to find a value candidate with a table that exists in this statement
            Collection<String> valueSubclassNames = storeMgr.getSubClassesForClass(valueType, true, clr);
            if (valueSubclassNames != null && !valueSubclassNames.isEmpty()) {
                for (String valueSubclassName : valueSubclassNames) {
                    DatastoreClass valueTbl = storeMgr.getDatastoreClass(valueSubclassName, clr);
                    if (valueTbl != null) {
                        valueSqlTbl = sqlStmt.getTable(valueTbl, sqlStmt.getPrimaryTable().getGroupName());
                        if (valueSqlTbl != null) {
                            break;
                        }
                    }
                }
            }
        }
        SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, getMappingDef, ec.getFetchPlan(), valueSqlTbl, valueCmd, ec.getFetchPlan().getMaxFetchDepth());
    }
    // 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) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) SerialisedMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass)

Example 29 with StatementClassMapping

use of org.datanucleus.store.rdbms.query.StatementClassMapping in project datanucleus-rdbms by datanucleus.

the class OracleBlobRDBMSMapping method updateBlobColumn.

/**
 * Convenience method to update the contents of a BLOB column.
 * Oracle requires that a BLOB is initialised with EMPTY_BLOB() and then you retrieve
 * the column and update its BLOB value. Performs a statement
 * <pre>
 * SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE
 * </pre>
 * and then updates the Blob value returned.
 * @param op ObjectProvider of the object
 * @param table Table storing the BLOB column
 * @param mapping Datastore mapping for the BLOB column
 * @param bytes The bytes to store in the BLOB
 * @throws NucleusObjectNotFoundException thrown if an object isnt found
 * @throws NucleusDataStoreException thrown if an error occurs in datastore communication
 */
@SuppressWarnings("deprecation")
public static void updateBlobColumn(ObjectProvider op, Table table, DatastoreMapping mapping, byte[] bytes) {
    ExecutionContext ec = op.getExecutionContext();
    RDBMSStoreManager storeMgr = table.getStoreManager();
    // Don't support join tables yet
    DatastoreClass classTable = (DatastoreClass) table;
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    // Generate "SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE" statement
    SelectStatement sqlStmt = new SelectStatement(storeMgr, table, null, null);
    sqlStmt.setClassLoaderResolver(ec.getClassLoaderResolver());
    sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
    SQLTable blobSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), mapping.getJavaTypeMapping());
    sqlStmt.select(blobSqlTbl, mapping.getColumn(), null);
    StatementClassMapping mappingDefinition = new StatementClassMapping();
    AbstractClassMetaData cmd = op.getClassMetaData();
    int inputParamNum = 1;
    if (cmd.getIdentityType() == IdentityType.DATASTORE) {
        // Datastore identity value for input
        JavaTypeMapping datastoreIdMapping = classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
        SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), datastoreIdMapping);
        SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, datastoreIdMapping, null, "ID");
        sqlStmt.whereAnd(expr.eq(val), true);
        StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
        if (datastoreIdx == null) {
            datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
            mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
        }
        datastoreIdx.addParameterOccurrence(new int[] { inputParamNum });
    } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        // Application identity value(s) for input
        int[] pkNums = cmd.getPKMemberPositions();
        for (int i = 0; i < pkNums.length; i++) {
            AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[i]);
            JavaTypeMapping pkMapping = classTable.getMemberMapping(mmd);
            SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), pkMapping);
            SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, pkMapping, null, "PK" + i);
            sqlStmt.whereAnd(expr.eq(val), true);
            StatementMappingIndex pkIdx = mappingDefinition.getMappingForMemberPosition(pkNums[i]);
            if (pkIdx == null) {
                pkIdx = new StatementMappingIndex(pkMapping);
                mappingDefinition.addMappingForMember(pkNums[i], pkIdx);
            }
            int[] inputParams = new int[pkMapping.getNumberOfDatastoreMappings()];
            for (int j = 0; j < pkMapping.getNumberOfDatastoreMappings(); j++) {
                inputParams[j] = inputParamNum++;
            }
            pkIdx.addParameterOccurrence(inputParams);
        }
    }
    String textStmt = sqlStmt.getSQLText().toSQL();
    if (op.isEmbedded()) {
        // This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
        ObjectProvider[] embeddedOwners = ec.getOwnersForEmbeddedObjectProvider(op);
        if (embeddedOwners != null) {
            // Just use the first owner
            // TODO Should check if the owner is stored in this table
            op = embeddedOwners[0];
        }
    }
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            PreparedStatement ps = sqlControl.getStatementForQuery(mconn, textStmt);
            try {
                // Provide the primary key field(s) to the JDBC statement
                if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                    StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
                    for (int i = 0; i < datastoreIdx.getNumberOfParameterOccurrences(); i++) {
                        classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(i), op.getInternalObjectId());
                    }
                } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                    op.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(op, ps, mappingDefinition));
                }
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, textStmt, ps);
                try {
                    if (!rs.next()) {
                        throw new NucleusObjectNotFoundException("No such database row", op.getInternalObjectId());
                    }
                    DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
                    int jdbcMajorVersion = dba.getDriverMajorVersion();
                    if (dba.getDatastoreDriverName().equalsIgnoreCase(OracleAdapter.OJDBC_DRIVER_NAME) && jdbcMajorVersion < 10) {
                        // Oracle JDBC drivers version 9 and below use some sh*tty Oracle-specific BLOB type
                        // we have to cast to that, face west, pray whilst saying ommmmmmmmmmm
                        oracle.sql.BLOB blob = null;
                        if (jdbcMajorVersion <= 8) {
                            OracleResultSet ors = (OracleResultSet) rs;
                            blob = ors.getBLOB(1);
                        } else {
                            blob = (oracle.sql.BLOB) rs.getBlob(1);
                        }
                        if (blob != null) {
                            // Deprecated but what can you do
                            blob.putBytes(1, bytes);
                        }
                    } else {
                        // Oracle JDBC drivers 10 and above supposedly use the JDBC standard class for Blobs
                        java.sql.Blob blob = rs.getBlob(1);
                        if (blob != null) {
                            blob.setBytes(1, bytes);
                        }
                    }
                } finally {
                    rs.close();
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException e) {
        throw new NucleusDataStoreException("Update of BLOB value failed: " + textStmt, e);
    }
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) OracleResultSet(oracle.jdbc.driver.OracleResultSet) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLException(java.sql.SQLException) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ParameterSetter(org.datanucleus.store.rdbms.fieldmanager.ParameterSetter) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) SQLController(org.datanucleus.store.rdbms.SQLController) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) ResultSet(java.sql.ResultSet) OracleResultSet(oracle.jdbc.driver.OracleResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) PreparedStatement(java.sql.PreparedStatement) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider) DatastoreAdapter(org.datanucleus.store.rdbms.adapter.DatastoreAdapter) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) Blob(java.sql.Blob) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 30 with StatementClassMapping

use of org.datanucleus.store.rdbms.query.StatementClassMapping in project datanucleus-rdbms by datanucleus.

the class ResultSetGetter method fetchObjectField.

public Object fetchObjectField(int fieldNumber) {
    StatementMappingIndex mapIdx = resultMappings.getMappingForMemberPosition(fieldNumber);
    JavaTypeMapping mapping = mapIdx.getMapping();
    AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
    RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
    Object value;
    if (mapping instanceof EmbeddedPCMapping || mapping instanceof SerialisedPCMapping || mapping instanceof SerialisedReferenceMapping) {
        value = mapping.getObject(ec, rs, mapIdx.getColumnPositions(), op, fieldNumber);
    } else {
        if (mmd.isSingleCollection()) {
            StatementClassMapping relationMappings = resultMappings.getMappingDefinitionForMemberPosition(fieldNumber);
            if (relationMappings != null) {
                Class type = ec.getClassLoaderResolver().classForName(mmd.getCollection().getElementType());
                value = processSubObjectFields(mapping, type, relationMappings);
                ElementContainerHandler containerHandler = ec.getTypeManager().getContainerHandler(mmd.getType());
                value = containerHandler.newContainer(mmd, value);
            } else {
                value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
            }
        } else if (RelationType.isRelationSingleValued(relationType)) {
            // Process fields of sub-object if available in this result set
            StatementClassMapping relationMappings = resultMappings.getMappingDefinitionForMemberPosition(fieldNumber);
            if (relationMappings != null) {
                value = processSubObjectFields(mapping, mmd.getType(), relationMappings);
            } else {
                value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
            }
        } else {
            value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
        }
    }
    if (op != null) {
        if (cmd.getSCOMutableMemberFlags()[fieldNumber]) {
            // Wrap any SCO mutable fields
            return SCOUtils.wrapSCOField(op, fieldNumber, value, false);
        } else if (RelationType.isRelationSingleValued(relationType) && (mmd.getEmbeddedMetaData() != null && mmd.getEmbeddedMetaData().getOwnerMember() != null)) {
            // Embedded PC, so make sure the field is wrapped where appropriate TODO This should be part of ManagedRelationships
            op.updateOwnerFieldInEmbeddedField(fieldNumber, value);
            return value;
        }
    }
    return value;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SerialisedReferenceMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedReferenceMapping) EmbeddedPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedPCMapping) RelationType(org.datanucleus.metadata.RelationType) SerialisedPCMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedPCMapping) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ElementContainerHandler(org.datanucleus.store.types.ElementContainerHandler) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping)

Aggregations

StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)30 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)24 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)19 ExecutionContext (org.datanucleus.ExecutionContext)17 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)17 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)14 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)13 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)13 PreparedStatement (java.sql.PreparedStatement)12 SQLException (java.sql.SQLException)12 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)12 NucleusException (org.datanucleus.exceptions.NucleusException)12 ObjectProvider (org.datanucleus.state.ObjectProvider)12 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)12 SQLController (org.datanucleus.store.rdbms.SQLController)12 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)12 UnionStatementGenerator (org.datanucleus.store.rdbms.sql.UnionStatementGenerator)10 ResultSet (java.sql.ResultSet)9 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)9 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)9