Search in sources :

Example 1 with NumericSubqueryExpression

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

the class SimpleNumericAggregateMethod method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List<SQLExpression> args) {
    if (expr != null) {
        throw new NucleusException(Localiser.msg("060002", getFunctionName(), expr));
    }
    if (args == null || args.size() != 1) {
        throw new NucleusException(getFunctionName() + " is only supported with a single argument");
    }
    if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.RESULT || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.HAVING) {
        // FUNC(argExpr)
        // Use same java type as the argument
        SQLExpression argExpr = args.get(0);
        JavaTypeMapping m = argExpr.getJavaTypeMapping();
        return new AggregateNumericExpression(stmt, m, getFunctionName(), args);
    }
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    // Handle as Subquery "SELECT AVG(expr) FROM tbl"
    SQLExpression argExpr = args.get(0);
    SelectStatement subStmt = new SelectStatement(stmt, stmt.getRDBMSManager(), argExpr.getSQLTable().getTable(), argExpr.getSQLTable().getAlias(), null);
    subStmt.setClassLoaderResolver(clr);
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    JavaTypeMapping mapping = stmt.getRDBMSManager().getMappingManager().getMappingWithColumnMapping(String.class, false, false, clr);
    String aggregateString = getFunctionName() + "(" + argExpr.toSQLText() + ")";
    SQLExpression aggExpr = exprFactory.newLiteral(subStmt, mapping, aggregateString);
    ((StringLiteral) aggExpr).generateStatementWithoutQuotes();
    subStmt.select(aggExpr, null);
    JavaTypeMapping subqMapping = exprFactory.getMappingForType(Integer.class, false);
    SQLExpression subqExpr = new NumericSubqueryExpression(stmt, subStmt);
    subqExpr.setJavaTypeMapping(subqMapping);
    return subqExpr;
}
Also used : SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) StringLiteral(org.datanucleus.store.rdbms.sql.expression.StringLiteral) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) AggregateNumericExpression(org.datanucleus.store.rdbms.sql.expression.AggregateNumericExpression) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NucleusException(org.datanucleus.exceptions.NucleusException) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression)

Example 2 with NumericSubqueryExpression

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

the class ArraySizeMethod method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List<SQLExpression> args) {
    if (args != null && args.size() > 0) {
        throw new NucleusException(Localiser.msg("060015", "size/length", "ArrayExpression"));
    }
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    if (expr instanceof ArrayLiteral) {
        // Just return the array length since we have the value
        return exprFactory.newLiteral(stmt, exprFactory.getMappingForType(int.class, false), Integer.valueOf(Array.getLength(((ArrayLiteral) expr).getValue())));
    }
    AbstractMemberMetaData ownerMmd = expr.getJavaTypeMapping().getMemberMetaData();
    String elementType = ownerMmd.getArray().getElementType();
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    // TODO Allow for interface elements, etc
    JavaTypeMapping ownerMapping = null;
    Table arrayTbl = null;
    if (ownerMmd.getMappedBy() != null) {
        // Bidirectional
        AbstractMemberMetaData elementMmd = ownerMmd.getRelatedMemberMetaData(clr)[0];
        if (ownerMmd.getJoinMetaData() != null || elementMmd.getJoinMetaData() != null) {
            // JoinTable
            arrayTbl = storeMgr.getTable(ownerMmd);
            ownerMapping = ((JoinTable) arrayTbl).getOwnerMapping();
        } else {
            // ForeignKey
            arrayTbl = storeMgr.getDatastoreClass(elementType, clr);
            ownerMapping = arrayTbl.getMemberMapping(elementMmd);
        }
    } else {
        // Unidirectional
        if (ownerMmd.getJoinMetaData() != null) {
            // JoinTable
            arrayTbl = storeMgr.getTable(ownerMmd);
            ownerMapping = ((JoinTable) arrayTbl).getOwnerMapping();
        } else {
            // ForeignKey
            arrayTbl = storeMgr.getDatastoreClass(elementType, clr);
            ownerMapping = ((DatastoreClass) arrayTbl).getExternalMapping(ownerMmd, MappingType.EXTERNAL_FK);
        }
    }
    SelectStatement subStmt = new SelectStatement(stmt, storeMgr, arrayTbl, null, null);
    subStmt.setClassLoaderResolver(clr);
    JavaTypeMapping mapping = storeMgr.getMappingManager().getMappingWithColumnMapping(String.class, false, false, clr);
    SQLExpression countExpr = exprFactory.newLiteral(subStmt, mapping, "COUNT(*)");
    ((StringLiteral) countExpr).generateStatementWithoutQuotes();
    subStmt.select(countExpr, null);
    SQLExpression elementOwnerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
    SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, expr.getSQLTable(), expr.getSQLTable().getTable().getIdMapping());
    subStmt.whereAnd(elementOwnerExpr.eq(ownerIdExpr), true);
    JavaTypeMapping subqMapping = exprFactory.getMappingForType(Integer.class, false);
    SQLExpression subqExpr = new NumericSubqueryExpression(stmt, subStmt);
    subqExpr.setJavaTypeMapping(subqMapping);
    return subqExpr;
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) Table(org.datanucleus.store.rdbms.table.Table) JoinTable(org.datanucleus.store.rdbms.table.JoinTable) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) ArrayLiteral(org.datanucleus.store.rdbms.sql.expression.ArrayLiteral) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) StringLiteral(org.datanucleus.store.rdbms.sql.expression.StringLiteral) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 3 with NumericSubqueryExpression

