Search in sources :

Example 1 with SQLStatement

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

the class JDOQLQuery method compileQueryUpdate.

/**
 * Method to compile the query for RDBMS for a bulk update.
 * @param parameterValues The parameter values (if any)
 * @param candidateCmd Meta-data for the candidate class
 */
protected void compileQueryUpdate(Map parameterValues, AbstractClassMetaData candidateCmd) {
    Expression[] updateExprs = compilation.getExprUpdate();
    if (updateExprs == null || updateExprs.length == 0) {
        // Nothing to update
        return;
    }
    // Generate statement for candidate
    RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
    DatastoreClass candidateTbl = storeMgr.getDatastoreClass(candidateCmd.getFullClassName(), clr);
    if (candidateTbl == null) {
        throw new NucleusDataStoreException("Bulk update of " + candidateCmd.getFullClassName() + " not supported since candidate has no table of its own");
    }
    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(new BulkTable(tbl, false));
        }
    }
    List<SQLStatement> stmts = new ArrayList<>();
    List<Boolean> stmtCountFlags = new ArrayList<>();
    for (BulkTable bulkTable : tables) {
        // Generate statement for candidate
        DatastoreClass table = bulkTable.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");
        }
        UpdateStatement stmt = new UpdateStatement(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
            SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), multitenancyMapping);
            SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, candidateCmd));
            stmt.whereAnd(tenantExpr.eq(tenantVal), true);
        }
        // TODO Discriminator restriction?
        JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
        if (softDeleteMapping != null) {
            // Soft-delete restriction
            SQLExpression softDeleteExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), softDeleteMapping);
            SQLExpression softDeleteVal = stmt.getSQLExpressionFactory().newLiteral(stmt, softDeleteMapping, Boolean.FALSE);
            stmt.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
        }
        Set<String> options = new HashSet<>();
        if (getBooleanExtensionProperty(EXTENSION_USE_IS_NULL_WHEN_EQUALS_NULL_PARAM, true)) {
            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();
        if (stmt.hasUpdates()) {
            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 : UpdateStatement(org.datanucleus.store.rdbms.sql.UpdateStatement) 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) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) Expression(org.datanucleus.query.expression.Expression) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) HashSet(java.util.HashSet)

Example 2 with SQLStatement

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

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

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

Example 5 with SQLStatement

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

the class QueryToSQLMapper method compileFilter.

/**
 * Method to compile the WHERE clause of the query into the SQLStatement.
 */
protected void compileFilter() {
    if (compilation.getExprFilter() != null) {
        // Apply the filter to the SQLStatement
        compileComponent = CompilationComponent.FILTER;
        if (QueryUtils.expressionHasOrOperator(compilation.getExprFilter())) {
            compileProperties.put("Filter.OR", true);
        }
        if (QueryUtils.expressionHasNotOperator(compilation.getExprFilter())) {
            // Really we want to know if there is a NOT contains, but just check NOT for now
            compileProperties.put("Filter.NOT", true);
        }
        if (stmt instanceof SelectStatement && ((SelectStatement) stmt).getNumberOfUnions() > 0) {
            // Process each UNIONed statement separately TODO This is only necessary when the filter contains things like "instanceof"/"TYPE" so maybe detect that
            List<SelectStatement> unionStmts = ((SelectStatement) stmt).getUnions();
            // a). Main SelectStatement, disable unions while we process it
            SQLStatement originalStmt = stmt;
            ((SelectStatement) stmt).setAllowUnions(false);
            SQLExpression filterSqlExpr = (SQLExpression) compilation.getExprFilter().evaluate(this);
            if (!(filterSqlExpr instanceof BooleanExpression)) {
                throw new QueryCompilerSyntaxException("Filter compiles to something that is not a boolean expression. Kindly fix your query : " + filterSqlExpr);
            }
            BooleanExpression filterExpr = getBooleanExpressionForUseInFilter((BooleanExpression) filterSqlExpr);
            stmt.whereAnd(filterExpr, true);
            ((SelectStatement) stmt).setAllowUnions(true);
            // b). UNIONed SelectStatements
            for (SelectStatement unionStmt : unionStmts) {
                stmt = unionStmt;
                stmt.setQueryGenerator(this);
                filterSqlExpr = (SQLExpression) compilation.getExprFilter().evaluate(this);
                if (!(filterSqlExpr instanceof BooleanExpression)) {
                    throw new QueryCompilerSyntaxException("Filter compiles to something that is not a boolean expression. Kindly fix your query : " + filterSqlExpr);
                }
                filterExpr = getBooleanExpressionForUseInFilter((BooleanExpression) filterSqlExpr);
                stmt.whereAnd(filterExpr, true);
                stmt.setQueryGenerator(null);
            }
            stmt = originalStmt;
        } else {
            SQLExpression filterSqlExpr = (SQLExpression) compilation.getExprFilter().evaluate(this);
            if (!(filterSqlExpr instanceof BooleanExpression)) {
                throw new QueryCompilerSyntaxException("Filter compiles to something that is not a boolean expression. Kindly fix your query : " + filterSqlExpr);
            }
            BooleanExpression filterExpr = (BooleanExpression) filterSqlExpr;
            filterExpr = getBooleanExpressionForUseInFilter(filterExpr);
            stmt.whereAnd(filterExpr, true);
        }
        compileComponent = null;
    }
}
Also used : SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) QueryCompilerSyntaxException(org.datanucleus.store.query.QueryCompilerSyntaxException) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement)

Aggregations

SQLStatement (org.datanucleus.store.rdbms.sql.SQLStatement)16 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)10 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)10 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)8 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)7 ArrayList (java.util.ArrayList)6 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)6 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)6 ExecutionContext (org.datanucleus.ExecutionContext)5 Expression (org.datanucleus.query.expression.Expression)5 BooleanExpression (org.datanucleus.store.rdbms.sql.expression.BooleanExpression)5 PreparedStatement (java.sql.PreparedStatement)4 ResultSet (java.sql.ResultSet)4 SQLException (java.sql.SQLException)4 HashSet (java.util.HashSet)4 Transaction (org.datanucleus.Transaction)4 SubqueryExpression (org.datanucleus.query.expression.SubqueryExpression)4 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)4 SQLController (org.datanucleus.store.rdbms.SQLController)4 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)4