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;
}
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;
}
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;
}
}
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;
}
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;
}
Aggregations