Search in sources :

Example 61 with DNStateManager

use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.

the class ForwardQueryResult method nextResultSetElement.

/**
 * Accessor for the next object from the ResultSet.
 * @return The next element from the ResultSet.
 */
protected E nextResultSetElement() {
    if (rof == null) {
        // Already disconnected
        return null;
    }
    // Convert this row into its associated object and save it
    E nextElement = rof.getObject();
    JDBCUtils.logWarnings(rs);
    resultObjs.add(nextElement);
    if (resultIds != null) {
        resultIds.add(api.getIdForObject(nextElement));
    }
    // Process any bulk loaded members
    if (bulkLoadedValueByMemberNumber != null) {
        Map<Integer, Object> memberValues = bulkLoadedValueByMemberNumber.get(api.getIdForObject(nextElement));
        if (memberValues != null) {
            DNStateManager sm = query.getExecutionContext().findStateManager(nextElement);
            Iterator<Map.Entry<Integer, Object>> memberValIter = memberValues.entrySet().iterator();
            while (memberValIter.hasNext()) {
                Map.Entry<Integer, Object> memberValueEntry = memberValIter.next();
                sm.replaceField(memberValueEntry.getKey(), memberValueEntry.getValue());
            }
            sm.replaceAllLoadedSCOFieldsWithWrappers();
        }
    }
    // Update the status of whether there are more results outstanding
    if (rs == null) {
        throw new NucleusUserException("Results for query have already been closed. Perhaps you called flush(), closed the query, or ended a transaction");
    }
    try {
        moreResultSetRows = rs.next();
        if (applyRangeChecks) {
            // Check if we have reached the end of the range
            int maxElements = (int) (query.getRangeToExcl() - query.getRangeFromIncl());
            if (resultObjs.size() == maxElements) {
                moreResultSetRows = false;
            }
        }
        if (!moreResultSetRows) {
            closeResults();
        }
    } catch (SQLException e) {
        throw api.getDataStoreExceptionForException(Localiser.msg("052601", e.getMessage()), e);
    }
    return nextElement;
}
Also used : SQLException(java.sql.SQLException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) DNStateManager(org.datanucleus.state.DNStateManager) Map(java.util.Map)

Example 62 with DNStateManager

use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.

the class PersistentClassROF method getObject.

/**
 * Method to convert the current ResultSet row into a persistable Object.
 * @return The persistable object.
 */
