Search in sources :

Example 1 with UnboundExpression

use of org.datanucleus.store.rdbms.sql.expression.UnboundExpression in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processNoteqExpression.

/* (non-Javadoc)
     * @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processNoteqExpression(org.datanucleus.query.expression.Expression)
     */
@Override
protected Object processNoteqExpression(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());
    }
    if (left.isParameter() && right.isParameter()) {
        if (left.isParameter() && left instanceof SQLLiteral && ((SQLLiteral) left).getValue() != null) {
            useParameterExpressionAsLiteral((SQLLiteral) left);
        }
        if (right.isParameter() && right instanceof SQLLiteral && ((SQLLiteral) right).getValue() != null) {
            useParameterExpressionAsLiteral((SQLLiteral) right);
        }
    }
    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.ne(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) SQLLiteral(org.datanucleus.store.rdbms.sql.expression.SQLLiteral) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression)

Example 2 with UnboundExpression

use of org.datanucleus.store.rdbms.sql.expression.UnboundExpression in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processPrimaryExpression.

/* (non-Javadoc)
     * @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processPrimaryExpression(org.datanucleus.query.expression.PrimaryExpression)
     */
protected Object processPrimaryExpression(PrimaryExpression expr) {
    SQLExpression sqlExpr = null;
    if (expr.getLeft() != null) {
        if (expr.getLeft() instanceof DyadicExpression && expr.getLeft().getOperator() == Expression.OP_CAST) {
            String exprCastName = null;
            if (expr.getLeft().getLeft() instanceof PrimaryExpression) {
                exprCastName = "CAST_" + ((PrimaryExpression) expr.getLeft().getLeft()).getId();
            } else if (expr.getLeft().getLeft() instanceof VariableExpression) {
                exprCastName = "CAST_" + ((VariableExpression) expr.getLeft().getLeft()).getId();
            } else if (expr.getLeft().getLeft() instanceof InvokeExpression) {
                exprCastName = "CAST_" + expr.getLeft().getLeft();
            } else {
                throw new NucleusException("Don't currently support cast of " + expr.getLeft().getLeft());
            }
            expr.getLeft().getLeft().evaluate(this);
            sqlExpr = stack.pop();
            JavaTypeMapping mapping = sqlExpr.getJavaTypeMapping();
            if (mapping instanceof EmbeddedMapping) {
                // Cast of an embedded field, so use same table
                // Extract what we are casting it to
                Literal castLitExpr = (Literal) expr.getLeft().getRight();
                Class castType = resolveClass((String) castLitExpr.getLiteral());
                AbstractClassMetaData castCmd = ec.getMetaDataManager().getMetaDataForClass(castType, clr);
                JavaTypeMapping discMapping = ((EmbeddedMapping) mapping).getDiscriminatorMapping();
                if (discMapping != null) {
                    // Should have a discriminator always when casting this
                    SQLExpression discExpr = exprFactory.newExpression(stmt, sqlExpr.getSQLTable(), discMapping);
                    Object discVal = castCmd.getDiscriminatorValue();
                    SQLExpression discValExpr = exprFactory.newLiteral(stmt, discMapping, discVal);
                    BooleanExpression discRestrictExpr = discExpr.eq(discValExpr);
                    Iterator<String> subclassIter = storeMgr.getSubClassesForClass(castType.getName(), true, clr).iterator();
                    while (subclassIter.hasNext()) {
                        String subclassName = subclassIter.next();
                        AbstractClassMetaData subtypeCmd = storeMgr.getMetaDataManager().getMetaDataForClass(subclassName, clr);
                        discVal = subtypeCmd.getDiscriminatorValue();
                        discValExpr = exprFactory.newLiteral(stmt, discMapping, discVal);
                        BooleanExpression subtypeExpr = discExpr.eq(discValExpr);
                        discRestrictExpr = discRestrictExpr.ior(subtypeExpr);
                    }
                    stmt.whereAnd(discRestrictExpr, true);
                }
                SQLTableMapping tblMapping = new SQLTableMapping(sqlExpr.getSQLTable(), castCmd, sqlExpr.getJavaTypeMapping());
                setSQLTableMappingForAlias(exprCastName, tblMapping);
                SQLTableMapping sqlMapping = getSQLTableMappingForPrimaryExpression(stmt, exprCastName, expr, Boolean.FALSE);
                if (sqlMapping == null) {
                    throw new NucleusException("PrimaryExpression " + expr + " is not yet supported");
                }
                sqlExpr = exprFactory.newExpression(stmt, sqlMapping.table, sqlMapping.mapping);
                stack.push(sqlExpr);
                return sqlExpr;
            }
            // Evaluate the cast
            expr.getLeft().evaluate(this);
            sqlExpr = stack.pop();
            // Extract what we are casting it to
            Literal castLitExpr = (Literal) expr.getLeft().getRight();
            AbstractClassMetaData castCmd = ec.getMetaDataManager().getMetaDataForClass(resolveClass((String) castLitExpr.getLiteral()), clr);
            SQLTableMapping tblMapping = new SQLTableMapping(sqlExpr.getSQLTable(), castCmd, sqlExpr.getJavaTypeMapping());
            setSQLTableMappingForAlias(exprCastName, tblMapping);
            SQLTableMapping sqlMapping = getSQLTableMappingForPrimaryExpression(stmt, exprCastName, expr, Boolean.FALSE);
            if (sqlMapping == null) {
                throw new NucleusException("PrimaryExpression " + expr + " is not yet supported");
            }
            sqlExpr = exprFactory.newExpression(stmt, sqlMapping.table, sqlMapping.mapping);
            stack.push(sqlExpr);
            return sqlExpr;
        } else if (expr.getLeft() instanceof ParameterExpression) {
            // "{paramExpr}.field[.field[.field]]"
            // Need parameter values to process this
            setNotPrecompilable();
            ParameterExpression paramExpr = (ParameterExpression) expr.getLeft();
            Symbol paramSym = compilation.getSymbolTable().getSymbol(paramExpr.getId());
            if (paramSym.getValueType() != null && paramSym.getValueType().isArray()) {
                // Special case : array "methods" (particularly "length")
                String first = expr.getTuples().get(0);
                processParameterExpression(paramExpr, true);
                SQLExpression paramSqlExpr = stack.pop();
                sqlExpr = exprFactory.invokeMethod(stmt, "ARRAY", first, paramSqlExpr, null);
                stack.push(sqlExpr);
                return sqlExpr;
            }
            // Create Literal for the parameter (since we need to perform operations on it)
            processParameterExpression(paramExpr, true);
            SQLExpression paramSqlExpr = stack.pop();
            SQLLiteral lit = (SQLLiteral) paramSqlExpr;
            Object paramValue = lit.getValue();
            List<String> tuples = expr.getTuples();
            Iterator<String> tuplesIter = tuples.iterator();
            Object objValue = paramValue;
            while (tuplesIter.hasNext()) {
                String fieldName = tuplesIter.next();
                if (objValue == null) {
                    NucleusLogger.QUERY.warn(">> Compilation of " + expr + " : need to direct through field \"" + fieldName + "\" on null value, hence not compilable!");
                    // Null value, and we have further path to navigate TODO Handle this "NPE"
                    break;
                }
                objValue = getValueForObjectField(objValue, fieldName);
                // Using literal value of parameter, so cannot precompile it
                setNotPrecompilable();
            }
            if (objValue == null) {
                sqlExpr = exprFactory.newLiteral(stmt, null, null);
                stack.push(sqlExpr);
                return sqlExpr;
            }
            JavaTypeMapping m = exprFactory.getMappingForType(objValue.getClass(), false);
            sqlExpr = exprFactory.newLiteral(stmt, m, objValue);
            stack.push(sqlExpr);
            return sqlExpr;
        } else if (expr.getLeft() instanceof VariableExpression) {
            // "{varExpr}.field[.field[.field]]"
            VariableExpression varExpr = (VariableExpression) expr.getLeft();
            processVariableExpression(varExpr);
            SQLExpression varSqlExpr = stack.pop();
            if (varSqlExpr instanceof UnboundExpression) {
                // Bind as CROSS JOIN for now
                processUnboundExpression((UnboundExpression) varSqlExpr);
                varSqlExpr = stack.pop();
            }
            Class varType = clr.classForName(varSqlExpr.getJavaTypeMapping().getType());
            if (varSqlExpr.getSQLStatement() == stmt.getParentStatement()) {
                // Use parent mapper to get the mapping for this field since it has the table
                SQLTableMapping sqlMapping = parentMapper.getSQLTableMappingForPrimaryExpression(stmt, null, expr, Boolean.FALSE);
                if (sqlMapping == null) {
                    throw new NucleusException("PrimaryExpression " + expr.getId() + " is not yet supported");
                }
                // TODO Cater for the table required to join to not being the primary table of the outer query
                // This should check on
                // getDatastoreAdapter().supportsOption(RDBMSAdapter.ACCESS_PARENTQUERY_IN_SUBQUERY))
                sqlExpr = exprFactory.newExpression(varSqlExpr.getSQLStatement(), sqlMapping.table, sqlMapping.mapping);
                stack.push(sqlExpr);
                return sqlExpr;
            }
            SQLTableMapping varTblMapping = getSQLTableMappingForAlias(varExpr.getId());
            if (varTblMapping == null) {
                throw new NucleusUserException("Variable " + varExpr.getId() + " is not yet bound, so cannot get field " + expr.getId());
            }
            if (varTblMapping.cmd == null) {
                throw new NucleusUserException("Variable " + varExpr.getId() + " of type " + varType.getName() + " cannot evaluate " + expr.getId());
            }
            SQLTableMapping sqlMapping = getSQLTableMappingForPrimaryExpression(varSqlExpr.getSQLStatement(), varExpr.getId(), expr, Boolean.FALSE);
            sqlExpr = exprFactory.newExpression(sqlMapping.table.getSQLStatement(), sqlMapping.table, sqlMapping.mapping);
            stack.push(sqlExpr);
            return sqlExpr;
        } else if (expr.getLeft() instanceof InvokeExpression) {
            InvokeExpression invokeExpr = (InvokeExpression) expr.getLeft();
            SQLExpression invokedSqlExpr = getInvokedSqlExpressionForInvokeExpression(invokeExpr);
            processInvokeExpression(invokeExpr, invokedSqlExpr);
            SQLExpression invokeSqlExpr = stack.pop();
            Table tbl = invokeSqlExpr.getSQLTable().getTable();
            if (expr.getTuples().size() > 1) {
                throw new NucleusUserException("Dont currently support evaluating " + expr.getId() + " on " + invokeSqlExpr);
            }
            SQLTable invokeSqlTbl = invokeSqlExpr.getSQLTable();
            if (invokedSqlExpr.getJavaTypeMapping() instanceof OptionalMapping && invokeExpr.getOperation().equals("get") && expr.getTuples().size() == 1) {
                OptionalMapping opMapping = (OptionalMapping) invokedSqlExpr.getJavaTypeMapping();
                if (opMapping.getWrappedMapping() instanceof PersistableMapping) {
                    // Special case of Optional.get().{field}, so we need to join to the related table
                    AbstractMemberMetaData mmd = invokedSqlExpr.getJavaTypeMapping().getMemberMetaData();
                    AbstractClassMetaData otherCmd = ec.getMetaDataManager().getMetaDataForClass(mmd.getCollection().getElementType(), clr);
                    Table otherTbl = storeMgr.getDatastoreClass(otherCmd.getFullClassName(), clr);
                    // Optional type so do LEFT OUTER JOIN since if it is null then we would eliminate all other results
                    invokeSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, invokeSqlExpr.getSQLTable(), opMapping.getWrappedMapping(), otherTbl, null, otherTbl.getIdMapping(), null, null, true);
                    tbl = invokeSqlTbl.getTable();
                }
            }
            if (tbl instanceof DatastoreClass) {
                // Table of a class, so assume to have field in the table of the class
                // TODO Allow joins to superclasses if required
                JavaTypeMapping mapping = ((DatastoreClass) tbl).getMemberMapping(expr.getId());
                if (mapping == null) {
                    throw new NucleusUserException("Dont currently support evaluating " + expr.getId() + " on " + invokeSqlExpr + ". The field " + expr.getId() + " doesnt exist in table " + tbl);
                }
                sqlExpr = exprFactory.newExpression(stmt, invokeSqlTbl, mapping);
                stack.push(sqlExpr);
                return sqlExpr;
            } else if (tbl instanceof JoinTable) {
                if (invokeSqlExpr.getJavaTypeMapping() instanceof EmbeddedMapping) {
                    // Table containing an embedded element/key/value so assume we have a column in the join table
                    EmbeddedMapping embMapping = (EmbeddedMapping) invokeSqlExpr.getJavaTypeMapping();
                    JavaTypeMapping mapping = embMapping.getJavaTypeMapping(expr.getId());
                    if (mapping == null) {
                        throw new NucleusUserException("Dont currently support evaluating " + expr.getId() + " on " + invokeSqlExpr + ". The field " + expr.getId() + " doesnt exist in table " + tbl);
                    }
                    sqlExpr = exprFactory.newExpression(stmt, invokeSqlTbl, mapping);
                    stack.push(sqlExpr);
                    return sqlExpr;
                }
            }
            throw new NucleusUserException("Dont currently support evaluating " + expr.getId() + " on " + invokeSqlExpr + " with invoke having table of " + tbl);
        } else {
            throw new NucleusUserException("Dont currently support PrimaryExpression with 'left' of " + expr.getLeft());
        }
    }
    // Real primary expression ("field.field", "alias.field.field" etc)
    SQLTableMapping sqlMapping = getSQLTableMappingForPrimaryExpression(stmt, null, expr, null);
    if (sqlMapping == null) {
        throw new NucleusException("PrimaryExpression " + expr.getId() + " is not yet supported");
    }
    sqlExpr = exprFactory.newExpression(stmt, sqlMapping.table, sqlMapping.mapping);
    if (sqlMapping.mmd != null && sqlExpr instanceof MapExpression) {
        // This sqlMapping is for something joined in a FROM clause, so set the alias on the returned MapExpression to avoid doing the same joins
        String alias = getAliasForSQLTableMapping(sqlMapping);
        if (alias == null && parentMapper != null) {
            alias = parentMapper.getAliasForSQLTableMapping(sqlMapping);
        }
        ((MapExpression) sqlExpr).setAliasForMapTable(alias);
    }
    stack.push(sqlExpr);
    return sqlExpr;
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) PrimaryExpression(org.datanucleus.query.expression.PrimaryExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) Symbol(org.datanucleus.query.compiler.Symbol) SQLLiteral(org.datanucleus.store.rdbms.sql.expression.SQLLiteral) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) TemporalLiteral(org.datanucleus.store.rdbms.sql.expression.TemporalLiteral) SQLLiteral(org.datanucleus.store.rdbms.sql.expression.SQLLiteral) ParameterLiteral(org.datanucleus.store.rdbms.sql.expression.ParameterLiteral) BooleanLiteral(org.datanucleus.store.rdbms.sql.expression.BooleanLiteral) IntegerLiteral(org.datanucleus.store.rdbms.sql.expression.IntegerLiteral) Literal(org.datanucleus.query.expression.Literal) NullLiteral(org.datanucleus.store.rdbms.sql.expression.NullLiteral) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) ListIterator(java.util.ListIterator) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) List(java.util.List) MapExpression(org.datanucleus.store.rdbms.sql.expression.MapExpression) InvokeExpression(org.datanucleus.query.expression.InvokeExpression) Table(org.datanucleus.store.rdbms.table.Table) JoinTable(org.datanucleus.store.rdbms.table.JoinTable) ClassTable(org.datanucleus.store.rdbms.table.ClassTable) ElementContainerTable(org.datanucleus.store.rdbms.table.ElementContainerTable) MapTable(org.datanucleus.store.rdbms.table.MapTable) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) ArrayTable(org.datanucleus.store.rdbms.table.ArrayTable) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) VariableExpression(org.datanucleus.query.expression.VariableExpression) DyadicExpression(org.datanucleus.query.expression.DyadicExpression) OptionalMapping(org.datanucleus.store.rdbms.mapping.java.OptionalMapping) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) EmbeddedMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedMapping) ParameterExpression(org.datanucleus.query.expression.ParameterExpression) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) FetchPlanForClass(org.datanucleus.FetchPlanForClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) JoinTable(org.datanucleus.store.rdbms.table.JoinTable)

