use of org.datanucleus.store.rdbms.sql.expression.NumericExpression 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);
}
}
use of org.datanucleus.store.rdbms.sql.expression.NumericExpression in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method processBitOrExpression.
/* (non-Javadoc)
* @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processBitOrExpression(org.datanucleus.query.expression.Expression)
*/
@Override
protected Object processBitOrExpression(Expression expr) {
SQLExpression rightExpr = stack.pop();
SQLExpression leftExpr = stack.pop();
if (rightExpr instanceof BooleanExpression && leftExpr instanceof BooleanExpression) {
// Handle as Boolean logical OR
stack.push(leftExpr);
stack.push(rightExpr);
return processOrExpression(expr);
} else if (rightExpr instanceof NumericExpression && leftExpr instanceof NumericExpression) {
if (storeMgr.getDatastoreAdapter().supportsOption(DatastoreAdapter.OPERATOR_BITWISE_OR)) {
SQLExpression bitExpr = new NumericExpression(leftExpr, Expression.OP_BIT_OR, rightExpr).encloseInParentheses();
stack.push(bitExpr);
return bitExpr;
}
}
// TODO Support BITWISE OR for more cases
throw new NucleusUserException("Operation BITWISE OR is not supported for " + leftExpr + " and " + rightExpr + " is not supported by this datastore");
}
use of org.datanucleus.store.rdbms.sql.expression.NumericExpression in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method compileUpdate.
/**
* Method to compile the result clause of the query into the SQLStatement.
* @param stmt UPDATE statement
*/
protected void compileUpdate(UpdateStatement stmt) {
if (compilation.getExprUpdate() != null) {
// Update statement, so generate update expression(s)
compileComponent = CompilationComponent.UPDATE;
Expression[] updateExprs = compilation.getExprUpdate();
SQLExpression[] updateSqlExprs = new SQLExpression[updateExprs.length];
// TODO If the field being set is in a different table omit it
boolean performingUpdate = false;
for (int i = 0; i < updateExprs.length; i++) {
// "field = value"
DyadicExpression updateExpr = (DyadicExpression) updateExprs[i];
// Left-side has to be PrimaryExpression
SQLExpression leftSqlExpr = null;
if (updateExpr.getLeft() instanceof PrimaryExpression) {
processPrimaryExpression((PrimaryExpression) updateExpr.getLeft());
leftSqlExpr = stack.pop();
if (leftSqlExpr.getSQLTable() != stmt.getPrimaryTable()) {
// Set left to null to signify that it is not applicable to the table of this UPDATE statement
leftSqlExpr = null;
}
} else {
throw new NucleusException("Dont currently support update clause containing left expression of type " + updateExpr.getLeft());
}
if (leftSqlExpr != null) {
if (!stmt.getDatastoreAdapter().supportsOption(DatastoreAdapter.UPDATE_STATEMENT_ALLOW_TABLE_ALIAS_IN_SET_CLAUSE)) {
// This datastore doesn't allow table alias in UPDATE SET clause, so just use column name
for (int j = 0; j < leftSqlExpr.getNumberOfSubExpressions(); j++) {
ColumnExpression colExpr = leftSqlExpr.getSubExpression(j);
colExpr.setOmitTableFromString(true);
}
}
performingUpdate = true;
SQLExpression rightSqlExpr = null;
if (updateExpr.getRight() instanceof Literal) {
processLiteral((Literal) updateExpr.getRight());
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof ParameterExpression) {
ParameterExpression paramExpr = (ParameterExpression) updateExpr.getRight();
paramMappingForName.put(paramExpr.getId(), leftSqlExpr.getJavaTypeMapping());
processParameterExpression(paramExpr);
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof PrimaryExpression) {
processPrimaryExpression((PrimaryExpression) updateExpr.getRight());
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof DyadicExpression) {
updateExpr.getRight().evaluate(this);
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof CaseExpression) {
CaseExpression caseExpr = (CaseExpression) updateExpr.getRight();
processCaseExpression(caseExpr, leftSqlExpr);
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof VariableExpression) {
// Subquery?
processVariableExpression((VariableExpression) updateExpr.getRight());
rightSqlExpr = stack.pop();
if (rightSqlExpr instanceof UnboundExpression) {
// TODO Support whatever this is
throw new NucleusException("Found UnboundExpression in UPDATE clause!");
}
} else {
throw new NucleusException("Dont currently support update clause containing right expression of type " + updateExpr.getRight());
}
if (rightSqlExpr != null) {
updateSqlExprs[i] = leftSqlExpr.eq(rightSqlExpr);
}
}
}
if (candidateCmd.isVersioned() && options.contains(OPTION_BULK_UPDATE_VERSION)) {
SQLExpression updateSqlExpr = null;
ClassTable table = (ClassTable) stmt.getPrimaryTable().getTable();
JavaTypeMapping verMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, true);
ClassTable verTable = table.getTableManagingMapping(verMapping);
if (verTable == stmt.getPrimaryTable().getTable()) {
VersionMetaData vermd = candidateCmd.getVersionMetaDataForClass();
if (vermd.getStrategy() == VersionStrategy.VERSION_NUMBER) {
// Increment the version
SQLTable verSqlTbl = stmt.getTable(verTable, stmt.getPrimaryTable().getGroupName());
SQLExpression verExpr = new NumericExpression(stmt, verSqlTbl, verMapping);
SQLExpression incrExpr = verExpr.add(new IntegerLiteral(stmt, exprFactory.getMappingForType(Integer.class, false), Integer.valueOf(1), null));
updateSqlExpr = verExpr.eq(incrExpr);
SQLExpression[] oldArray = updateSqlExprs;
updateSqlExprs = new SQLExpression[oldArray.length + 1];
System.arraycopy(oldArray, 0, updateSqlExprs, 0, oldArray.length);
updateSqlExprs[oldArray.length] = updateSqlExpr;
performingUpdate = true;
} else if (vermd.getStrategy() == VersionStrategy.DATE_TIME) {
// Set version to the time of update
SQLTable verSqlTbl = stmt.getTable(verTable, stmt.getPrimaryTable().getGroupName());
SQLExpression verExpr = new NumericExpression(stmt, verSqlTbl, verMapping);
Object newVersion = ec.getLockManager().getNextVersion(vermd, null);
JavaTypeMapping valMapping = exprFactory.getMappingForType(newVersion.getClass(), false);
SQLExpression valExpr = new TemporalLiteral(stmt, valMapping, newVersion, null);
updateSqlExpr = verExpr.eq(valExpr);
SQLExpression[] oldArray = updateSqlExprs;
updateSqlExprs = new SQLExpression[oldArray.length + 1];
System.arraycopy(oldArray, 0, updateSqlExprs, 0, oldArray.length);
updateSqlExprs[oldArray.length] = updateSqlExpr;
performingUpdate = true;
}
}
}
if (performingUpdate) {
// Only set the updates component of the SQLStatement if anything to update in this table
stmt.setUpdates(updateSqlExprs);
}
}
compileComponent = null;
}
use of org.datanucleus.store.rdbms.sql.expression.NumericExpression in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method processCaseExpression.
protected Object processCaseExpression(CaseExpression expr, SQLExpression typeExpr) {
processingCase = true;
try {
List<ExpressionPair> conditions = expr.getConditions();
Iterator<ExpressionPair> whenExprIter = conditions.iterator();
SQLExpression[] whenSqlExprs = new SQLExpression[conditions.size()];
SQLExpression[] actionSqlExprs = new SQLExpression[conditions.size()];
boolean numericCase = false;
boolean booleanCase = false;
boolean stringCase = false;
boolean typeSet = false;
if (typeExpr != null) {
if (typeExpr instanceof NumericExpression) {
numericCase = true;
typeSet = true;
} else if (typeExpr instanceof BooleanExpression) {
booleanCase = true;
typeSet = true;
} else if (typeExpr instanceof StringExpression) {
stringCase = true;
typeSet = true;
}
}
int i = 0;
while (whenExprIter.hasNext()) {
ExpressionPair pair = whenExprIter.next();
Expression whenExpr = pair.getWhenExpression();
whenExpr.evaluate(this);
whenSqlExprs[i] = stack.pop();
if (!(whenSqlExprs[i] instanceof BooleanExpression)) {
throw new QueryCompilerSyntaxException("IF/ELSE conditional expression should return boolean but doesn't : " + expr);
}
Expression actionExpr = pair.getActionExpression();
actionExpr.evaluate(this);
actionSqlExprs[i] = stack.pop();
if (!typeSet) {
if (actionSqlExprs[i] instanceof NumericExpression) {
numericCase = true;
typeSet = true;
} else if (actionSqlExprs[i] instanceof BooleanExpression) {
booleanCase = true;
typeSet = true;
} else if (actionSqlExprs[i] instanceof StringExpression) {
stringCase = true;
typeSet = true;
}
}
i++;
}
Expression elseExpr = expr.getElseExpression();
elseExpr.evaluate(this);
SQLExpression elseActionSqlExpr = stack.pop();
// Check that all action sql expressions are consistent
for (int j = 1; j < actionSqlExprs.length; j++) {
if (!checkCaseExpressionsConsistent(actionSqlExprs[0], actionSqlExprs[j])) {
throw new QueryCompilerSyntaxException("IF/ELSE action expression " + actionSqlExprs[j] + " is of different type to first action " + actionSqlExprs[0] + " - must be consistent");
}
}
if (!checkCaseExpressionsConsistent(actionSqlExprs[0], elseActionSqlExpr)) {
throw new QueryCompilerSyntaxException("IF/ELSE action expression " + elseActionSqlExpr + " is of different type to first action " + actionSqlExprs[0] + " - must be consistent");
}
SQLExpression caseSqlExpr = null;
if (numericCase) {
caseSqlExpr = new org.datanucleus.store.rdbms.sql.expression.CaseNumericExpression(whenSqlExprs, actionSqlExprs, elseActionSqlExpr);
} else if (booleanCase) {
caseSqlExpr = new org.datanucleus.store.rdbms.sql.expression.CaseBooleanExpression(whenSqlExprs, actionSqlExprs, elseActionSqlExpr);
} else if (stringCase) {
caseSqlExpr = new org.datanucleus.store.rdbms.sql.expression.CaseStringExpression(whenSqlExprs, actionSqlExprs, elseActionSqlExpr);
} else {
caseSqlExpr = new org.datanucleus.store.rdbms.sql.expression.CaseExpression(whenSqlExprs, actionSqlExprs, elseActionSqlExpr);
}
stack.push(caseSqlExpr);
return caseSqlExpr;
} finally {
processingCase = false;
}
}
use of org.datanucleus.store.rdbms.sql.expression.NumericExpression in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method processBitXorExpression.
/* (non-Javadoc)
* @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processBitXorExpression(org.datanucleus.query.expression.Expression)
*/
@Override
protected Object processBitXorExpression(Expression expr) {
SQLExpression rightExpr = stack.pop();
SQLExpression leftExpr = stack.pop();
if (rightExpr instanceof BooleanExpression && leftExpr instanceof BooleanExpression) {
// Handle as Boolean logical OR
stack.push(leftExpr);
stack.push(rightExpr);
return processOrExpression(expr);
} else if (rightExpr instanceof NumericExpression && leftExpr instanceof NumericExpression) {
if (storeMgr.getDatastoreAdapter().supportsOption(DatastoreAdapter.OPERATOR_BITWISE_XOR)) {
SQLExpression bitExpr = new NumericExpression(leftExpr, Expression.OP_BIT_XOR, rightExpr).encloseInParentheses();
stack.push(bitExpr);
return bitExpr;
}
}
// TODO Support BITWISE XOR for more cases
throw new NucleusUserException("Operation BITWISE XOR is not supported for " + leftExpr + " and " + rightExpr + " is not supported by this datastore");
}
Aggregations