public T getObject() {
    // Find the class of the returned object in this row of the ResultSet
    String className = null;
    boolean requiresInheritanceCheck = true;
    String discrimValue = null;
    // Used for reporting details of a failed class lookup by discriminator
    boolean hasDiscrimValue = false;
    boolean foundClassByDiscrim = false;
    StatementMappingIndex discrimMapIdx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.DISCRIMINATOR.getFieldNumber());
    if (discrimMapIdx != null) {
        // Discriminator mapping registered so use that
        try {
            discrimValue = rs.getString(discrimMapIdx.getColumnPositions()[0]);
            if (discrimValue == null) {
                // Discriminator has no value so return null object
                NucleusLogger.DATASTORE_RETRIEVE.debug("Value of discriminator is null so assuming object is null");
                return null;
            }
            hasDiscrimValue = true;
            JavaTypeMapping discrimMapping = discrimMapIdx.getMapping();
            DiscriminatorMetaData dismd = (discrimMapping != null ? discrimMapping.getTable().getDiscriminatorMetaData() : null);
            className = ec.getMetaDataManager().getClassNameFromDiscriminatorValue(discrimValue, dismd);
            if (className != null) {
                foundClassByDiscrim = true;
            }
            requiresInheritanceCheck = false;
        } catch (SQLException sqle) {
            NucleusLogger.DATASTORE_RETRIEVE.debug("Exception obtaining value of discriminator : " + sqle.getMessage());
        }
    } else if (resultMapping.getNucleusTypeColumnName() != null) {
        // Extract the object type using the NucleusType column (if available)
        try {
            className = rs.getString(resultMapping.getNucleusTypeColumnName());
            if (className == null) {
                // Discriminator has no value so return null object
                NucleusLogger.DATASTORE_RETRIEVE.debug("Value of determiner column is null so assuming object is null");
                return null;
            }
            className = className.trim();
            requiresInheritanceCheck = false;
        } catch (SQLException sqle) {
        // NucleusType column not found so ignore
        }
    }
    ClassLoaderResolver clr = ec.getClassLoaderResolver();
    Class pcClassForObject = persistentClass;
    if (className != null) {
        Class cls = (Class) resolvedClasses.get(className);
        if (cls != null) {
            pcClassForObject = cls;
        } else {
            if (persistentClass.getName().equals(className)) {
                pcClassForObject = persistentClass;
            } else {
                pcClassForObject = clr.classForName(className, persistentClass.getClassLoader());
            }
            resolvedClasses.put(className, pcClassForObject);
        }
    }
    if (requiresInheritanceCheck) {
        // Check if no instantiable subclasses
        String[] subclasses = ec.getMetaDataManager().getSubclassesForClass(pcClassForObject.getName(), false);
        if (subclasses == null || subclasses.length == 0) {
            requiresInheritanceCheck = false;
        }
    }
    String warnMsg = null;
    if (Modifier.isAbstract(pcClassForObject.getModifiers())) {
        // Persistent class is abstract so we can't create instances of that type!
        // This can happen if the user is using subclass-table and hasn't provided a discriminator in
        // the table. Try going out one level and find a (single) concrete subclass
        // TODO make this more robust and go out further
        String[] subclasses = ec.getMetaDataManager().getSubclassesForClass(pcClassForObject.getName(), false);
        if (subclasses != null) {
            Class concreteSubclass = null;
            int numConcreteSubclasses = 0;
            for (int i = 0; i < subclasses.length; i++) {
                Class subcls = clr.classForName(subclasses[i]);
                if (!Modifier.isAbstract(subcls.getModifiers())) {
                    numConcreteSubclasses++;
                    concreteSubclass = subcls;
                }
            }
            if (numConcreteSubclasses == 1) {
                // Only one possible subclass, so use that
                NucleusLogger.DATASTORE_RETRIEVE.warn(Localiser.msg("052300", pcClassForObject.getName(), concreteSubclass.getName()));
                pcClassForObject = concreteSubclass;
            } else if (numConcreteSubclasses == 0) {
                throw new NucleusUserException(Localiser.msg("052301", pcClassForObject.getName()));
            } else {
                // More than 1 possible so notify the user. Really should return the abstract
                String warnMsgSuffix;
                if (hasDiscrimValue && !foundClassByDiscrim)
                    warnMsgSuffix = "No persistent class could be found that matches the discriminator value '" + discrimValue + "'. Has the metadata for all persistent concrete subclasses been added?";
                else
                    warnMsgSuffix = "Really you need a discriminator to help identifying the type.";
                warnMsg = "Found type=" + pcClassForObject + " but abstract and more than 1 concrete subclass (" + StringUtils.objectArrayToString(subclasses) + ") when searching immediate subclasses. Choosing " + concreteSubclass + ". " + warnMsgSuffix;
                pcClassForObject = concreteSubclass;
                requiresInheritanceCheck = true;
            }
        }
    }
    // Find the statement mappings and field numbers to use for the result class
    // Caters for persistent-interfaces and the result class being an implementation
    AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(pcClassForObject, clr);
    if (cmd == null) {
        // TODO Improve this and check PK cols
        return null;
    }
    int[] fieldNumbers = resultMapping.getMemberNumbers();
    if (resultSetGetter == null) {
        // First time through, so generate mapping lookups and ResultSetGetter
        if (rootCmd instanceof InterfaceMetaData) {
            // Persistent-interface : create new mapping definition for a result type of the implementation
            mappingDefinition = new StatementClassMapping();
            mappingDefinition.setNucleusTypeColumnName(resultMapping.getNucleusTypeColumnName());
            mappedFieldNumbers = new int[fieldNumbers.length];
            for (int i = 0; i < fieldNumbers.length; i++) {
                AbstractMemberMetaData mmd = rootCmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumbers[i]);
                mappedFieldNumbers[i] = cmd.getAbsolutePositionOfMember(mmd.getName());
                mappingDefinition.addMappingForMember(mappedFieldNumbers[i], resultMapping.getMappingForMemberPosition(fieldNumbers[i]));
            }
        } else {
            // Persistent class
            mappingDefinition = resultMapping;
            mappedFieldNumbers = fieldNumbers;
        }
        // Use this result mapping definition for our ResultSetGetter
        this.resultSetGetter = new ResultSetGetter(ec, rs, mappingDefinition, rootCmd);
    }
    // Extract any surrogate version
    Object surrogateVersion = null;
    VersionMetaData vermd = cmd.getVersionMetaDataForClass();
    if (vermd != null) {
        StatementMappingIndex versionMappingIdx = null;
        if (vermd.getMemberName() == null) {
            versionMappingIdx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.VERSION.getFieldNumber());
        } else {
            versionMappingIdx = resultMapping.getMappingForMemberPosition(cmd.getMetaDataForMember(vermd.getMemberName()).getAbsoluteFieldNumber());
        }
        if (versionMappingIdx != null) {
            // Surrogate version column returned by query
            surrogateVersion = versionMappingIdx.getMapping().getObject(ec, rs, versionMappingIdx.getColumnPositions());
        }
    }
    if (persistentClass.isInterface() && !cmd.isImplementationOfPersistentDefinition()) {
        // Querying by interface, and not a generated implementation so use the metadata for the interface
        cmd = ec.getMetaDataManager().getMetaDataForInterface(persistentClass, clr);
        if (cmd == null) {
            // Fallback to the class we had
            cmd = ec.getMetaDataManager().getMetaDataForClass(pcClassForObject, clr);
        }
    }
    // Split mappedFieldNumbers into memberToSet and membersToStore
    FetchPlanForClass fpClass = fp.getFetchPlanForClass(cmd);
    List<Integer> memberNumbersToStoreTmp = new ArrayList<>();
    for (int i = 0; i < mappedFieldNumbers.length; i++) {
        if (fpClass.getRecursionDepthForMember(mappedFieldNumbers[i]) == 0) {
            memberNumbersToStoreTmp.add(mappedFieldNumbers[i]);
        } else {
            AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(mappedFieldNumbers[i]);
            if (mmd.fetchFKOnly()) {
                memberNumbersToStoreTmp.add(mappedFieldNumbers[i]);
            }
        }
    }
    int[] memberNumbersToStore = null;
    int[] memberNumbersToLoad = mappedFieldNumbers;
    if (memberNumbersToStoreTmp.size() > 0) {
        int[] memberNumberTmp = new int[mappedFieldNumbers.length - memberNumbersToStoreTmp.size()];
        int j = 0;
        for (int i = 0; i < fieldNumbers.length; i++) {
            if (!memberNumbersToStoreTmp.contains(mappedFieldNumbers[i])) {
                memberNumberTmp[j++] = mappedFieldNumbers[i];
            }
        }
        memberNumbersToLoad = memberNumberTmp;
        memberNumbersToStore = new int[memberNumbersToStoreTmp.size()];
        j = 0;
        for (Integer absNum : memberNumbersToStoreTmp) {
            memberNumbersToStore[j++] = absNum;
        }
    }
    // Extract the object from the ResultSet
    T obj = null;
    boolean needToSetVersion = false;
    if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        // Check if the PK field(s) are all null (implies null object, when using OUTER JOIN)
        int[] pkNumbers = cmd.getPKMemberPositions();
        boolean nullObject = true;
        for (int i = 0; i < pkNumbers.length; i++) {
            StatementMappingIndex pkIdx = mappingDefinition.getMappingForMemberPosition(pkNumbers[i]);
            if (pkIdx == null) {
                throw new NucleusException("You have just executed an SQL statement yet the information " + "for the primary key column(s) is not available! Please generate a testcase and report this issue");
            }
            int[] colPositions = pkIdx.getColumnPositions();
            for (int j = 0; j < colPositions.length; j++) {
                try {
                    if (rs.getObject(colPositions[j]) != null) {
                        nullObject = false;
                        break;
                    }
                } catch (SQLException sqle) {
                    NucleusLogger.DATASTORE_RETRIEVE.warn("Exception thrown while retrieving results ", sqle);
                }
                if (!nullObject) {
                    break;
                }
            }
        }
        if (!nullObject) {
            // Retrieve the object with this application-identity
            if (warnMsg != null) {
                NucleusLogger.DATASTORE_RETRIEVE.warn(warnMsg);
            }
            Object id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, pcClassForObject, requiresInheritanceCheck, resultSetGetter);
            String idClassName = IdentityUtils.getTargetClassNameForIdentity(id);
            if (idClassName != null) {
                // "identity" defines the class name
                pcClassForObject = clr.classForName(idClassName);
            }
            obj = findObjectWithIdAndLoadFields(id, memberNumbersToLoad, memberNumbersToStore, pcClassForObject, cmd, surrogateVersion);
        }
    } else if (cmd.getIdentityType() == IdentityType.DATASTORE) {
        // Generate the "id" for this object (of type pcClassForObject), and find the object for that
        StatementMappingIndex datastoreIdMapping = resultMapping.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
        JavaTypeMapping mapping = datastoreIdMapping.getMapping();
        Object id = mapping.getObject(ec, rs, datastoreIdMapping.getColumnPositions());
        if (id != null) {
            String idClassName = IdentityUtils.getTargetClassNameForIdentity(id);
            if (!pcClassForObject.getName().equals(idClassName)) {
                // Get a DatastoreId for the right inheritance level
                id = ec.getNucleusContext().getIdentityManager().getDatastoreId(pcClassForObject.getName(), IdentityUtils.getTargetKeyForDatastoreIdentity(id));
            }
            if (warnMsg != null) {
                NucleusLogger.DATASTORE_RETRIEVE.warn(warnMsg);
            }
            if (mappedFieldNumbers == null) {
                obj = (T) ec.findObject(id, false, requiresInheritanceCheck, null);
                needToSetVersion = true;
            } else {
                obj = findObjectWithIdAndLoadFields(id, memberNumbersToLoad, memberNumbersToStore, requiresInheritanceCheck ? null : pcClassForObject, cmd, surrogateVersion);
            }
        }
    } else if (cmd.getIdentityType() == IdentityType.NONDURABLE) {
        String classNameForId = className;
        if (className == null) {
            // No discriminator info from the query, so just fallback to default type
            classNameForId = cmd.getFullClassName();
        }
        Object id = ec.newObjectId(classNameForId, null);
        if (mappedFieldNumbers == null) {
            obj = (T) ec.findObject(id, false, requiresInheritanceCheck, null);
            needToSetVersion = true;
        } else {
            // TODO Not passing in memberNumbersToStore. Why are we using fieldNumbers anyway?
            obj = findObjectWithIdAndLoadFields(id, fieldNumbers, null, pcClassForObject, cmd, surrogateVersion);
        }
    }
    if (obj != null && needToSetVersion) {
        // Set the version of the object where possible
        if (surrogateVersion != null) {
            DNStateManager objSM = ec.findStateManager(obj);
            objSM.setVersion(surrogateVersion);
        } else {
            if (vermd != null && vermd.getMemberName() != null) {
                // Version stored in a normal field
                int versionFieldNumber = rootCmd.getMetaDataForMember(vermd.getMemberName()).getAbsoluteFieldNumber();
                if (resultMapping.getMappingForMemberPosition(versionFieldNumber) != null) {
                    DNStateManager objSM = ec.findStateManager(obj);
                    Object verFieldValue = objSM.provideField(versionFieldNumber);
                    if (verFieldValue != null) {
                        objSM.setVersion(verFieldValue);
                    }
                }
            }
        }
    }
    return obj;
}
Also used : FetchPlanForClass(org.datanucleus.FetchPlanForClass) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLException(java.sql.SQLException) VersionMetaData(org.datanucleus.metadata.VersionMetaData) ArrayList(java.util.ArrayList) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ResultSetGetter(org.datanucleus.store.rdbms.fieldmanager.ResultSetGetter) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) FetchPlanForClass(org.datanucleus.FetchPlanForClass) InterfaceMetaData(org.datanucleus.metadata.InterfaceMetaData) DNStateManager(org.datanucleus.state.DNStateManager) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 63 with DNStateManager

