Search in sources :

Example 21 with NucleusUserException

use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-rdbms by datanucleus.

the class JDOQLQuery method compileInternal.

/**
 * Method to compile the JDOQL query.
 * Uses the superclass to compile the generic query populating the "compilation", and then generates
 * the datastore-specific "datastoreCompilation".
 * @param parameterValues Map of param values keyed by param name (if available at compile time)
 */
protected synchronized void compileInternal(Map parameterValues) {
    if (isCompiled()) {
        return;
    }
    if (getExtension("include-soft-deletes") != null) {
        // If using an extension that can change the datastore query then evict any existing compilation
        QueryManager qm = getQueryManager();
        qm.removeQueryCompilation(Query.LANGUAGE_JDOQL, getQueryCacheKey());
    }
    // Compile the generic query expressions
    super.compileInternal(parameterValues);
    boolean inMemory = evaluateInMemory();
    if (candidateCollection != null && inMemory) {
        // TODO Maybe apply the result class checks ?
        return;
    }
    // Create the SQL statement, and its result/parameter definitions
    RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
    if (candidateClass == null) {
        throw new NucleusUserException(Localiser.msg("021009", candidateClassName));
    }
    // Make sure any persistence info is loaded
    ec.hasPersistenceInformationForClass(candidateClass);
    if (parameterValues != null) {
        // Check for null values on primitive parameters
        Set paramNames = parameterValues.entrySet();
        Iterator<Map.Entry> iter = paramNames.iterator();
        while (iter.hasNext()) {
            Map.Entry entry = iter.next();
            Object paramName = entry.getKey();
            if (paramName instanceof String) {
                Symbol sym = compilation.getSymbolTable().getSymbol((String) paramName);
                Object value = entry.getValue();
                if (value == null) {
                    // so omit the check for that case
                    if (sym != null && sym.getValueType() != null && sym.getValueType().isPrimitive()) {
                        throw new NucleusUserException(Localiser.msg("021117", paramName, sym.getValueType().getName()));
                    }
                }
            }
        }
    }
    QueryManager qm = getQueryManager();
    String datastoreKey = storeMgr.getQueryCacheKey();
    String queryCacheKey = getQueryCacheKey();
    if (useCaching() && queryCacheKey != null) {
        // Check if we have any parameters set to null, since this can invalidate a datastore compilation
        // e.g " field == :val" can be "COL IS NULL" or "COL = <val>"
        boolean nullParameter = false;
        if (parameterValues != null) {
            Iterator iter = parameterValues.values().iterator();
            while (iter.hasNext()) {
                Object val = iter.next();
                if (val == null) {
                    nullParameter = true;
                    break;
                }
            }
        }
        if (!nullParameter) {
            // Allowing caching so try to find compiled (datastore) query
            datastoreCompilation = (RDBMSQueryCompilation) qm.getDatastoreQueryCompilation(datastoreKey, getLanguage(), queryCacheKey);
            if (datastoreCompilation != null) {
                // Cached compilation exists for this datastore so reuse it
                setResultDistinct(compilation.getResultDistinct());
                return;
            }
        }
    }
    // Compile the query for the datastore since not cached
    AbstractClassMetaData acmd = getCandidateClassMetaData();
    if (type == QueryType.BULK_UPDATE) {
        datastoreCompilation = new RDBMSQueryCompilation();
        compileQueryUpdate(parameterValues, acmd);
    } else if (type == QueryType.BULK_DELETE) {
        datastoreCompilation = new RDBMSQueryCompilation();
        compileQueryDelete(parameterValues, acmd);
    } else {
        datastoreCompilation = new RDBMSQueryCompilation();
        synchronized (datastoreCompilation) {
            if (inMemory) {
                // Generate statement to just retrieve all candidate objects for later processing
                compileQueryToRetrieveCandidates(parameterValues, acmd);
            } else {
                // Generate statement to perform the full query in the datastore
                compileQueryFull(parameterValues, acmd);
                if (result != null) {
                    // Check existence of invalid selections in the result
                    StatementResultMapping resultMapping = datastoreCompilation.getResultDefinition();
                    for (int i = 0; i < resultMapping.getNumberOfResultExpressions(); i++) {
                        Object stmtMap = resultMapping.getMappingForResultExpression(i);
                        if (stmtMap instanceof StatementMappingIndex) {
                            StatementMappingIndex idx = (StatementMappingIndex) stmtMap;
                            AbstractMemberMetaData mmd = idx.getMapping().getMemberMetaData();
                            if (mmd != null) {
                                if (idx.getMapping() instanceof AbstractContainerMapping && idx.getMapping().getNumberOfDatastoreMappings() != 1) {
                                    throw new NucleusUserException(Localiser.msg("021213"));
                                }
                            }
                        }
                    }
                    if (resultClass != null) {
                        if (// Don't apply checks when user has specified the default (no result class)
                        !resultClass.getName().equals(Object[].class.getName())) {
                            // Check validity of resultClass for the result (PrivilegedAction since uses reflection)
                            AccessController.doPrivileged(new PrivilegedAction() {

                                public Object run() {
                                    // Check that this class has the necessary constructor/setters/fields to be used
                                    StatementResultMapping resultMapping = datastoreCompilation.getResultDefinition();
                                    if (QueryUtils.resultClassIsSimple(resultClass.getName())) {
                                        if (resultMapping.getNumberOfResultExpressions() > 1) {
                                            // Invalid number of result expressions
                                            throw new NucleusUserException(Localiser.msg("021201", resultClass.getName()));
                                        }
                                        Object stmtMap = resultMapping.getMappingForResultExpression(0);
                                        if (stmtMap instanceof StatementMappingIndex) {
                                            StatementMappingIndex idx = (StatementMappingIndex) stmtMap;
                                            Class exprType = idx.getMapping().getJavaType();
                                            boolean typeConsistent = false;
                                            if (exprType == resultClass) {
                                                typeConsistent = true;
                                            } else if (exprType.isPrimitive()) {
                                                Class resultClassPrimitive = ClassUtils.getPrimitiveTypeForType(resultClass);
                                                if (resultClassPrimitive == exprType) {
                                                    typeConsistent = true;
                                                }
                                            }
                                            if (!typeConsistent) {
                                                // Inconsistent expression type not matching the result class type
                                                throw new NucleusUserException(Localiser.msg("021202", resultClass.getName(), exprType));
                                            }
                                        } else {
                                            // TODO Handle StatementNewObjectMapping
                                            throw new NucleusUserException("Don't support result clause of " + result + " with resultClass of " + resultClass.getName());
                                        }
                                    } else if (QueryUtils.resultClassIsUserType(resultClass.getName())) {
                                        // Check for valid constructor (either using param types, or using default ctr)
                                        Class[] ctrTypes = new Class[resultMapping.getNumberOfResultExpressions()];
                                        for (int i = 0; i < ctrTypes.length; i++) {
                                            Object stmtMap = resultMapping.getMappingForResultExpression(i);
                                            if (stmtMap instanceof StatementMappingIndex) {
                                                ctrTypes[i] = ((StatementMappingIndex) stmtMap).getMapping().getJavaType();
                                            } else if (stmtMap instanceof StatementNewObjectMapping) {
                                            // TODO Handle this
                                            }
                                        }
                                        Constructor ctr = ClassUtils.getConstructorWithArguments(resultClass, ctrTypes);
                                        if (ctr == null && !ClassUtils.hasDefaultConstructor(resultClass)) {
                                            // No valid constructor found!
                                            throw new NucleusUserException(Localiser.msg("021205", resultClass.getName()));
                                        } else if (ctr == null) {
                                            // We are using default constructor, so check the types of the result expressions for means of input
                                            for (int i = 0; i < resultMapping.getNumberOfResultExpressions(); i++) {
                                                Object stmtMap = resultMapping.getMappingForResultExpression(i);
                                                if (stmtMap instanceof StatementMappingIndex) {
                                                    StatementMappingIndex mapIdx = (StatementMappingIndex) stmtMap;
                                                    AbstractMemberMetaData mmd = mapIdx.getMapping().getMemberMetaData();
                                                    String fieldName = mapIdx.getColumnAlias();
                                                    Class fieldType = mapIdx.getMapping().getJavaType();
                                                    if (fieldName == null && mmd != null) {
                                                        fieldName = mmd.getName();
                                                    }
                                                    if (fieldName != null) {
                                                        // Check for the field of that name in the result class
                                                        Class resultFieldType = null;
                                                        boolean publicField = true;
                                                        try {
                                                            Field fld = resultClass.getDeclaredField(fieldName);
                                                            resultFieldType = fld.getType();
                                                            // Check the type of the field
                                                            if (!ClassUtils.typesAreCompatible(fieldType, resultFieldType) && !ClassUtils.typesAreCompatible(resultFieldType, fieldType)) {
                                                                throw new NucleusUserException(Localiser.msg("021211", fieldName, fieldType.getName(), resultFieldType.getName()));
                                                            }
                                                            if (!Modifier.isPublic(fld.getModifiers())) {
                                                                publicField = false;
                                                            }
                                                        } catch (NoSuchFieldException nsfe) {
                                                            publicField = false;
                                                        }
                                                        // Check for a public set method
                                                        if (!publicField) {
                                                            Method setMethod = QueryUtils.getPublicSetMethodForFieldOfResultClass(resultClass, fieldName, resultFieldType);
                                                            if (setMethod == null) {
                                                                // No setter, so check for a public put(Object, Object) method
                                                                Method putMethod = QueryUtils.getPublicPutMethodForResultClass(resultClass);
                                                                if (putMethod == null) {
                                                                    throw new NucleusUserException(Localiser.msg("021212", resultClass.getName(), fieldName));
                                                                }
                                                            }
                                                        }
                                                    }
                                                } else if (stmtMap instanceof StatementNewObjectMapping) {
                                                // TODO Handle this
                                                }
                                            }
                                        }
                                    }
                                    return null;
                                }
                            });
                        }
                    }
                }
            }
            boolean hasParams = false;
            if (explicitParameters != null) {
                hasParams = true;
            } else if (parameterValues != null && parameterValues.size() > 0) {
                hasParams = true;
            }
            if (!statementReturnsEmpty && queryCacheKey != null && useCaching()) {
                // TODO Allow caching of queries with subqueries
                if (!datastoreCompilation.isPrecompilable() || (datastoreCompilation.getSQL().indexOf('?') < 0 && hasParams)) {
                    // Some parameters had their clauses evaluated during compilation so the query didn't gain any parameters, so don't cache it
                    NucleusLogger.QUERY.debug(Localiser.msg("021075"));
                } else {
                    qm.addDatastoreQueryCompilation(datastoreKey, getLanguage(), queryCacheKey, datastoreCompilation);
                }
            }
        }
    }
}
Also used : ResultSet(java.sql.ResultSet) Set(java.util.Set) HashSet(java.util.HashSet) Symbol(org.datanucleus.query.compiler.Symbol) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) Field(java.lang.reflect.Field) PrivilegedAction(java.security.PrivilegedAction) Iterator(java.util.Iterator) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) Constructor(java.lang.reflect.Constructor) Method(java.lang.reflect.Method) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) AbstractContainerMapping(org.datanucleus.store.rdbms.mapping.java.AbstractContainerMapping) QueryManager(org.datanucleus.store.query.QueryManager) FetchPlanForClass(org.datanucleus.FetchPlanForClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) Map(java.util.Map) HashMap(java.util.HashMap) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 22 with NucleusUserException