Example 3 with UnboundExpression

use of org.datanucleus.store.rdbms.sql.expression.UnboundExpression 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 4 with UnboundExpression

use of org.datanucleus.store.rdbms.sql.expression.UnboundExpression 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.getVersionStrategy() == 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.getVersionStrategy() == 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;
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) PrimaryExpression(org.datanucleus.query.expression.PrimaryExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) VersionMetaData(org.datanucleus.metadata.VersionMetaData) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression) TemporalLiteral(org.datanucleus.store.rdbms.sql.expression.TemporalLiteral) VariableExpression(org.datanucleus.query.expression.VariableExpression) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) DyadicExpression(org.datanucleus.query.expression.DyadicExpression) CaseExpression(org.datanucleus.query.expression.CaseExpression) 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) ColumnExpression(org.datanucleus.store.rdbms.sql.expression.ColumnExpression) ClassTable(org.datanucleus.store.rdbms.table.ClassTable) TemporalLiteral(org.datanucleus.store.rdbms.sql.expression.TemporalLiteral) SQLLiteral(org.datanucleus.store.rdbms.sql.expression.SQLLiteral) ParameterLiteral(org.datanucleus.store.rdbms.sql.expression.ParameterLiteral) BooleanLiteral(org.datanucleus.store.rdbms.sql.expression.BooleanLiteral) IntegerLiteral(org.datanucleus.store.rdbms.sql.expression.IntegerLiteral) Literal(org.datanucleus.query.expression.Literal) NullLiteral(org.datanucleus.store.rdbms.sql.expression.NullLiteral) ParameterExpression(org.datanucleus.query.expression.ParameterExpression) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) NucleusException(org.datanucleus.exceptions.NucleusException) IntegerLiteral(org.datanucleus.store.rdbms.sql.expression.IntegerLiteral)