use of org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression 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.store.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) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) SubqueryExpression(org.datanucleus.store.query.expression.SubqueryExpression) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) StringSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression) QueryCompilation(org.datanucleus.store.query.compiler.QueryCompilation) TemporalMapping(org.datanucleus.store.rdbms.mapping.java.TemporalMapping)

Example 4 with NumericSubqueryExpression

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

the class AvgFunction method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List args) {
    if (expr != null) {
        throw new NucleusException(Localiser.msg("060002", getFunctionName(), expr));
    }
    if (args == null || args.size() != 1) {
        throw new NucleusException(getFunctionName() + " is only supported with a single argument");
    }
    // Set the return type (double, for JDOQL and JPQL)
    Class returnType = Double.class;
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.RESULT || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.HAVING) {
        // FUNC(argExpr)
        JavaTypeMapping m = exprFactory.getMappingForType(returnType, true);
        return getAggregateExpression(stmt, args, m);
    }
    // Handle as Subquery "SELECT AVG(expr) FROM tbl"
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    SQLExpression argExpr = (SQLExpression) args.get(0);
    SelectStatement subStmt = new SelectStatement(stmt, stmt.getRDBMSManager(), argExpr.getSQLTable().getTable(), argExpr.getSQLTable().getAlias(), null);
    subStmt.setClassLoaderResolver(clr);
    JavaTypeMapping mapping = stmt.getRDBMSManager().getMappingManager().getMappingWithColumnMapping(String.class, false, false, clr);
    SQLExpression aggExpr = getAggregateExpression(stmt, args, mapping);
    subStmt.select(aggExpr, null);
    JavaTypeMapping subqMapping = exprFactory.getMappingForType(returnType, false);
    SQLExpression subqExpr = new NumericSubqueryExpression(stmt, subStmt);
    subqExpr.setJavaTypeMapping(subqMapping);
    return subqExpr;
}
Also used : SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NucleusException(org.datanucleus.exceptions.NucleusException) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression)

Example 5 with NumericSubqueryExpression

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

