Search in sources :

Example 11 with SQLExpression

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;
}
Also used : BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) ParameterLiteral(org.datanucleus.store.rdbms.sql.expression.ParameterLiteral) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression)

Example 12 with SQLExpression

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;
    }
}
Also used : NullOrderingType(org.datanucleus.query.NullOrderingType) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) PrimaryExpression(org.datanucleus.query.expression.PrimaryExpression) CaseExpression(org.datanucleus.query.expression.CaseExpression) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) StringExpression(org.datanucleus.store.rdbms.sql.expression.StringExpression) JoinExpression(org.datanucleus.query.expression.JoinExpression) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) StringSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression) ClassExpression(org.datanucleus.query.expression.ClassExpression) InvokeExpression(org.datanucleus.query.expression.InvokeExpression) MapExpression(org.datanucleus.store.rdbms.sql.expression.MapExpression) SubqueryExpression(org.datanucleus.query.expression.SubqueryExpression) NewObjectExpression(org.datanucleus.store.rdbms.sql.expression.NewObjectExpression) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) OrderExpression(org.datanucleus.query.expression.OrderExpression) PrimaryExpression(org.datanucleus.query.expression.PrimaryExpression) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) TemporalExpression(org.datanucleus.store.rdbms.sql.expression.TemporalExpression) ArrayExpression(org.datanucleus.query.expression.ArrayExpression) ResultAliasExpression(org.datanucleus.store.rdbms.sql.expression.ResultAliasExpression) CreatorExpression(org.datanucleus.query.expression.CreatorExpression) Expression(org.datanucleus.query.expression.Expression) TypeExpression(org.datanucleus.query.expression.TypeExpression) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression) CollectionExpression(org.datanucleus.store.rdbms.sql.expression.CollectionExpression) DyadicExpression(org.datanucleus.query.expression.DyadicExpression) ParameterExpression(org.datanucleus.query.expression.ParameterExpression) ColumnExpression(org.datanucleus.store.rdbms.sql.expression.ColumnExpression) VariableExpression(org.datanucleus.query.expression.VariableExpression) OrderExpression(org.datanucleus.query.expression.OrderExpression) ResultAliasExpression(org.datanucleus.store.rdbms.sql.expression.ResultAliasExpression)

Example 13 with SQLExpression

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");
}
Also used : BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression)

Example 14 with SQLExpression

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;
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression)

Example 15 with SQLExpression

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;
}
Also used : ParameterLiteral(org.datanucleus.store.rdbms.sql.expression.ParameterLiteral) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) HashMap(java.util.HashMap) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) PersistableIdMapping(org.datanucleus.store.rdbms.mapping.java.PersistableIdMapping) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) TypeConverterMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMapping) QueryCompilerSyntaxException(org.datanucleus.store.query.QueryCompilerSyntaxException) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) FetchPlanForClass(org.datanucleus.FetchPlanForClass) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)199 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)98 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)95 ArrayList (java.util.ArrayList)75 NumericExpression (org.datanucleus.store.rdbms.sql.expression.NumericExpression)74 NucleusException (org.datanucleus.exceptions.NucleusException)63 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)56 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)47 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)44 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)41 BooleanExpression (org.datanucleus.store.rdbms.sql.expression.BooleanExpression)40 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)35 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)34 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)34 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)34 UnboundExpression (org.datanucleus.store.rdbms.sql.expression.UnboundExpression)31 SQLLiteral (org.datanucleus.store.rdbms.sql.expression.SQLLiteral)29 NullLiteral (org.datanucleus.store.rdbms.sql.expression.NullLiteral)28 ParameterLiteral (org.datanucleus.store.rdbms.sql.expression.ParameterLiteral)28 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)25