use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-rdbms by datanucleus.

the class JPQLQuery method compileQueryInsert.

/**
 * Method to compile the query for RDBMS for a bulk INSERT.
 * @param parameterValues The parameter values (if any)
 * @param candidateCmd Meta-data for the candidate class
 */
protected void compileQueryInsert(Map parameterValues, AbstractClassMetaData candidateCmd) {
    if (StringUtils.isWhitespace(insertFields) || StringUtils.isWhitespace(insertSelectQuery)) {
        // Nothing to INSERT
        return;
    }
    List<String> fieldNames = new ArrayList<>();
    StringTokenizer fieldTokenizer = new StringTokenizer(insertFields, ",");
    while (fieldTokenizer.hasMoreTokens()) {
        String token = fieldTokenizer.nextToken().trim();
        fieldNames.add(token);
    }
    // Generate statement for candidate and related classes in this inheritance tree
    RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
    DatastoreClass candidateTbl = storeMgr.getDatastoreClass(candidateCmd.getFullClassName(), clr);
    if (candidateTbl == null) {
        // TODO Using subclass-table, so find the table(s) it can be persisted into
        throw new NucleusDataStoreException("Bulk INSERT of " + candidateCmd.getFullClassName() + " not supported since candidate has no table of its own");
    }
    // Find table(s) that need populating with this information
    List<BulkTable> tables = new ArrayList<>();
    tables.add(new BulkTable(candidateTbl, true));
    if (candidateTbl.getSuperDatastoreClass() != null) {
        DatastoreClass tbl = candidateTbl;
        while (tbl.getSuperDatastoreClass() != null) {
            tbl = tbl.getSuperDatastoreClass();
            tables.add(0, new BulkTable(tbl, false));
        }
    }
    if (tables.size() > 1) {
        throw new NucleusUserException("BULK INSERT only currently allows a single table, but this query implies INSERT into " + tables.size() + " tables!");
    }
    List<SQLStatement> stmts = new ArrayList<>();
    List<Boolean> stmtCountFlags = new ArrayList<>();
    for (BulkTable bulkTable : tables) {
        // Generate statement for candidate
        InsertStatement stmt = new InsertStatement(storeMgr, bulkTable.table, null, null, null);
        stmt.setClassLoaderResolver(clr);
        stmt.setCandidateClassName(candidateCmd.getFullClassName());
        // Set columns for this table
        for (String fieldName : fieldNames) {
            AbstractMemberMetaData fieldMmd = candidateCmd.getMetaDataForMember(fieldName);
            if (fieldMmd == null) {
            // No such field
            } else {
                JavaTypeMapping fieldMapping = bulkTable.table.getMemberMapping(fieldMmd);
                if (fieldMapping != null) {
                    SQLExpression fieldExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), fieldMapping);
                    for (int i = 0; i < fieldExpr.getNumberOfSubExpressions(); i++) {
                        ColumnExpression fieldColExpr = fieldExpr.getSubExpression(i);
                        fieldColExpr.setOmitTableFromString(true);
                    }
                    stmt.addColumn(fieldExpr);
                } else {
                // Not in this table
                }
            }
        }
        // Generate the select query and add it to the InsertStatement
        JPQLQuery selectQuery = new JPQLQuery(storeMgr, ec, insertSelectQuery);
        selectQuery.compile();
        stmt.setSelectStatement((SelectStatement) selectQuery.getDatastoreCompilation().getStatementCompilations().get(0).getStatement());
        selectQuery.closeAll();
        // TODO if we have multiple tables then this will mean only using some of the columns in the selectSQL
        stmts.add(stmt);
        stmtCountFlags.add(bulkTable.useInCount);
        datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
    }
    datastoreCompilation.clearStatements();
    Iterator<SQLStatement> stmtIter = stmts.iterator();
    Iterator<Boolean> stmtCountFlagsIter = stmtCountFlags.iterator();
    while (stmtIter.hasNext()) {
        SQLStatement stmt = stmtIter.next();
        Boolean useInCount = stmtCountFlagsIter.next();
        if (stmts.size() == 1) {
            useInCount = true;
        }
        datastoreCompilation.addStatement(stmt, stmt.getSQLText().toSQL(), useInCount);
    }
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ArrayList(java.util.ArrayList) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) InsertStatement(org.datanucleus.store.rdbms.sql.InsertStatement) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) StringTokenizer(java.util.StringTokenizer) ColumnExpression(org.datanucleus.store.rdbms.sql.expression.ColumnExpression) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractJPQLQuery(org.datanucleus.store.query.AbstractJPQLQuery) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 23 with NucleusUserException

