use of org.datanucleus.store.rdbms.sql.expression.SQLExpression in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method processLtExpression.
/* (non-Javadoc)
* @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processLtExpression(org.datanucleus.query.expression.Expression)
*/
@Override
protected Object processLtExpression(Expression expr) {
SQLExpression right = stack.pop();
SQLExpression left = stack.pop();
if (left instanceof ParameterLiteral && !(right instanceof ParameterLiteral)) {
left = replaceParameterLiteral((ParameterLiteral) left, right.getJavaTypeMapping());
} else if (right instanceof ParameterLiteral && !(left instanceof ParameterLiteral)) {
right = replaceParameterLiteral((ParameterLiteral) right, left.getJavaTypeMapping());
}
ExpressionUtils.checkAndCorrectExpressionMappingsForBooleanComparison(left, right);
if (left instanceof UnboundExpression) {
processUnboundExpression((UnboundExpression) left);
left = stack.pop();
}
if (right instanceof UnboundExpression) {
processUnboundExpression((UnboundExpression) right);
right = stack.pop();
}
BooleanExpression opExpr = left.lt(right);
stack.push(opExpr);
return opExpr;
}
use of org.datanucleus.store.rdbms.sql.expression.SQLExpression in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method compileOrdering.
/**
* Method to compile the ordering clause of the query into the SQLStatement.
* @param stmt SELECT statement
*/
protected void compileOrdering(SelectStatement stmt) {
if (compilation.getExprOrdering() != null) {
compileComponent = CompilationComponent.ORDERING;
Expression[] orderingExpr = compilation.getExprOrdering();
SQLExpression[] orderSqlExprs = new SQLExpression[orderingExpr.length];
boolean[] directions = new boolean[orderingExpr.length];
NullOrderingType[] nullOrders = new NullOrderingType[orderingExpr.length];
for (int i = 0; i < orderingExpr.length; i++) {
OrderExpression orderExpr = (OrderExpression) orderingExpr[i];
Expression expr = orderExpr.getLeft();
if (expr instanceof PrimaryExpression) {
PrimaryExpression orderPrimExpr = (PrimaryExpression) expr;
if (orderPrimExpr.getTuples().size() == 1 && resultAliases != null) {
if (resultAliases.contains(orderPrimExpr.getId().toLowerCase())) {
// Order by a result alias
orderSqlExprs[i] = new ResultAliasExpression(stmt, orderPrimExpr.getId());
}
}
}
if (orderSqlExprs[i] == null) {
orderSqlExprs[i] = (SQLExpression) orderExpr.getLeft().evaluate(this);
}
String orderDir = orderExpr.getSortOrder();
directions[i] = ((orderDir == null || orderDir.equals("ascending")) ? false : true);
nullOrders[i] = orderExpr.getNullOrder();
}
stmt.setOrdering(orderSqlExprs, directions, nullOrders);
compileComponent = null;
}
}
use of org.datanucleus.store.rdbms.sql.expression.SQLExpression 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");
}
use of org.datanucleus.store.rdbms.sql.expression.SQLExpression in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method processDistinctExpression.
/* (non-Javadoc)
* @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processDistinctExpression(org.datanucleus.query.expression.Expression)
*/
@Override
protected Object processDistinctExpression(Expression expr) {
SQLExpression sqlExpr = stack.pop();
sqlExpr.distinct();
stack.push(sqlExpr);
return sqlExpr;
}
use of org.datanucleus.store.rdbms.sql.expression.SQLExpression in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method processParameterExpression.
/**
* Method to process a parameter expression.
* The optional argument controls whether we should create this as a parameter or as a literal (i.e the param value is known etc).
* If the parameter doesn't have its value defined then returns ParameterLiteral otherwise we get an XXXLiteral of the (declared) type of the parameter
* @param expr The ParameterExpression
* @param asLiteral Whether to create a SQLLiteral rather than a parameter literal
* @return The processed expression
*/
protected Object processParameterExpression(ParameterExpression expr, boolean asLiteral) {
if (compileComponent == CompilationComponent.ORDERING || compileComponent == CompilationComponent.RESULT) {
// All JDBC drivers I know don't allow parameters in the order-by, or update clause
// Note that we also don't allow parameters in result clause since SQLStatement squashes all SELECT expression to a String so losing info about params
asLiteral = true;
} else if (compileComponent == CompilationComponent.UPDATE && processingCase && !storeMgr.getDatastoreAdapter().supportsOption(DatastoreAdapter.PARAMETER_IN_CASE_IN_UPDATE_CLAUSE)) {
// This database doesn't support parameters within a CASE expression in the UPDATE clause, so process as a literal
asLiteral = true;
}
if (expr.getPosition() >= 0) {
if (paramNameByPosition == null) {
paramNameByPosition = new HashMap<>();
}
paramNameByPosition.put(Integer.valueOf(expr.getPosition()), expr.getId());
}
// Find the parameter value if supplied
Object paramValue = null;
boolean paramValueSet = false;
if (parameters != null && parameters.size() > 0) {
// Check if the parameter has a value
if (parameters.containsKey(expr.getId())) {
// Named parameter
paramValue = parameters.get(expr.getId());
paramValueSet = true;
} else if (parameterValueByName != null && parameterValueByName.containsKey(expr.getId())) {
// Positional parameter, but already encountered
paramValue = parameterValueByName.get(expr.getId());
paramValueSet = true;
} else {
// Positional parameter, not yet encountered
int position = positionalParamNumber;
if (positionalParamNumber < 0) {
position = 0;
}
if (parameters.containsKey(Integer.valueOf(position))) {
paramValue = parameters.get(Integer.valueOf(position));
paramValueSet = true;
positionalParamNumber = position + 1;
if (parameterValueByName == null) {
parameterValueByName = new HashMap<>();
}
parameterValueByName.put(expr.getId(), paramValue);
}
}
}
// Find the type to use for the parameter
JavaTypeMapping m = paramMappingForName.get(expr.getId());
if (m == null) {
// Try to determine from provided parameter value or from symbol table (declared type)
if (paramValue != null) {
if (!storeMgr.getMetaDataManager().isClassPersistable(paramValue.getClass().getName()) && !paramValue.getClass().isArray() && !paramValue.getClass().isInterface() && !Collection.class.isAssignableFrom(paramValue.getClass()) && !Map.class.isAssignableFrom(paramValue.getClass()) && !storeMgr.getNucleusContext().getTypeManager().isSupportedSecondClassType(paramValue.getClass().getName())) {
// Test for this being the "id" of a persistable object
// Persistable/array/interface/collection/map/simple cannot be an object "id"
String className = storeMgr.getClassNameForObjectID(paramValue, clr, ec);
if (className != null) {
// Identity for persistable class
AbstractClassMetaData cmd = storeMgr.getMetaDataManager().getMetaDataForClass(className, clr);
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
Class cls = clr.classForName(className);
m = exprFactory.getMappingForType(cls, false);
m = new PersistableIdMapping((PersistableMapping) m);
}
}
}
if (m == null) {
// Use the type of the input parameter value
try {
m = exprFactory.getMappingForType(paramValue.getClass(), false);
if (m instanceof TypeConverterMapping && expr.getSymbol().getValueType() != null && expr.getSymbol().getValueType() != m.getJavaType()) {
// This is because if we have a parameter of type "ZoneInfo" it needs to use TimeZone since we have the TypeConverter for that
try {
m = exprFactory.getMappingForType(expr.getSymbol().getValueType(), false);
} catch (NucleusUserException nue) {
}
}
} catch (NucleusUserException nue) {
// Maybe it needs a TypeConverter so try with the (declared) symbol type of this parameter
m = exprFactory.getMappingForType(expr.getSymbol().getValueType(), false);
}
}
if (expr.getSymbol() != null && expr.getSymbol().getValueType() != null) {
if (!QueryUtils.queryParameterTypesAreCompatible(expr.getSymbol().getValueType(), paramValue.getClass())) {
throw new QueryCompilerSyntaxException(Localiser.msg("021118", expr.getId(), expr.getSymbol().getValueType().getName(), paramValue.getClass().getName()));
}
if (expr.getSymbol().getValueType() != paramValue.getClass()) {
// Mark as not precompilable since the supplied type implies a subclass of the declared type
setNotPrecompilable();
}
}
} else if (expr.getSymbol() != null && expr.getSymbol().getValueType() != null) {
Class valueType = expr.getSymbol().getValueType();
if (!paramValueSet) {
if (valueType.isInterface()) {
// Special case where we have an interface parameter (not set), and don't know the type, so we pick the first implementation just to get something that works
// This is recompiled when the parameter is provided so is just for use in "compile()"
String[] implNames = storeMgr.getMetaDataManager().getClassesImplementingInterface(valueType.getName(), clr);
if (implNames != null && implNames.length > 0) {
valueType = clr.classForName(implNames[0]);
setNotPrecompilable();
}
}
}
// Use the declared type of the parameter (explicit params)
m = exprFactory.getMappingForType(valueType, false);
}
}
if (asLiteral && m != null && !m.representableAsStringLiteralInStatement()) {
// Must keep this as a parameter since its String form is no good in statements
asLiteral = false;
}
if (asLiteral) {
// Parameter being represented as a literal (for whatever reason), so no longer precompilable
if (isPrecompilable()) {
NucleusLogger.QUERY.debug("Parameter " + expr + " is being resolved as a literal, so the query is no longer precompilable");
}
setNotPrecompilable();
} else if (paramValue == null && expr.getSymbol() != null) {
if (isPrecompilable()) {
NucleusLogger.QUERY.debug("Parameter " + expr + " is set to null so this has to be resolved as a NullLiteral, and the query is no longer precompilable");
}
setNotPrecompilable();
}
// Create the SQLExpression for this parameter, either as value-literal or as parameter-literal
SQLExpression sqlExpr = null;
if (paramValueSet && paramValue == null && options.contains(OPTION_NULL_PARAM_USE_IS_NULL)) {
// Value is set to null, but we enforce a NullLiteral for the case of null comparisons e.g we don't want "field = ?", but instead "field IS NULL"
sqlExpr = exprFactory.newLiteral(stmt, null, null);
} else if (asLiteral) {
// Create a value-literal as requested
sqlExpr = exprFactory.newLiteral(stmt, m, paramValue);
} else {
// Create a parameter-literal with it tied to the parameter name for later replacement in the statement
sqlExpr = exprFactory.newLiteralParameter(stmt, m, paramValue, expr.getId());
if (sqlExpr instanceof ParameterLiteral) {
((ParameterLiteral) sqlExpr).setName(expr.getId());
}
if (expressionForParameter == null) {
expressionForParameter = new HashMap<>();
}
expressionForParameter.put(expr.getId(), sqlExpr);
paramMappingForName.put(expr.getId(), m);
}
stack.push(sqlExpr);
return sqlExpr;
}
Aggregations