Example 5 with UnboundExpression

use of org.datanucleus.store.rdbms.sql.expression.UnboundExpression in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processVariableExpression.

/* (non-Javadoc)
     * @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processVariableExpression(org.datanucleus.query.expression.VariableExpression)
     */
@Override
protected Object processVariableExpression(VariableExpression expr) {
    String varName = expr.getId();
    Symbol varSym = expr.getSymbol();
    if (varSym != null) {
        // Use name from symbol if possible
        varName = varSym.getQualifiedName();
    }
    if (hasSQLTableMappingForAlias(varName)) {
        // Variable already found
        SQLTableMapping tblMapping = getSQLTableMappingForAlias(varName);
        SQLExpression sqlExpr = exprFactory.newExpression(tblMapping.table.getSQLStatement(), tblMapping.table, tblMapping.mapping);
        stack.push(sqlExpr);
        return sqlExpr;
    } else if (compilation.getCompilationForSubquery(varName) != null) {
        // Subquery variable
        QueryCompilation subCompilation = compilation.getCompilationForSubquery(varName);
        AbstractClassMetaData subCmd = ec.getMetaDataManager().getMetaDataForClass(subCompilation.getCandidateClass(), ec.getClassLoaderResolver());
        // Create subquery statement, using any provided alias if possible
        String subAlias = null;
        if (subCompilation.getCandidateAlias() != null && !subCompilation.getCandidateAlias().equals(candidateAlias)) {
            subAlias = subCompilation.getCandidateAlias();
        }
        StatementResultMapping subqueryResultMapping = new StatementResultMapping();
        // TODO Fix "avg(something)" arg - not essential but is a hack right now
        SQLStatement subStmt = RDBMSQueryUtils.getStatementForCandidates(storeMgr, stmt, subCmd, null, ec, subCompilation.getCandidateClass(), true, "avg(something)", subAlias, null, null);
        QueryToSQLMapper sqlMapper = new QueryToSQLMapper(subStmt, subCompilation, parameters, null, subqueryResultMapping, subCmd, true, fetchPlan, ec, importsDefinition, options, extensionsByName);
        sqlMapper.setDefaultJoinType(defaultJoinType);
        sqlMapper.setDefaultJoinTypeFilter(defaultJoinTypeFilter);
        sqlMapper.setParentMapper(this);
        sqlMapper.compile();
        if (subqueryResultMapping.getNumberOfResultExpressions() > 1) {
            throw new NucleusUserException("Number of result expressions in subquery should be 1");
        }
        SQLExpression subExpr = null;
        // TODO Cater for subquery select of its own candidate
        if (subqueryResultMapping.getNumberOfResultExpressions() == 0) {
            subExpr = new org.datanucleus.store.rdbms.sql.expression.SubqueryExpression(stmt, subStmt);
        } else {
            JavaTypeMapping subMapping = ((StatementMappingIndex) subqueryResultMapping.getMappingForResultExpression(0)).getMapping();
            if (subMapping instanceof TemporalMapping) {
                subExpr = new TemporalSubqueryExpression(stmt, subStmt);
            } else if (subMapping instanceof StringMapping) {
                subExpr = new StringSubqueryExpression(stmt, subStmt);
            } else {
                subExpr = new NumericSubqueryExpression(stmt, subStmt);
            }
            if (subExpr.getJavaTypeMapping() == null) {
                subExpr.setJavaTypeMapping(subMapping);
            }
        }
        stack.push(subExpr);
        return subExpr;
    } else if (stmt.getParentStatement() != null && parentMapper != null && parentMapper.candidateAlias != null && parentMapper.candidateAlias.equals(varName)) {
        // Variable in subquery linking back to parent query
        SQLExpression varExpr = exprFactory.newExpression(stmt.getParentStatement(), stmt.getParentStatement().getPrimaryTable(), stmt.getParentStatement().getPrimaryTable().getTable().getIdMapping());
        stack.push(varExpr);
        return varExpr;
    } else {
        // Variable never met before, so return as UnboundExpression - process later if needing binding
        NucleusLogger.QUERY.debug("QueryToSQL.processVariable (unbound) variable=" + varName + " is not yet bound so returning UnboundExpression");
        UnboundExpression unbExpr = new UnboundExpression(stmt, varName);
        stack.push(unbExpr);
        return unbExpr;
    }
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) Symbol(org.datanucleus.query.compiler.Symbol) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) StringMapping(org.datanucleus.store.rdbms.mapping.java.StringMapping) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) NumericSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.NumericSubqueryExpression) StringSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression) SubqueryExpression(org.datanucleus.query.expression.SubqueryExpression) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) TemporalSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.TemporalSubqueryExpression) StringSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.StringSubqueryExpression) QueryCompilation(org.datanucleus.query.compiler.QueryCompilation) TemporalMapping(org.datanucleus.store.rdbms.mapping.java.TemporalMapping)

Aggregations

SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)24 UnboundExpression (org.datanucleus.store.rdbms.sql.expression.UnboundExpression)24 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)18 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)15 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)14 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)13 BooleanExpression (org.datanucleus.store.rdbms.sql.expression.BooleanExpression)13 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)13 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)12 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)10 NucleusException (org.datanucleus.exceptions.NucleusException)9 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)9 ParameterLiteral (org.datanucleus.store.rdbms.sql.expression.ParameterLiteral)9 BooleanSubqueryExpression (org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression)8 MapTable (org.datanucleus.store.rdbms.table.MapTable)7 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)6 MapExpression (org.datanucleus.store.rdbms.sql.expression.MapExpression)6 NumericExpression (org.datanucleus.store.rdbms.sql.expression.NumericExpression)6 SQLLiteral (org.datanucleus.store.rdbms.sql.expression.SQLLiteral)6 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)6