use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-rdbms by datanucleus.

the class JPQLQuery method compileInternal.

/**
 * Method to compile the JPQL query.
 * Uses the superclass to compile the generic query populating the "compilation", and then generates
 * the datastore-specific "datastoreCompilation".
 * @param parameterValues Map of param values keyed by param name (if available at compile time)
 */
protected synchronized void compileInternal(Map parameterValues) {
    if (isCompiled()) {
        return;
    }
    // Compile the generic query expressions
    super.compileInternal(parameterValues);
    boolean inMemory = evaluateInMemory();
    if (candidateCollection != null) {
        // TODO Maybe apply the result class checks ?
        return;
    }
    if (candidateClass == null || candidateClassName == null) {
        candidateClass = compilation.getCandidateClass();
        candidateClassName = candidateClass.getName();
    }
    // Create the SQL statement, and its result/parameter definitions
    RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
    QueryManager qm = getQueryManager();
    String datastoreKey = storeMgr.getQueryCacheKey();
    String queryCacheKey = getQueryCacheKey();
    if (useCaching() && queryCacheKey != null) {
        // Check if we have any parameters set to null, since this can invalidate a datastore compilation
        // e.g " field == :val" can be "COL IS NULL" or "COL = <val>"
        boolean nullParameter = false;
        if (parameterValues != null) {
            Iterator iter = parameterValues.values().iterator();
            while (iter.hasNext()) {
                Object val = iter.next();
                if (val == null) {
                    nullParameter = true;
                    break;
                }
            }
        }
        if (!nullParameter) {
            // Allowing caching so try to find compiled (datastore) query
            datastoreCompilation = (RDBMSQueryCompilation) qm.getDatastoreQueryCompilation(datastoreKey, getLanguage(), queryCacheKey);
            if (datastoreCompilation != null) {
                // Cached compilation exists for this datastore so reuse it
                return;
            }
        }
    }
    // No cached compilation for this query in this datastore so compile it
    AbstractClassMetaData acmd = getCandidateClassMetaData();
    if (type == QueryType.BULK_INSERT) {
        datastoreCompilation = new RDBMSQueryCompilation();
        compileQueryInsert(parameterValues, acmd);
    } else if (type == QueryType.BULK_UPDATE) {
        datastoreCompilation = new RDBMSQueryCompilation();
        compileQueryUpdate(parameterValues, acmd);
    } else if (type == QueryType.BULK_DELETE) {
        datastoreCompilation = new RDBMSQueryCompilation();
        compileQueryDelete(parameterValues, acmd);
    } else {
        datastoreCompilation = new RDBMSQueryCompilation();
        if (inMemory) {
            // Generate statement to just retrieve all candidate objects for later processing
            compileQueryToRetrieveCandidates(parameterValues, acmd);
        } else {
            // Generate statement to perform the full query in the datastore
            compileQueryFull(parameterValues, acmd);
            if (result != null) {
                StatementResultMapping resultMapping = datastoreCompilation.getResultDefinition();
                for (int i = 0; i < resultMapping.getNumberOfResultExpressions(); i++) {
                    Object stmtMap = resultMapping.getMappingForResultExpression(i);
                    if (stmtMap instanceof StatementMappingIndex) {
                        StatementMappingIndex idx = (StatementMappingIndex) stmtMap;
                        AbstractMemberMetaData mmd = idx.getMapping().getMemberMetaData();
                        if (mmd != null) {
                            if (idx.getMapping() instanceof AbstractContainerMapping && idx.getMapping().getNumberOfDatastoreMappings() != 1) {
                                throw new NucleusUserException(Localiser.msg("021213"));
                            }
                        }
                    }
                }
            }
        }
        if (resultClass != null && result != null) {
            // Do as PrivilegedAction since uses reflection
            AccessController.doPrivileged(new PrivilegedAction() {

                public Object run() {
                    // Check that this class has the necessary constructor/setters/fields to be used
                    StatementResultMapping resultMapping = datastoreCompilation.getResultDefinition();
                    if (QueryUtils.resultClassIsSimple(resultClass.getName())) {
                        if (resultMapping.getNumberOfResultExpressions() > 1) {
                            // Invalid number of result expressions
                            throw new NucleusUserException(Localiser.msg("021201", resultClass.getName()));
                        }
                        Object stmtMap = resultMapping.getMappingForResultExpression(0);
                        // TODO Handle StatementNewObjectMapping
                        StatementMappingIndex idx = (StatementMappingIndex) stmtMap;
                        Class exprType = idx.getMapping().getJavaType();
                        boolean typeConsistent = false;
                        if (exprType == resultClass) {
                            typeConsistent = true;
                        } else if (exprType.isPrimitive()) {
                            Class resultClassPrimitive = ClassUtils.getPrimitiveTypeForType(resultClass);
                            if (resultClassPrimitive == exprType) {
                                typeConsistent = true;
                            }
                        }
                        if (!typeConsistent) {
                            // Inconsistent expression type not matching the result class type
                            throw new NucleusUserException(Localiser.msg("021202", resultClass.getName(), exprType));
                        }
                    } else if (QueryUtils.resultClassIsUserType(resultClass.getName())) {
                        // Check for valid constructor (either using param types, or using default ctr)
                        Class[] ctrTypes = new Class[resultMapping.getNumberOfResultExpressions()];
                        for (int i = 0; i < ctrTypes.length; i++) {
                            Object stmtMap = resultMapping.getMappingForResultExpression(i);
                            if (stmtMap instanceof StatementMappingIndex) {
                                ctrTypes[i] = ((StatementMappingIndex) stmtMap).getMapping().getJavaType();
                            } else if (stmtMap instanceof StatementNewObjectMapping) {
                            // TODO Handle this
                            }
                        }
                        Constructor ctr = ClassUtils.getConstructorWithArguments(resultClass, ctrTypes);
                        if (ctr == null && !ClassUtils.hasDefaultConstructor(resultClass)) {
                            // No valid constructor found!
                            throw new NucleusUserException(Localiser.msg("021205", resultClass.getName()));
                        } else if (ctr == null) {
                            // We are using default constructor, so check the types of the result expressions for means of input
                            for (int i = 0; i < resultMapping.getNumberOfResultExpressions(); i++) {
                                Object stmtMap = resultMapping.getMappingForResultExpression(i);
                                if (stmtMap instanceof StatementMappingIndex) {
                                    StatementMappingIndex mapIdx = (StatementMappingIndex) stmtMap;
                                    AbstractMemberMetaData mmd = mapIdx.getMapping().getMemberMetaData();
                                    String fieldName = mapIdx.getColumnAlias();
                                    Class fieldType = mapIdx.getMapping().getJavaType();
                                    if (fieldName == null && mmd != null) {
                                        fieldName = mmd.getName();
                                    }
                                    if (fieldName != null) {
                                        // Check for the field of that name in the result class
                                        Class resultFieldType = null;
                                        boolean publicField = true;
                                        try {
                                            Field fld = resultClass.getDeclaredField(fieldName);
                                            resultFieldType = fld.getType();
                                            // Check the type of the field
                                            if (!ClassUtils.typesAreCompatible(fieldType, resultFieldType) && !ClassUtils.typesAreCompatible(resultFieldType, fieldType)) {
                                                throw new NucleusUserException(Localiser.msg("021211", fieldName, fieldType.getName(), resultFieldType.getName()));
                                            }
                                            if (!Modifier.isPublic(fld.getModifiers())) {
                                                publicField = false;
                                            }
                                        } catch (NoSuchFieldException nsfe) {
                                            publicField = false;
                                        }
                                        // Check for a public set method
                                        if (!publicField) {
                                            Method setMethod = QueryUtils.getPublicSetMethodForFieldOfResultClass(resultClass, fieldName, resultFieldType);
                                            if (setMethod == null) {
                                                // No setter, so check for a public put(Object, Object) method
                                                Method putMethod = QueryUtils.getPublicPutMethodForResultClass(resultClass);
                                                if (putMethod == null) {
                                                    throw new NucleusUserException(Localiser.msg("021212", resultClass.getName(), fieldName));
                                                }
                                            }
                                        }
                                    }
                                } else if (stmtMap instanceof StatementNewObjectMapping) {
                                // TODO Handle this
                                }
                            }
                        }
                    }
                    return null;
                }
            });
        }
        boolean hasParams = false;
        if (explicitParameters != null) {
            hasParams = true;
        } else if (parameterValues != null && parameterValues.size() > 0) {
            hasParams = true;
        }
        if (!datastoreCompilation.isPrecompilable() || (datastoreCompilation.getSQL().indexOf('?') < 0 && hasParams)) {
            // Some parameters had their clauses evaluated during compilation so the query didn't gain any parameters, so don't cache it
            NucleusLogger.QUERY.debug(Localiser.msg("021075"));
        } else {
            if (useCaching() && queryCacheKey != null) {
                qm.addDatastoreQueryCompilation(datastoreKey, getLanguage(), queryCacheKey, datastoreCompilation);
            }
        }
    }
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) Constructor(java.lang.reflect.Constructor) Method(java.lang.reflect.Method) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) Field(java.lang.reflect.Field) PrivilegedAction(java.security.PrivilegedAction) AbstractContainerMapping(org.datanucleus.store.rdbms.mapping.java.AbstractContainerMapping) QueryManager(org.datanucleus.store.query.QueryManager) Iterator(java.util.Iterator) FetchPlanForClass(org.datanucleus.FetchPlanForClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 24 with NucleusUserException

use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-rdbms by datanucleus.

the class JPQLQuery method compileQueryDelete.

/**
 * Method to compile the query for RDBMS for a bulk delete.
 * @param parameterValues The parameter values (if any)
 * @param candidateCmd Meta-data for the candidate class
 */
protected void compileQueryDelete(Map parameterValues, AbstractClassMetaData candidateCmd) {
    RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
    DatastoreClass candidateTbl = storeMgr.getDatastoreClass(candidateCmd.getFullClassName(), clr);
    if (candidateTbl == null) {
        // TODO Using subclass-table, so find the table(s) it can be persisted into
        throw new NucleusDataStoreException("Bulk delete of " + candidateCmd.getFullClassName() + " not supported since candidate has no table of its own");
    }
    InheritanceStrategy inhStr = candidateCmd.getBaseAbstractClassMetaData().getInheritanceMetaData().getStrategy();
    List<BulkTable> tables = new ArrayList<>();
    tables.add(new BulkTable(candidateTbl, true));
    if (inhStr != InheritanceStrategy.COMPLETE_TABLE) {
        // Add deletion from superclass tables since we will have an entry there
        while (candidateTbl.getSuperDatastoreClass() != null) {
            candidateTbl = candidateTbl.getSuperDatastoreClass();
            tables.add(new BulkTable(candidateTbl, false));
        }
    }
    Collection<String> subclassNames = storeMgr.getSubClassesForClass(candidateCmd.getFullClassName(), true, clr);
    if (subclassNames != null && !subclassNames.isEmpty()) {
        // Check for subclasses having their own tables and hence needing multiple DELETEs
        Iterator<String> iter = subclassNames.iterator();
        while (iter.hasNext()) {
            String subclassName = iter.next();
            DatastoreClass subclassTbl = storeMgr.getDatastoreClass(subclassName, clr);
            if (candidateTbl != subclassTbl) {
                // Only include BulkTable in count if using COMPLETE_TABLE strategy
                tables.add(0, new BulkTable(subclassTbl, inhStr == InheritanceStrategy.COMPLETE_TABLE));
            }
        }
    }
    List<SQLStatement> stmts = new ArrayList<>();
    List<Boolean> stmtCountFlags = new ArrayList<>();
    for (BulkTable bulkTable : tables) {
        // Generate statement for candidate
        DatastoreClass table = bulkTable.table;
        JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
        if (softDeleteMapping != null) {
            throw new NucleusUserException("Cannot use BulkDelete queries when using SoftDelete on an affected table (" + table + ")");
        }
        Map<String, Object> extensions = null;
        if (!storeMgr.getDatastoreAdapter().supportsOption(DatastoreAdapter.UPDATE_DELETE_STATEMENT_ALLOW_TABLE_ALIAS_IN_WHERE_CLAUSE)) {
            extensions = new HashMap<>();
            extensions.put(SQLStatement.EXTENSION_SQL_TABLE_NAMING_STRATEGY, "table-name");
        }
        SQLStatement stmt = new DeleteStatement(storeMgr, table, null, null, extensions);
        stmt.setClassLoaderResolver(clr);
        stmt.setCandidateClassName(candidateCmd.getFullClassName());
        JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
        if (multitenancyMapping != null) {
            // Multi-tenancy restriction
            SQLTable tenantSqlTbl = stmt.getPrimaryTable();
            SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, tenantSqlTbl, multitenancyMapping);
            SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, candidateCmd));
            stmt.whereAnd(tenantExpr.eq(tenantVal), true);
        }
        // TODO Discriminator restriction?
        Set<String> options = new HashSet<>();
        options.add(QueryToSQLMapper.OPTION_CASE_INSENSITIVE);
        options.add(QueryToSQLMapper.OPTION_EXPLICIT_JOINS);
        if (// Default to false for "IS NULL" with null param
        getBooleanExtensionProperty(EXTENSION_USE_IS_NULL_WHEN_EQUALS_NULL_PARAM, false)) {
            options.add(QueryToSQLMapper.OPTION_NULL_PARAM_USE_IS_NULL);
        }
        QueryToSQLMapper sqlMapper = new QueryToSQLMapper(stmt, compilation, parameterValues, null, null, candidateCmd, subclasses, getFetchPlan(), ec, null, options, extensions);
        setMapperJoinTypes(sqlMapper);
        sqlMapper.compile();
        stmts.add(stmt);
        stmtCountFlags.add(bulkTable.useInCount);
        datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
        datastoreCompilation.setPrecompilable(sqlMapper.isPrecompilable());
    }
    datastoreCompilation.clearStatements();
    Iterator<SQLStatement> stmtIter = stmts.iterator();
    Iterator<Boolean> stmtCountFlagsIter = stmtCountFlags.iterator();
    while (stmtIter.hasNext()) {
        SQLStatement stmt = stmtIter.next();
        Boolean useInCount = stmtCountFlagsIter.next();
        if (stmts.size() == 1) {
            useInCount = true;
        }
        datastoreCompilation.addStatement(stmt, stmt.getSQLText().toSQL(), useInCount);
    }
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ArrayList(java.util.ArrayList) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) DeleteStatement(org.datanucleus.store.rdbms.sql.DeleteStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) HashSet(java.util.HashSet) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) InheritanceStrategy(org.datanucleus.metadata.InheritanceStrategy) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass)

