use of org.datanucleus.store.rdbms.sql.expression.NullLiteral in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method processInvokeExpression.
/**
* Internal method to handle the processing of an InvokeExpression.
* @param expr The InvokeExpression
* @param invokedSqlExpr The SQLExpression that we are invoking the method on.
* @return The resultant SQLExpression
*/
protected SQLExpression processInvokeExpression(InvokeExpression expr, SQLExpression invokedSqlExpr) {
if (invokedSqlExpr instanceof NullLiteral) {
// We cannot invoke anything on a null TODO Handle this "NPE"
NucleusLogger.QUERY.warn("Compilation of InvokeExpression needs to invoke method \"" + expr.getOperation() + "\" on " + invokedSqlExpr + " but not possible");
}
String operation = expr.getOperation();
if (invokedSqlExpr instanceof MapExpression && operation.equals("contains") && compilation.getQueryLanguage().equalsIgnoreCase(Query.LANGUAGE_JPQL)) {
// JPQL "MEMBER OF" will be passed through from generic compilation as "contains" since we don't know types at that point
operation = "containsValue";
}
// Process the arguments for invoking
List args = expr.getArguments();
List sqlExprArgs = null;
if (args != null) {
sqlExprArgs = new ArrayList<SQLExpression>();
Iterator<Expression> iter = args.iterator();
while (iter.hasNext()) {
Expression argExpr = iter.next();
if (argExpr instanceof PrimaryExpression) {
processPrimaryExpression((PrimaryExpression) argExpr);
SQLExpression argSqlExpr = stack.pop();
if (compileComponent == CompilationComponent.RESULT && operation.equalsIgnoreCase("count") && stmt.getNumberOfTableGroups() > 1) {
if (argSqlExpr.getSQLTable() == stmt.getPrimaryTable() && argSqlExpr.getJavaTypeMapping() == stmt.getPrimaryTable().getTable().getIdMapping()) {
// Result with "count(this)" and joins to other groups, so enforce distinct
argSqlExpr.distinct();
}
}
sqlExprArgs.add(argSqlExpr);
} else if (argExpr instanceof ParameterExpression) {
processParameterExpression((ParameterExpression) argExpr);
sqlExprArgs.add(stack.pop());
} else if (argExpr instanceof InvokeExpression) {
processInvokeExpression((InvokeExpression) argExpr);
sqlExprArgs.add(stack.pop());
} else if (argExpr instanceof Literal) {
processLiteral((Literal) argExpr);
sqlExprArgs.add(stack.pop());
} else if (argExpr instanceof DyadicExpression) {
// Evaluate using this evaluator
argExpr.evaluate(this);
sqlExprArgs.add(stack.pop());
} else if (argExpr instanceof VariableExpression) {
processVariableExpression((VariableExpression) argExpr);
sqlExprArgs.add(stack.pop());
} else if (argExpr instanceof CaseExpression) {
processCaseExpression((CaseExpression) argExpr);
sqlExprArgs.add(stack.pop());
} else {
throw new NucleusException("Dont currently support invoke expression argument " + argExpr);
}
}
if (operation.equals("INDEX")) {
// Special case of index expression
List<Expression> indexArgs = expr.getArguments();
if (indexArgs == null || indexArgs.size() > 1) {
throw new NucleusException("Can only use INDEX with single argument");
}
PrimaryExpression indexExpr = (PrimaryExpression) indexArgs.get(0);
String joinAlias = indexExpr.getId();
String collExprName = joinAlias;
if (explicitJoinPrimaryByAlias != null) {
collExprName = explicitJoinPrimaryByAlias.get(joinAlias);
if (collExprName == null) {
throw new NucleusException("Unable to locate primary expression for alias " + joinAlias);
}
}
// Find an expression for the collection field
List<String> tuples = new ArrayList<>();
StringTokenizer primTokenizer = new StringTokenizer(collExprName, ".");
while (primTokenizer.hasMoreTokens()) {
String token = primTokenizer.nextToken();
tuples.add(token);
}
PrimaryExpression collPrimExpr = new PrimaryExpression(tuples);
processPrimaryExpression(collPrimExpr);
SQLExpression collSqlExpr = stack.pop();
sqlExprArgs.add(collSqlExpr);
}
}
// Invoke the method
SQLExpression sqlExpr = null;
if (invokedSqlExpr instanceof org.datanucleus.store.rdbms.sql.expression.SubqueryExpression) {
if (operation.equalsIgnoreCase("isEmpty")) {
// Special case of {subquery}.isEmpty(), equates to "NOT EXISTS (subquery)"
org.datanucleus.store.rdbms.sql.expression.SubqueryExpression subquerySqlExpr = (org.datanucleus.store.rdbms.sql.expression.SubqueryExpression) invokedSqlExpr;
SQLStatement subStmt = subquerySqlExpr.getSubqueryStatement();
SQLExpression subqueryNotExistsExpr = new BooleanSubqueryExpression(stmt, "EXISTS", subStmt).not();
stack.push(subqueryNotExistsExpr);
return subqueryNotExistsExpr;
} else if (operation.equalsIgnoreCase("size")) {
// {subquery}.size() should simply be changed to have a subquery of "SELECT COUNT(*) FROM ..."
throw new NucleusUserException("Attempt to invoke method `" + operation + "` on Subquery. This is not supported. Change the subquery to return COUNT() instead.");
}
throw new NucleusUserException("Attempt to invoke method `" + operation + "` on Subquery. This is not supported");
}
if (invokedSqlExpr != null) {
sqlExpr = invokedSqlExpr.invoke(operation, sqlExprArgs);
} else {
sqlExpr = exprFactory.invokeMethod(stmt, null, operation, null, sqlExprArgs);
}
stack.push(sqlExpr);
return sqlExpr;
}
use of org.datanucleus.store.rdbms.sql.expression.NullLiteral in project datanucleus-rdbms by datanucleus.
the class UnionStatementGenerator method getSelectStatementForCandidate.
/**
* Convenience method to return the SelectStatement for a particular class.
* Returns a SelectStatement with primaryTable of the "candidateTable", and which joins to the table of the class (if different).
* @param className The class name to generate the statement for
* @param ec ExecutionContext
* @return The SelectStatement
*/
protected SelectStatement getSelectStatementForCandidate(String className, ExecutionContext ec) {
DatastoreClass table = storeMgr.getDatastoreClass(className, clr);
if (table == null) {
// Subclass-table, so persisted into table(s) of subclasses
NucleusLogger.GENERAL.info("Generation of statement to retrieve objects of type " + candidateType.getName() + (includeSubclasses ? " including subclasses " : "") + " attempted to include " + className + " but this has no table of its own; ignored");
// TODO Cater for use of single subclass-table
return null;
}
// Start from an SQL SELECT of the candidate table
SelectStatement stmt = new SelectStatement(parentStmt, storeMgr, candidateTable, candidateTableAlias, candidateTableGroupName);
stmt.setClassLoaderResolver(clr);
stmt.setCandidateClassName(className);
String tblGroupName = stmt.getPrimaryTable().getGroupName();
if (table != candidateTable) {
// INNER JOIN from the root candidate table to this candidates table
JavaTypeMapping candidateIdMapping = candidateTable.getIdMapping();
JavaTypeMapping tableIdMapping = table.getIdMapping();
SQLTable tableSqlTbl = stmt.join(JoinType.INNER_JOIN, null, candidateIdMapping, table, null, tableIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
tblGroupName = tableSqlTbl.getGroupName();
}
// Add any discriminator restriction in this table for the specified class
// Caters for the case where we have more than 1 class stored in this table
SQLExpressionFactory factory = storeMgr.getSQLExpressionFactory();
JavaTypeMapping discriminatorMapping = table.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, false);
DiscriminatorMetaData discriminatorMetaData = table.getDiscriminatorMetaData();
if (discriminatorMapping != null && discriminatorMetaData.getStrategy() != DiscriminatorStrategy.NONE) {
// Restrict to valid discriminator values where we have a discriminator specified on this table
AbstractClassMetaData targetCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(className, clr);
SQLExpression discExpr = factory.newExpression(stmt, stmt.getPrimaryTable(), discriminatorMapping);
SQLExpression discValExpr = factory.newLiteral(stmt, discriminatorMapping, targetCmd.getDiscriminatorValue());
stmt.whereAnd(discExpr.eq(discValExpr), false);
}
JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
if (multitenancyMapping != null) {
// Multi-tenancy restriction
AbstractClassMetaData cmd = table.getClassMetaData();
SQLTable tenantSqlTbl = stmt.getTable(multitenancyMapping.getTable(), tblGroupName);
SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, tenantSqlTbl, multitenancyMapping);
SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, cmd));
stmt.whereAnd(tenantExpr.eq(tenantVal), true);
}
JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
if (softDeleteMapping != null && !hasOption(OPTION_INCLUDE_SOFT_DELETES)) {
// Soft-delete restriction
SQLTable softDeleteSqlTbl = stmt.getTable(softDeleteMapping.getTable(), tblGroupName);
SQLExpression softDeleteExpr = stmt.getSQLExpressionFactory().newExpression(stmt, softDeleteSqlTbl, softDeleteMapping);
SQLExpression softDeleteVal = stmt.getSQLExpressionFactory().newLiteral(stmt, softDeleteMapping, Boolean.FALSE);
stmt.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
}
// Eliminate any subclasses (catered for in separate UNION statement)
Iterator<String> subIter = storeMgr.getSubClassesForClass(className, false, clr).iterator();
while (subIter.hasNext()) {
String subclassName = subIter.next();
DatastoreClass[] subclassTables = null;
DatastoreClass subclassTable = storeMgr.getDatastoreClass(subclassName, clr);
if (subclassTable == null) {
AbstractClassMetaData targetSubCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(subclassName, clr);
AbstractClassMetaData[] targetSubCmds = storeMgr.getClassesManagingTableForClass(targetSubCmd, clr);
subclassTables = new DatastoreClass[targetSubCmds.length];
for (int i = 0; i < targetSubCmds.length; i++) {
subclassTables[i] = storeMgr.getDatastoreClass(targetSubCmds[i].getFullClassName(), clr);
}
} else {
subclassTables = new DatastoreClass[1];
subclassTables[0] = subclassTable;
}
for (int i = 0; i < subclassTables.length; i++) {
if (subclassTables[i] != table) {
// Subclass of our class is stored in different table to the candidate so exclude it
// Adds FROM clause of "LEFT OUTER JOIN {subTable} ON ..."
// and WHERE clause of "{subTable}.ID = NULL"
JavaTypeMapping tableIdMapping = table.getIdMapping();
JavaTypeMapping subclassIdMapping = subclassTables[i].getIdMapping();
SQLTable sqlTableSubclass = stmt.join(JoinType.LEFT_OUTER_JOIN, null, tableIdMapping, subclassTables[i], null, subclassIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
SQLExpression subclassIdExpr = factory.newExpression(stmt, sqlTableSubclass, subclassIdMapping);
SQLExpression nullExpr = new NullLiteral(stmt, null, null, null);
stmt.whereAnd(subclassIdExpr.eq(nullExpr), false);
}
}
}
if (hasOption(OPTION_SELECT_DN_TYPE)) {
// Add SELECT of dummy metadata for this class ("'mydomain.MyClass' AS DN_TYPE")
addTypeSelectForClass(stmt, className);
}
return stmt;
}
use of org.datanucleus.store.rdbms.sql.expression.NullLiteral in project datanucleus-rdbms by datanucleus.
the class UnionStatementGenerator method getSQLStatementForCandidateViaJoin.
/**
* Convenience method to return the SQLStatement for a particular class selecting a join table.
* Returns a SQLStatement with primaryTable of the "joinTable", and which joins to the table of the class.
* @param className The class name to generate the statement for
* @return The SQLStatement
*/
protected SelectStatement getSQLStatementForCandidateViaJoin(String className) {
DatastoreClass table = storeMgr.getDatastoreClass(className, clr);
if (table == null) {
// TODO Cater for use of single subclass-table
throw new NucleusException("We do not currently support a UNION statement for class=" + className + " since it has no table of its own");
}
// Start from an SQL SELECT of the join table
SelectStatement stmt = new SelectStatement(parentStmt, storeMgr, joinTable, joinTableAlias, candidateTableGroupName);
stmt.setClassLoaderResolver(clr);
stmt.setCandidateClassName(className);
// INNER/LEFT OUTER JOIN from the join table to the root candidate table
// If we allow nulls we do a left outer join here, otherwise an inner join
SQLTable candidateSQLTable = null;
if (candidateTable != null) {
// We have a root candidate table, so join to that
JavaTypeMapping candidateIdMapping = candidateTable.getIdMapping();
if (hasOption(OPTION_ALLOW_NULLS)) {
// Put element table in same table group since all relates to the elements
candidateSQLTable = stmt.join(JoinType.LEFT_OUTER_JOIN, null, joinElementMapping, candidateTable, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
} else {
// Put element table in same table group since all relates to the elements
candidateSQLTable = stmt.join(JoinType.INNER_JOIN, null, joinElementMapping, candidateTable, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
}
// Join the root candidate table to this particular candidate table
if (table != candidateTable) {
// INNER JOIN from the root candidate table to this candidates table
stmt.join(JoinType.INNER_JOIN, candidateSQLTable, candidateIdMapping, table, null, table.getIdMapping(), null, stmt.getPrimaryTable().getGroupName(), true);
}
} else {
// No root candidate table, so join direct to this candidate
JavaTypeMapping candidateIdMapping = table.getIdMapping();
if (hasOption(OPTION_ALLOW_NULLS)) {
// Put element table in same table group since all relates to the elements
candidateSQLTable = stmt.join(JoinType.LEFT_OUTER_JOIN, null, joinElementMapping, table, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
} else {
// Put element table in same table group since all relates to the elements
candidateSQLTable = stmt.join(JoinType.INNER_JOIN, null, joinElementMapping, table, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
}
}
// Add any discriminator restriction in the table for the specified class
// Caters for the case where we have more than 1 class stored in this table
SQLExpressionFactory factory = storeMgr.getSQLExpressionFactory();
JavaTypeMapping discriminatorMapping = table.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, false);
DiscriminatorMetaData discriminatorMetaData = table.getDiscriminatorMetaData();
if (discriminatorMapping != null && discriminatorMetaData.getStrategy() != DiscriminatorStrategy.NONE) {
// Restrict to valid discriminator value where we have a discriminator specified on this table
BooleanExpression discExpr = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, className, discriminatorMetaData, discriminatorMapping, stmt.getPrimaryTable(), clr);
stmt.whereAnd(discExpr, false);
}
// Eliminate any subclasses (catered for in separate UNION statement)
Iterator<String> subIter = storeMgr.getSubClassesForClass(className, false, clr).iterator();
while (subIter.hasNext()) {
String subclassName = subIter.next();
DatastoreClass[] subclassTables = null;
DatastoreClass subclassTable = storeMgr.getDatastoreClass(subclassName, clr);
if (subclassTable == null) {
AbstractClassMetaData targetSubCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(subclassName, clr);
AbstractClassMetaData[] targetSubCmds = storeMgr.getClassesManagingTableForClass(targetSubCmd, clr);
subclassTables = new DatastoreClass[targetSubCmds.length];
for (int i = 0; i < targetSubCmds.length; i++) {
subclassTables[i] = storeMgr.getDatastoreClass(targetSubCmds[i].getFullClassName(), clr);
}
} else {
subclassTables = new DatastoreClass[1];
subclassTables[0] = subclassTable;
}
for (int i = 0; i < subclassTables.length; i++) {
if (subclassTables[i] != table) {
// Subclass of our class is stored in different table to the candidate so exclude it
// Adds FROM clause of "LEFT OUTER JOIN {subTable} ON ..."
// and WHERE clause of "{subTable}.ID = NULL"
JavaTypeMapping subclassIdMapping = subclassTables[i].getIdMapping();
SQLTable sqlTableSubclass = stmt.join(JoinType.LEFT_OUTER_JOIN, null, joinElementMapping, subclassTables[i], null, subclassIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
SQLExpression subclassIdExpr = factory.newExpression(stmt, sqlTableSubclass, subclassIdMapping);
SQLExpression nullExpr = new NullLiteral(stmt, null, null, null);
stmt.whereAnd(subclassIdExpr.eq(nullExpr), false);
}
}
}
if (hasOption(OPTION_SELECT_DN_TYPE)) {
// Add SELECT of dummy metadata for this class ("'mydomain.MyClass' AS DN_TYPE")
addTypeSelectForClass(stmt, className);
}
return stmt;
}
use of org.datanucleus.store.rdbms.sql.expression.NullLiteral in project datanucleus-rdbms by datanucleus.
the class MapGetMethod 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 || args.size() > 1) {
throw new NucleusException(Localiser.msg("060016", "get", "MapExpression", 1));
}
MapExpression mapExpr = (MapExpression) expr;
SQLExpression keyValExpr = args.get(0);
if (keyValExpr instanceof UnboundExpression) {
// TODO Add support for unbound variables (as per CollectionContains)
throw new NucleusException("Dont currently support binding of unbound variables using Map.get");
}
if (mapExpr instanceof MapLiteral && keyValExpr instanceof SQLLiteral) {
MapLiteral lit = (MapLiteral) expr;
if (lit.getValue() == null) {
return new NullLiteral(stmt, null, null, null);
}
return lit.getKeyLiteral().invoke("get", args);
} else if (mapExpr instanceof MapLiteral) {
// MapLiteral.get(SQLExpression)
throw new NucleusUserException("We do not support MapLiteral.get(SQLExpression) since SQL doesnt allow such constructs");
} else {
if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.FILTER || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.ORDERING) {
return getAsInnerJoin(stmt, mapExpr, keyValExpr);
} else if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.RESULT || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.HAVING) {
return getAsSubquery(stmt, mapExpr, keyValExpr);
}
throw new NucleusException("Map.get() is not supported for " + mapExpr + " with argument " + keyValExpr + " for query component " + stmt.getQueryGenerator().getCompilationComponent());
}
}
use of org.datanucleus.store.rdbms.sql.expression.NullLiteral in project datanucleus-rdbms by datanucleus.
the class MathAcosMethod 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 ignore, List<SQLExpression> args) {
if (args == null || args.size() == 0) {
throw new NucleusUserException("Cannot invoke Math.acos without an argument");
}
SQLExpression expr = args.get(0);
if (expr == null) {
return new NullLiteral(stmt, null, null, null);
} else if (expr instanceof SQLLiteral) {
if (expr instanceof ByteLiteral) {
int originalValue = ((BigInteger) ((ByteLiteral) expr).getValue()).intValue();
BigInteger absValue = new BigInteger(String.valueOf(Math.acos(originalValue)));
return new ByteLiteral(stmt, expr.getJavaTypeMapping(), absValue, null);
} else if (expr instanceof IntegerLiteral) {
int originalValue = ((Number) ((IntegerLiteral) expr).getValue()).intValue();
Double absValue = new Double(Math.acos(originalValue));
return new FloatingPointLiteral(stmt, expr.getJavaTypeMapping(), absValue, null);
} else if (expr instanceof FloatingPointLiteral) {
double originalValue = ((BigDecimal) ((FloatingPointLiteral) expr).getValue()).doubleValue();
Double absValue = new Double(Math.acos(originalValue));
return new FloatingPointLiteral(stmt, expr.getJavaTypeMapping(), absValue, null);
}
throw new IllegalExpressionOperationException("Math.acos()", expr);
} else {
// Relay to the equivalent "acos(expr)" function
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
return exprFactory.invokeMethod(stmt, null, "acos", null, args);
}
}
Aggregations