the class CollectionSizeMethod method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List<SQLExpression> args) {
    if (args != null && args.size() > 0) {
        throw new NucleusException(Localiser.msg("060015", "size", "CollectionExpression"));
    }
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    if (expr instanceof CollectionLiteral) {
        // Just return the collection size since we have the value
        Collection coll = (Collection) ((CollectionLiteral) expr).getValue();
        return exprFactory.newLiteral(stmt, exprFactory.getMappingForType(int.class, false), Integer.valueOf(coll.size()));
    }
    AbstractMemberMetaData mmd = expr.getJavaTypeMapping().getMemberMetaData();
    if (mmd.isSerialized()) {
        throw new NucleusUserException("Cannot perform Collection.size when the collection is being serialised");
    }
    ApiAdapter api = stmt.getRDBMSManager().getApiAdapter();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    Class elementCls = clr.classForName(mmd.getCollection().getElementType());
    if (!api.isPersistable(elementCls) && mmd.getJoinMetaData() == null) {
        throw new NucleusUserException("Cannot perform Collection.size when the collection<Non-Persistable> is not in a join table");
    }
    String elementType = mmd.getCollection().getElementType();
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    // TODO Allow for interface elements, etc
    JavaTypeMapping ownerMapping = null;
    Table collectionTbl = null;
    if (mmd.getMappedBy() != null) {
        // Bidirectional
        AbstractMemberMetaData elementMmd = mmd.getRelatedMemberMetaData(clr)[0];
        if (mmd.getJoinMetaData() != null || elementMmd.getJoinMetaData() != null) {
            // JoinTable
            collectionTbl = storeMgr.getTable(mmd);
            ownerMapping = ((JoinTable) collectionTbl).getOwnerMapping();
        } else {
            // ForeignKey
            collectionTbl = storeMgr.getDatastoreClass(elementType, clr);
            ownerMapping = collectionTbl.getMemberMapping(elementMmd);
        }
    } else {
        // Unidirectional
        if (mmd.getJoinMetaData() != null) {
            // JoinTable
            collectionTbl = storeMgr.getTable(mmd);
            ownerMapping = ((JoinTable) collectionTbl).getOwnerMapping();
        } else {
            // ForeignKey
            collectionTbl = storeMgr.getDatastoreClass(elementType, clr);
            ownerMapping = ((DatastoreClass) collectionTbl).getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
    }
    SelectStatement subStmt = new SelectStatement(stmt, storeMgr, collectionTbl, null, null);
    subStmt.setClassLoaderResolver(clr);
    JavaTypeMapping mapping = storeMgr.getMappingManager().getMappingWithColumnMapping(String.class, false, false, clr);
    SQLExpression countExpr = exprFactory.newLiteral(subStmt, mapping, "COUNT(*)");
    ((StringLiteral) countExpr).generateStatementWithoutQuotes();
    subStmt.select(countExpr, null);
    SQLExpression elementOwnerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
    SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, expr.getSQLTable(), expr.getSQLTable().getTable().getIdMapping());
    subStmt.whereAnd(elementOwnerExpr.eq(ownerIdExpr), true);
    JavaTypeMapping subqMapping = exprFactory.getMappingForType(Integer.class, false);
    SQLExpression subqExpr = new NumericSubqueryExpression(stmt, subStmt);
    subqExpr.setJavaTypeMapping(subqMapping);
    return subqExpr;
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) ApiAdapter(org.datanucleus.api.ApiAdapter) Table(org.datanucleus.store.rdbms.table.Table) JoinTable(org.datanucleus.store.rdbms.table.JoinTable) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) CollectionLiteral(org.datanucleus.store.rdbms.sql.expression.CollectionLiteral) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) StringLiteral(org.datanucleus.store.rdbms.sql.expression.StringLiteral) Collection(java.util.Collection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

NumericSubqueryExpression (org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression)8 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)8 NucleusException (org.datanucleus.exceptions.NucleusException)7 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)7 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)6 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)6 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)6 StringLiteral (org.datanucleus.store.rdbms.sql.expression.StringLiteral)5 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)3 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)3 StringSubqueryExpression (org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression)3 TemporalSubqueryExpression (org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression)3 JoinTable (org.datanucleus.store.rdbms.table.JoinTable)3 Table (org.datanucleus.store.rdbms.table.Table)3 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)2 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)2 SubqueryExpression (org.datanucleus.store.query.expression.SubqueryExpression)2 SQLStatement (org.datanucleus.store.rdbms.sql.SQLStatement)2 AggregateNumericExpression (org.datanucleus.store.rdbms.sql.expression.AggregateNumericExpression)2 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)2