use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class ListGetMethod 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", "CollectionExpression", 1));
}
CollectionExpression listSqlExpr = (CollectionExpression) expr;
AbstractMemberMetaData mmd = listSqlExpr.getJavaTypeMapping().getMemberMetaData();
if (mmd == null) {
// TODO Cater for the List being an input parameter
throw new NucleusException(Localiser.msg("060020", "indexOf", listSqlExpr.getClass().getName()));
}
if (!List.class.isAssignableFrom(mmd.getType())) {
throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the field is not a List!");
} else if (mmd.getOrderMetaData() != null && !mmd.getOrderMetaData().isIndexedList()) {
throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the field is not an 'indexed' List!");
}
SQLExpression idxExpr = args.get(0);
if (idxExpr instanceof SQLLiteral) {
if (!(((SQLLiteral) idxExpr).getValue() instanceof Number)) {
throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the index is not a numeric literal so not yet supported");
}
} else {
throw new UnsupportedOperationException("Query contains " + expr + ".get(int) yet the index is not a numeric literal so not yet supported");
}
if (listSqlExpr instanceof CollectionLiteral && idxExpr instanceof SQLLiteral) {
CollectionLiteral lit = (CollectionLiteral) expr;
if (lit.getValue() == null) {
return new NullLiteral(stmt, null, null, null);
}
return lit.invoke("get", args);
}
if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.FILTER) {
return getAsInnerJoin(stmt, listSqlExpr, idxExpr);
} else if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.ORDERING || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.RESULT || stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.HAVING) {
return getAsSubquery(stmt, listSqlExpr, idxExpr);
}
throw new NucleusException("List.get() is not supported for " + listSqlExpr + " with argument " + idxExpr + " for query component " + stmt.getQueryGenerator().getCompilationComponent());
}
use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class CoalesceFunction 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) {
// Find expression type that this handles - all expressions need to be consistent in our implementation
Class exprType = null;
Class cls = null;
int clsLevel = 0;
for (int i = 0; i < args.size(); i++) {
SQLExpression argExpr = args.get(i);
if (exprType == null) {
if (argExpr instanceof NumericExpression) {
exprType = NumericExpression.class;
cls = Integer.class;
} else if (argExpr instanceof StringExpression) {
exprType = StringExpression.class;
cls = String.class;
} else if (argExpr instanceof TemporalExpression) {
exprType = TemporalExpression.class;
cls = argExpr.getJavaTypeMapping().getJavaType();
} else {
exprType = argExpr.getClass();
cls = argExpr.getJavaTypeMapping().getJavaType();
}
} else {
if (!exprType.isAssignableFrom(argExpr.getClass())) {
throw new NucleusUserException("COALESCE invocation first argument of type " + exprType.getName() + " yet subsequent argument of type " + argExpr.getClass().getName());
}
}
if (exprType == NumericExpression.class) {
// Priority order is Double, Float, BigDecimal, BigInteger, Long, Integer
Class argType = argExpr.getJavaTypeMapping().getJavaType();
if (clsLevel < 5 && (argType == double.class || argType == Double.class)) {
cls = Double.class;
clsLevel = 5;
} else if (clsLevel < 4 && (argType == float.class || argType == Float.class)) {
cls = Float.class;
clsLevel = 4;
} else if (clsLevel < 3 && argType == BigDecimal.class) {
cls = BigDecimal.class;
clsLevel = 3;
} else if (clsLevel < 2 && argType == BigInteger.class) {
cls = BigInteger.class;
clsLevel = 2;
} else if (clsLevel < 1 && (argType == long.class || argType == Long.class)) {
cls = Long.class;
clsLevel = 1;
}
}
}
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
if (exprType == NumericExpression.class) {
return new NumericExpression(stmt, exprFactory.getMappingForType(cls, true), "COALESCE", args);
} else if (exprType == StringExpression.class) {
return new StringExpression(stmt, exprFactory.getMappingForType(cls, true), "COALESCE", args);
} else if (exprType == TemporalExpression.class) {
return new TemporalExpression(stmt, exprFactory.getMappingForType(cls, true), "COALESCE", args);
} else {
return new ObjectExpression(stmt, exprFactory.getMappingForType(cls, true), "COALESCE", args);
}
}
throw new NucleusException(Localiser.msg("060002", "COALESCE", expr));
}
use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class CurrentTimeFunction 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) {
// Assume that we have something like "CURRENT_DATE()"
SQLExpression dateExpr = new TemporalExpression(stmt, stmt.getSQLExpressionFactory().getMappingForType(getClassForMapping(), true), getFunctionName(), args);
// Update the SQL manually since the default is to add brackets after the name
dateExpr.toSQLText().clearStatement();
dateExpr.toSQLText().append(getFunctionName());
return dateExpr;
}
throw new NucleusException(Localiser.msg("060002", getFunctionName(), expr));
}
use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class ListIndexOfMethod 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) {
SQLExpression collSqlExpr = null;
SQLExpression elemSqlExpr = null;
if (expr != null) {
if (args == null || args.size() == 0 || args.size() > 1) {
throw new NucleusException(Localiser.msg("060016", "indexOf", "CollectionExpression", 1));
}
elemSqlExpr = args.get(0);
collSqlExpr = expr;
} else {
if (args == null || args.size() != 2) {
throw new NucleusException(Localiser.msg("060016", "indexOf", "CollectionExpression", 2));
}
elemSqlExpr = args.get(0);
collSqlExpr = args.get(1);
}
AbstractMemberMetaData mmd = collSqlExpr.getJavaTypeMapping().getMemberMetaData();
if (mmd == null) {
// TODO Cater for the List being an input parameter
throw new NucleusException(Localiser.msg("060020", "indexOf", collSqlExpr.getClass().getName()));
}
if (!mmd.hasCollection()) {
throw new NucleusException("List.indexOf expression for field " + mmd.getFullFieldName() + " does not represent a collection!");
} else if (!mmd.getOrderMetaData().isIndexedList()) {
throw new NucleusException("List.indexOf expression for field " + mmd.getFullFieldName() + " does not represent an indexed list!");
}
JavaTypeMapping orderMapping = null;
SQLTable orderTable = null;
Table joinTbl = stmt.getRDBMSManager().getTable(mmd);
if (joinTbl != null) {
// 1-N via join table
CollectionTable collTable = (CollectionTable) joinTbl;
orderTable = stmt.getTableForDatastoreContainer(collTable);
if (orderTable == null) {
// TODO Allow control over the join type? the alias?
orderTable = stmt.join(JoinType.LEFT_OUTER_JOIN, collSqlExpr.getSQLTable(), collSqlExpr.getSQLTable().getTable().getIdMapping(), collTable, null, collTable.getOwnerMapping(), null, null);
}
orderMapping = collTable.getOrderMapping();
} else {
// 1-N via FK
orderTable = elemSqlExpr.getSQLTable();
orderMapping = ((ClassTable) elemSqlExpr.getSQLTable().getTable()).getExternalMapping(mmd, MappingType.EXTERNAL_INDEX);
}
return new NumericExpression(stmt, orderTable, orderMapping);
}
use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class ArrayContainsMethod 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() != 1) {
throw new NucleusException("Incorrect arguments for Array.contains(SQLExpression)");
}
ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
ArrayExpression arrExpr = (ArrayExpression) expr;
SQLExpression elemExpr = args.get(0);
if (elemExpr.isParameter()) {
// Element is a parameter so make sure its type is set
AbstractMemberMetaData mmd = arrExpr.getJavaTypeMapping().getMemberMetaData();
if (mmd != null) {
stmt.getQueryGenerator().bindParameter(elemExpr.getParameterName(), mmd.getType().getComponentType());
}
}
if (expr instanceof ArrayLiteral) {
if (elemExpr instanceof UnboundExpression) {
Class elemCls = clr.classForName(arrExpr.getJavaTypeMapping().getType()).getComponentType();
elemExpr = stmt.getQueryGenerator().bindVariable((UnboundExpression) elemExpr, elemCls);
}
ArrayLiteral lit = (ArrayLiteral) expr;
Object array = lit.getValue();
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
if (array == null || Array.getLength(array) == 0) {
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
}
if (arrExpr.isParameter()) {
stmt.getQueryGenerator().useParameterExpressionAsLiteral((ArrayLiteral) arrExpr);
}
boolean useInExpression = false;
List<SQLExpression> collElementExprs = lit.getElementExpressions();
if (collElementExprs != null && !collElementExprs.isEmpty()) {
// Make sure the the collection element(s) are compatible with the elemExpr
boolean incompatible = true;
Class elemtype = clr.classForName(elemExpr.getJavaTypeMapping().getType());
Iterator<SQLExpression> collElementExprIter = collElementExprs.iterator();
while (collElementExprIter.hasNext()) {
SQLExpression collElementExpr = collElementExprIter.next();
Class collElemType = clr.classForName(collElementExpr.getJavaTypeMapping().getType());
if (elementTypeCompatible(elemtype, collElemType)) {
incompatible = false;
break;
}
}
if (incompatible) {
// The provided element type isn't assignable to any of the input collection elements!
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
}
// Check if we should compare using an "IN (...)" expression
SQLExpression collElementExpr = collElementExprs.get(0);
if (collElementExpr instanceof StringExpression || collElementExpr instanceof NumericExpression || collElementExpr instanceof TemporalExpression || collElementExpr instanceof CharacterExpression || collElementExpr instanceof EnumExpression) {
useInExpression = true;
}
}
if (useInExpression) {
// Return "elem IN (val1, val2, ...)"
SQLExpression[] exprs = (collElementExprs != null ? collElementExprs.toArray(new SQLExpression[collElementExprs.size()]) : null);
return new InExpression(elemExpr, exprs);
}
// TODO If elemExpr is a parameter and collExpr is derived from a parameter ?
BooleanExpression bExpr = null;
List<SQLExpression> elementExprs = lit.getElementExpressions();
for (int i = 0; i < elementExprs.size(); i++) {
SQLExpression arrElemExpr = elementExprs.get(i);
if (bExpr == null) {
bExpr = arrElemExpr.eq(elemExpr);
} else {
bExpr = bExpr.ior(arrElemExpr.eq(elemExpr));
}
}
if (bExpr != null) {
bExpr.encloseInParentheses();
}
return bExpr;
} else if (arrExpr.getElementExpressions() != null) {
if (elemExpr instanceof UnboundExpression) {
Class elemCls = clr.classForName(arrExpr.getJavaTypeMapping().getType()).getComponentType();
elemExpr = stmt.getQueryGenerator().bindVariable((UnboundExpression) elemExpr, elemCls);
}
// Array defined in query that has some expressions for elements, so just do OR chain
BooleanExpression bExpr = null;
List<SQLExpression> elementExprs = arrExpr.getElementExpressions();
for (int i = 0; i < elementExprs.size(); i++) {
SQLExpression arrElemExpr = elementExprs.get(i);
if (bExpr == null) {
bExpr = arrElemExpr.eq(elemExpr);
} else {
bExpr = bExpr.ior(arrElemExpr.eq(elemExpr));
}
}
if (bExpr != null) {
bExpr.encloseInParentheses();
}
return bExpr;
} else {
// TODO Support inner join variant
return containsAsSubquery(stmt, arrExpr, elemExpr);
}
}
Aggregations