use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.

the class ResultMetaDataROF method getObject.

/**
 * Accessor for the object(s) from the current row of the ResultSet.
 * @return The object(s) for this row of the ResultSet.
 */
public Object getObject() {
    List returnObjects = new ArrayList();
    // A). Process persistent types
    PersistentTypeMapping[] persistentTypes = queryResultMetaData.getPersistentTypeMappings();
    if (persistentTypes != null) {
        if (persistentTypeResultSetGetters == null) {
            persistentTypeResultSetGetters = new ResultSetGetter[persistentTypes.length];
        }
        int startColumnIndex = 0;
        for (int i = 0; i < persistentTypes.length; i++) {
            Set<String> columnsInThisType = new HashSet<>();
            AbstractMemberMetaData[] mmds = new AbstractMemberMetaData[columnNames.length];
            Map<String, AbstractMemberMetaData> fieldColumns = new HashMap<>();
            DatastoreClass dc = ((RDBMSStoreManager) ec.getStoreManager()).getDatastoreClass(persistentTypes[i].getClassName(), ec.getClassLoaderResolver());
            AbstractClassMetaData acmd = ec.getMetaDataManager().getMetaDataForClass(persistentTypes[i].getClassName(), ec.getClassLoaderResolver());
            Object id = null;
            // and two columns with similar names e.g "Col1" and "col1". Until that situation comes up we ignore it :-)
            for (int j = startColumnIndex; j < columnNames.length; j++) {
                if (columnsInThisType.contains(columnNames[j])) {
                    // already added this column, so must be another persistent type
                    startColumnIndex = j;
                    break;
                }
                boolean found = false;
                if (acmd.getIdentityType() == IdentityType.DATASTORE) {
                    JavaTypeMapping datastoreIdMapping = dc.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
                    Column df = datastoreIdMapping.getColumnMapping(0).getColumn();
                    if (df.getIdentifier().getName().equalsIgnoreCase(columnNames[j])) {
                        // add +1 because result sets in jdbc starts with 1
                        int datastoreIdentityExpressionIndex = j + 1;
                        id = datastoreIdMapping.getObject(ec, rs, new int[] { datastoreIdentityExpressionIndex });
                        found = true;
                    }
                }
                for (int k = 0; k < acmd.getNoOfManagedMembers() + acmd.getNoOfInheritedManagedMembers() && !found; k++) {
                    AbstractMemberMetaData apmd = acmd.getMetaDataForManagedMemberAtAbsolutePosition(k);
                    if (persistentTypes[i].getColumnForField(apmd.getName()) != null) {
                        if (persistentTypes[i].getColumnForField(apmd.getName()).equalsIgnoreCase(columnNames[j])) {
                            fieldColumns.put(columnNames[j], apmd);
                            columnsInThisType.add(columnNames[j]);
                            mmds[j] = apmd;
                            found = true;
                        }
                    } else {
                        JavaTypeMapping mapping = dc.getMemberMapping(apmd);
                        for (int l = 0; l < mapping.getColumnMappings().length && !found; l++) {
                            Column df = mapping.getColumnMapping(l).getColumn();
                            if (df.getIdentifier().getName().equalsIgnoreCase(columnNames[j])) {
                                fieldColumns.put(columnNames[j], apmd);
                                columnsInThisType.add(columnNames[j]);
                                mmds[j] = apmd;
                                found = true;
                            }
                        }
                    }
                }
                if (!columnsInThisType.contains(columnNames[j])) {
                    // column not found in this type, so must be another persistent type
                    startColumnIndex = j;
                    break;
                }
            }
            // Build fields and mappings in the results
            StatementMappingIndex[] stmtMappings = new StatementMappingIndex[acmd.getNoOfManagedMembers() + acmd.getNoOfInheritedManagedMembers()];
            Set<AbstractMemberMetaData> resultMmds = new HashSet<>();
            resultMmds.addAll(fieldColumns.values());
            int[] resultFieldNumbers = new int[resultMmds.size()];
            int j = 0;
            for (AbstractMemberMetaData apmd : resultMmds) {
                StatementMappingIndex stmtMapping = new StatementMappingIndex(dc.getMemberMapping(apmd));
                resultFieldNumbers[j] = apmd.getAbsoluteFieldNumber();
                List indexes = new ArrayList();
                for (int k = 0; k < mmds.length; k++) {
                    if (mmds[k] == apmd) {
                        indexes.add(Integer.valueOf(k));
                    }
                }
                int[] indxs = new int[indexes.size()];
                for (int k = 0; k < indxs.length; k++) {
                    // add +1 because result sets in JDBC starts with 1
                    indxs[k] = ((Integer) indexes.get(k)).intValue() + 1;
                }
                stmtMapping.setColumnPositions(indxs);
                stmtMappings[resultFieldNumbers[j]] = stmtMapping;
                j++;
            }
            Object obj = null;
            Class type = ec.getClassLoaderResolver().classForName(persistentTypes[i].getClassName());
            if (acmd.getIdentityType() == IdentityType.APPLICATION) {
                if (persistentTypeResultSetGetters[i] == null) {
                    final StatementClassMapping resultMappings = new StatementClassMapping();
                    for (int k = 0; k < resultFieldNumbers.length; k++) {
                        resultMappings.addMappingForMember(resultFieldNumbers[k], stmtMappings[resultFieldNumbers[k]]);
                    }
                    persistentTypeResultSetGetters[i] = new ResultSetGetter(ec, rs, resultMappings, acmd);
                }
                ResultSetGetter rsGetter = persistentTypeResultSetGetters[i];
                // TODO Make use of discriminator like in PersistentClassROF and set the pcClass in this?
                id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, acmd, type, false, rsGetter);
                obj = ec.findObject(id, new FieldValues() {

                    public void fetchFields(DNStateManager sm) {
                        rsGetter.setStateManager(sm);
                        sm.replaceFields(resultFieldNumbers, rsGetter, false);
                    }

                    public void fetchNonLoadedFields(DNStateManager sm) {
                        rsGetter.setStateManager(sm);
                        sm.replaceNonLoadedFields(resultFieldNumbers, rsGetter);
                    }

                    public FetchPlan getFetchPlanForLoading() {
                        return null;
                    }
                }, type, ignoreCache, false);
            } else if (acmd.getIdentityType() == IdentityType.DATASTORE) {
                if (persistentTypeResultSetGetters[i] == null) {
                    final StatementClassMapping resultMappings = new StatementClassMapping();
                    for (int k = 0; k < resultFieldNumbers.length; k++) {
                        resultMappings.addMappingForMember(resultFieldNumbers[k], stmtMappings[resultFieldNumbers[k]]);
                    }
                    persistentTypeResultSetGetters[i] = new ResultSetGetter(ec, rs, resultMappings, acmd);
                }
                ResultSetGetter rsGetter = persistentTypeResultSetGetters[i];
                obj = ec.findObject(id, new FieldValues() {

                    public void fetchFields(DNStateManager sm) {
                        rsGetter.setStateManager(sm);
                        sm.replaceFields(resultFieldNumbers, rsGetter, false);
                    }

                    public void fetchNonLoadedFields(DNStateManager sm) {
                        rsGetter.setStateManager(sm);
                        sm.replaceNonLoadedFields(resultFieldNumbers, rsGetter);
                    }

                    public FetchPlan getFetchPlanForLoading() {
                        return null;
                    }
                }, type, ignoreCache, false);
            } else {
                // TODO Handle non-durable
                NucleusLogger.QUERY.warn("We do not currently support non-durable objects in the results of this type of query.");
            }
            returnObjects.add(obj);
        }
    }
    // B). Process simple columns
    String[] columns = queryResultMetaData.getScalarColumns();
    if (columns != null) {
        for (int i = 0; i < columns.length; i++) {
            try {
                Object obj = rs.getObject(columns[i]);
                returnObjects.add(obj);
            } catch (SQLException sqe) {
                String msg = Localiser.msg("059027", sqe.getMessage());
                NucleusLogger.QUERY.error(msg);
                throw new NucleusUserException(msg, sqe);
            }
        }
    }
    // C). Process constructor type mappings
    ConstructorTypeMapping[] ctrTypeMappings = queryResultMetaData.getConstructorTypeMappings();
    if (ctrTypeMappings != null) {
        for (int i = 0; i < ctrTypeMappings.length; i++) {
            String ctrClassName = ctrTypeMappings[i].getClassName();
            Class ctrCls = ec.getClassLoaderResolver().classForName(ctrClassName);
            List<ConstructorTypeColumn> ctrColumns = ctrTypeMappings[i].getColumnsForConstructor();
            Class[] ctrArgTypes = null;
            Object[] ctrArgVals = null;
            if (ctrColumns != null && ctrColumns.size() > 0) {
                int j = 0;
                ctrArgTypes = new Class[ctrColumns.size()];
                ctrArgVals = new Object[ctrColumns.size()];
                Iterator<ConstructorTypeColumn> colIter = ctrColumns.iterator();
                while (colIter.hasNext()) {
                    ConstructorTypeColumn ctrCol = colIter.next();
                    try {
                        Object colVal = rs.getObject(ctrCol.getColumnName());
                        ctrArgTypes[j] = colVal.getClass();
                        if (ctrCol.getJavaType() != null) {
                            // Attempt to convert to the type requested
                            ctrArgTypes[j] = ctrCol.getJavaType();
                            ctrArgVals[j] = TypeConversionHelper.convertTo(colVal, ctrArgTypes[j]);
                        } else {
                            ctrArgTypes[j] = colVal.getClass();
                            ctrArgVals[j] = colVal;
                        }
                    } catch (SQLException sqle) {
                    // TODO Handle this
                    }
                    j++;
                }
            }
            returnObjects.add(ClassUtils.newInstance(ctrCls, ctrArgTypes, ctrArgVals));
        }
    }
    if (returnObjects.size() == 0) {
        // No objects so user must have supplied incorrect MetaData
        return null;
    } else if (returnObjects.size() == 1) {
        // Return Object
        return returnObjects.get(0);
    } else {
        // Return Object[]
        return returnObjects.toArray(new Object[returnObjects.size()]);
    }
}
Also used : HashMap(java.util.HashMap) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) FetchPlan(org.datanucleus.FetchPlan) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ResultSetGetter(org.datanucleus.store.rdbms.fieldmanager.ResultSetGetter) ConstructorTypeColumn(org.datanucleus.metadata.QueryResultMetaData.ConstructorTypeColumn) Column(org.datanucleus.store.rdbms.table.Column) ArrayList(java.util.ArrayList) List(java.util.List) PersistentTypeMapping(org.datanucleus.metadata.QueryResultMetaData.PersistentTypeMapping) HashSet(java.util.HashSet) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) ConstructorTypeColumn(org.datanucleus.metadata.QueryResultMetaData.ConstructorTypeColumn) ConstructorTypeMapping(org.datanucleus.metadata.QueryResultMetaData.ConstructorTypeMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DNStateManager(org.datanucleus.state.DNStateManager) FieldValues(org.datanucleus.store.FieldValues) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 64 with DNStateManager

use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.

the class ScrollableQueryResult method getObjectForIndex.

/**
 * Accessor for the result object at an index.
 * If the object has already been processed will return that object,
 * otherwise will retrieve the object using the factory.
 * @param index The list index position
 * @return The result object
 */
protected E getObjectForIndex(int index) {
    if (resultsObjsByIndex != null) {
        // Caching objects, so check the cache for this index
        E obj = resultsObjsByIndex.get(index);
        if (obj != null) {
            // Already retrieved so return it
            return obj;
        }
    }
    if (rs == null) {
        throw new NucleusUserException("Results for query have already been closed. Perhaps you called flush(), closed the query, or ended a transaction");
    }
    try {
        // ResultSet is numbered 1, 2, ... N
        // List is indexed 0, 1, 2, ... N-1
        rs.absolute(index + 1);
        E obj = rof.getObject();
        JDBCUtils.logWarnings(rs);
        // Process any bulk loaded members
        if (bulkLoadedValueByMemberNumber != null) {
            ExecutionContext ec = query.getExecutionContext();
            Map<Integer, Object> memberValues = bulkLoadedValueByMemberNumber.get(api.getIdForObject(obj));
            if (memberValues != null) {
                DNStateManager sm = ec.findStateManager(obj);
                Iterator<Map.Entry<Integer, Object>> memberValIter = memberValues.entrySet().iterator();
                while (memberValIter.hasNext()) {
                    Map.Entry<Integer, Object> memberValueEntry = memberValIter.next();
                    sm.replaceField(memberValueEntry.getKey(), memberValueEntry.getValue());
                }
                sm.replaceAllLoadedSCOFieldsWithWrappers();
            }
        }
        if (resultsObjsByIndex != null) {
            // Put it in our cache, keyed by the list index
            resultsObjsByIndex.put(index, obj);
            if (resultIdsByPosition != null) {
                resultIdsByPosition.put(index, api.getIdForObject(obj));
            }
        }
        return obj;
    } catch (SQLException sqe) {
        throw api.getDataStoreExceptionForException(Localiser.msg("052601", sqe.getMessage()), sqe);
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) SQLException(java.sql.SQLException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) DNStateManager(org.datanucleus.state.DNStateManager) HashMap(java.util.HashMap) ConcurrentReferenceHashMap(org.datanucleus.util.ConcurrentReferenceHashMap) Map(java.util.Map)

Aggregations

DNStateManager (org.datanucleus.state.DNStateManager)64 ExecutionContext (org.datanucleus.ExecutionContext)38 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)22 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)20 SQLException (java.sql.SQLException)17 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)16 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)15 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)15 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)14 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)14 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)13 SQLController (org.datanucleus.store.rdbms.SQLController)13 PreparedStatement (java.sql.PreparedStatement)12 ResultSet (java.sql.ResultSet)10 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)9 NucleusException (org.datanucleus.exceptions.NucleusException)9 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)9 Collection (java.util.Collection)8 ArrayList (java.util.ArrayList)7 RelationType (org.datanucleus.metadata.RelationType)7