Example 25 with NucleusUserException

use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processVariableExpression.

/* (non-Javadoc)
     * @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processVariableExpression(org.datanucleus.query.expression.VariableExpression)
     */
@Override
protected Object processVariableExpression(VariableExpression expr) {
    String varName = expr.getId();
    Symbol varSym = expr.getSymbol();
    if (varSym != null) {
        // Use name from symbol if possible
        varName = varSym.getQualifiedName();
    }
    if (hasSQLTableMappingForAlias(varName)) {
        // Variable already found
        SQLTableMapping tblMapping = getSQLTableMappingForAlias(varName);
        SQLExpression sqlExpr = exprFactory.newExpression(tblMapping.table.getSQLStatement(), tblMapping.table, tblMapping.mapping);
        stack.push(sqlExpr);
        return sqlExpr;
    } else if (compilation.getCompilationForSubquery(varName) != null) {
        // Subquery variable
        QueryCompilation subCompilation = compilation.getCompilationForSubquery(varName);
        AbstractClassMetaData subCmd = ec.getMetaDataManager().getMetaDataForClass(subCompilation.getCandidateClass(), ec.getClassLoaderResolver());
        // Create subquery statement, using any provided alias if possible
        String subAlias = null;
        if (subCompilation.getCandidateAlias() != null && !subCompilation.getCandidateAlias().equals(candidateAlias)) {
            subAlias = subCompilation.getCandidateAlias();
        }
        StatementResultMapping subqueryResultMapping = new StatementResultMapping();
        // TODO Fix "avg(something)" arg - not essential but is a hack right now
        SQLStatement subStmt = RDBMSQueryUtils.getStatementForCandidates(storeMgr, stmt, subCmd, null, ec, subCompilation.getCandidateClass(), true, "avg(something)", subAlias, null, null);
        QueryToSQLMapper sqlMapper = new QueryToSQLMapper(subStmt, subCompilation, parameters, null, subqueryResultMapping, subCmd, true, fetchPlan, ec, importsDefinition, options, extensionsByName);
        sqlMapper.setDefaultJoinType(defaultJoinType);
        sqlMapper.setDefaultJoinTypeFilter(defaultJoinTypeFilter);
        sqlMapper.setParentMapper(this);
        sqlMapper.compile();
        if (subqueryResultMapping.getNumberOfResultExpressions() > 1) {
            throw new NucleusUserException("Number of result expressions in subquery should be 1");
        }
        SQLExpression subExpr = null;
        // TODO Cater for subquery select of its own candidate
        if (subqueryResultMapping.getNumberOfResultExpressions() == 0) {
            subExpr = new org.datanucleus.store.rdbms.sql.expression.SubqueryExpression(stmt, subStmt);
        } else {
            JavaTypeMapping subMapping = ((StatementMappingIndex) subqueryResultMapping.getMappingForResultExpression(0)).getMapping();
            if (subMapping instanceof TemporalMapping) {
                subExpr = new TemporalSubqueryExpression(stmt, subStmt);
            } else if (subMapping instanceof StringMapping) {
                subExpr = new StringSubqueryExpression(stmt, subStmt);
            } else {
                subExpr = new NumericSubqueryExpression(stmt, subStmt);
            }
            if (subExpr.getJavaTypeMapping() == null) {
                subExpr.setJavaTypeMapping(subMapping);
            }
        }
        stack.push(subExpr);
        return subExpr;
    } else if (stmt.getParentStatement() != null && parentMapper != null && parentMapper.candidateAlias != null && parentMapper.candidateAlias.equals(varName)) {
        // Variable in subquery linking back to parent query
        SQLExpression varExpr = exprFactory.newExpression(stmt.getParentStatement(), stmt.getParentStatement().getPrimaryTable(), stmt.getParentStatement().getPrimaryTable().getTable().getIdMapping());
        stack.push(varExpr);
        return varExpr;
    } else {
        // Variable never met before, so return as UnboundExpression - process later if needing binding
        NucleusLogger.QUERY.debug("QueryToSQL.processVariable (unbound) variable=" + varName + " is not yet bound so returning UnboundExpression");
        UnboundExpression unbExpr = new UnboundExpression(stmt, varName);
        stack.push(unbExpr);
        return unbExpr;
    }
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) Symbol(org.datanucleus.query.compiler.Symbol) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) StringMapping(org.datanucleus.store.rdbms.mapping.java.StringMapping) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) StringSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression) SubqueryExpression(org.datanucleus.query.expression.SubqueryExpression) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) StringSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression) QueryCompilation(org.datanucleus.query.compiler.QueryCompilation) TemporalMapping(org.datanucleus.store.rdbms.mapping.java.TemporalMapping)

Aggregations

NucleusUserException (org.datanucleus.exceptions.NucleusUserException)258 NucleusException (org.datanucleus.exceptions.NucleusException)65 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)51 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)46 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)46 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)41 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)36 ArrayList (java.util.ArrayList)34 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)30 ObjectProvider (org.datanucleus.state.ObjectProvider)30 ClassNotResolvedException (org.datanucleus.exceptions.ClassNotResolvedException)26 Expression (org.datanucleus.query.expression.Expression)24 InvokeExpression (org.datanucleus.query.expression.InvokeExpression)23 SQLException (java.sql.SQLException)22 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)21 NullLiteral (org.datanucleus.store.rdbms.sql.expression.NullLiteral)21 SQLLiteral (org.datanucleus.store.rdbms.sql.expression.SQLLiteral)21 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)20 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)20 BigInteger (java.math.BigInteger)19