Search in sources :

Example 26 with PersistableMapping

use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.

the class AbstractClassTable method addApplicationIdUsingClassTableId.

/**
 * Utility to create the application identity columns and mapping.
 * Uses the id mapping of the specified class table and copies the mappings
 * and columns, whilst retaining the passed preferences for column namings.
 * This is used to copy the PK mappings of a superclass table so we have the same PK.
 * @param columnContainer The container of column MetaData with any namings
 * @param refTable The table that we use as reference
 * @param clr The ClassLoaderResolver
 * @param cmd The ClassMetaData
 */
final void addApplicationIdUsingClassTableId(ColumnMetaDataContainer columnContainer, DatastoreClass refTable, ClassLoaderResolver clr, AbstractClassMetaData cmd) {
    ColumnMetaData[] userdefinedCols = null;
    int nextUserdefinedCol = 0;
    if (columnContainer != null) {
        userdefinedCols = columnContainer.getColumnMetaData();
    }
    pkMappings = new JavaTypeMapping[cmd.getPKMemberPositions().length];
    for (int i = 0; i < cmd.getPKMemberPositions().length; i++) {
        AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(cmd.getPKMemberPositions()[i]);
        JavaTypeMapping mapping = refTable.getMemberMapping(mmd);
        if (mapping == null) {
            // probably due to invalid metadata defined by the user
            throw new NucleusUserException("Cannot find mapping for field " + mmd.getFullFieldName() + " in table " + refTable.toString() + " " + StringUtils.collectionToString(refTable.getColumns()));
        }
        JavaTypeMapping masterMapping = storeMgr.getMappingManager().getMapping(clr.classForName(mapping.getType()));
        // Update field info in mapping
        masterMapping.setMemberMetaData(mmd);
        masterMapping.setTable(this);
        pkMappings[i] = masterMapping;
        // applying the required names from the columnContainer
        for (int j = 0; j < mapping.getNumberOfDatastoreMappings(); j++) {
            JavaTypeMapping m = masterMapping;
            Column refColumn = mapping.getDatastoreMapping(j).getColumn();
            if (mapping instanceof PersistableMapping) {
                m = storeMgr.getMappingManager().getMapping(clr.classForName(refColumn.getJavaTypeMapping().getType()));
                ((PersistableMapping) masterMapping).addJavaTypeMapping(m);
            }
            ColumnMetaData userdefinedColumn = null;
            if (userdefinedCols != null) {
                for (int k = 0; k < userdefinedCols.length; k++) {
                    if (refColumn.getIdentifier().toString().equals(userdefinedCols[k].getTarget())) {
                        userdefinedColumn = userdefinedCols[k];
                        break;
                    }
                }
                if (userdefinedColumn == null && nextUserdefinedCol < userdefinedCols.length) {
                    userdefinedColumn = userdefinedCols[nextUserdefinedCol++];
                }
            }
            // Add this application identity column
            Column idColumn = null;
            if (userdefinedColumn != null) {
                // User has provided a name for this column
                // Currently we only use the column namings from the users definition but we could easily
                // take more of their details.
                idColumn = addColumn(refColumn.getStoredJavaType(), storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, userdefinedColumn.getName()), m, refColumn.getColumnMetaData());
            } else {
                // No name provided so take same as superclass
                idColumn = addColumn(refColumn.getStoredJavaType(), refColumn.getIdentifier(), m, refColumn.getColumnMetaData());
            }
            if (mapping.getDatastoreMapping(j).getColumn().getColumnMetaData() != null) {
                refColumn.copyConfigurationTo(idColumn);
            }
            idColumn.setPrimaryKey();
            // Set the column type based on the field.getType()
            getStoreManager().getMappingManager().createDatastoreMapping(m, idColumn, refColumn.getJavaTypeMapping().getType());
        }
        // Update highest field number if this is higher
        int absoluteFieldNumber = mmd.getAbsoluteFieldNumber();
        if (absoluteFieldNumber > highestMemberNumber) {
            highestMemberNumber = absoluteFieldNumber;
        }
    }
}
Also used : PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 27 with PersistableMapping

use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processCreatorExpression.

/* (non-Javadoc)
     * @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processCreatorExpression(org.datanucleus.query.expression.CreatorExpression)
     */
@Override
protected Object processCreatorExpression(CreatorExpression expr) {
    String className = expr.getId();
    Class cls = null;
    try {
        cls = clr.classForName(className);
    } catch (ClassNotResolvedException cnre) {
        if (importsDefinition != null) {
            cls = importsDefinition.resolveClassDeclaration(className, clr, null);
        }
    }
    List<SQLExpression> ctrArgExprs = null;
    List args = expr.getArguments();
    if (args != null) {
        Class[] ctrArgTypes = new Class[args.size()];
        boolean[] ctrArgTypeCheck = new boolean[args.size()];
        ctrArgExprs = new ArrayList<>(args.size());
        Iterator iter = args.iterator();
        int i = 0;
        while (iter.hasNext()) {
            Expression argExpr = (Expression) iter.next();
            SQLExpression sqlExpr = (SQLExpression) evaluate(argExpr);
            // TODO Cater for "SQL_function" mapping on to ANY type of constructor argument at that position since we don't know the precise type
            if (argExpr instanceof InvokeExpression && ((InvokeExpression) argExpr).getOperation().equalsIgnoreCase("SQL_function")) {
                ctrArgTypeCheck[i] = false;
            } else {
                ctrArgTypeCheck[i] = true;
            }
            ctrArgExprs.add(sqlExpr);
            if (sqlExpr instanceof NewObjectExpression) {
                ctrArgTypes[i] = ((NewObjectExpression) sqlExpr).getNewClass();
            } else if (sqlExpr.getJavaTypeMapping() instanceof DatastoreIdMapping || sqlExpr.getJavaTypeMapping() instanceof PersistableMapping) {
                ctrArgTypes[i] = clr.classForName(sqlExpr.getJavaTypeMapping().getType());
            } else {
                ctrArgTypes[i] = sqlExpr.getJavaTypeMapping().getJavaType();
            }
            i++;
        }
        // Check that this class has the required constructor
        Constructor ctr = ClassUtils.getConstructorWithArguments(cls, ctrArgTypes, ctrArgTypeCheck);
        if (ctr == null) {
            throw new NucleusUserException(Localiser.msg("021033", className, StringUtils.objectArrayToString(ctrArgTypes)));
        }
    }
    // TODO Retain the selected constructor (above)
    NewObjectExpression newExpr = new NewObjectExpression(stmt, cls, ctrArgExprs);
    stack.push(newExpr);
    return newExpr;
}
Also used : InvokeExpression(org.datanucleus.query.expression.InvokeExpression) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) Constructor(java.lang.reflect.Constructor) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassNotResolvedException(org.datanucleus.exceptions.ClassNotResolvedException) NewObjectExpression(org.datanucleus.store.rdbms.sql.expression.NewObjectExpression) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) DatastoreIdMapping(org.datanucleus.store.rdbms.mapping.java.DatastoreIdMapping) 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) ListIterator(java.util.ListIterator) Iterator(java.util.Iterator) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) FetchPlanForClass(org.datanucleus.FetchPlanForClass) ArrayList(java.util.ArrayList) List(java.util.List)

Example 28 with PersistableMapping

use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method compileResult.

/**
 * Method to compile the result clause of the query into the SQLStatement.
 * Note that this also compiles queries of the candidate (no specified result), selecting the candidate field(s).
 * @param stmt SELECT statement
 */
protected void compileResult(SelectStatement stmt) {
    compileComponent = CompilationComponent.RESULT;
    boolean unionsPresent = stmt.getNumberOfUnions() > 0;
    // TODO Cater for more expression types where we have UNIONs and select each UNION separately
    if (compilation.getExprResult() != null) {
        // Select any result expressions
        Expression[] resultExprs = compilation.getExprResult();
        for (int i = 0; i < resultExprs.length; i++) {
            String alias = resultExprs[i].getAlias();
            if (alias != null && resultAliases == null) {
                resultAliases = new HashSet<>();
            }
            if (resultExprs[i] instanceof InvokeExpression || resultExprs[i] instanceof ParameterExpression || resultExprs[i] instanceof Literal) {
                // Process expressions that need no special treatment
                if (resultExprs[i] instanceof InvokeExpression) {
                    processInvokeExpression((InvokeExpression) resultExprs[i]);
                } else if (resultExprs[i] instanceof ParameterExpression) {
                    // Second argument : parameters are literals in result
                    processParameterExpression((ParameterExpression) resultExprs[i], true);
                } else {
                    processLiteral((Literal) resultExprs[i]);
                }
                SQLExpression sqlExpr = stack.pop();
                validateExpressionForResult(sqlExpr);
                int[] cols = stmt.select(sqlExpr, alias);
                StatementMappingIndex idx = new StatementMappingIndex(sqlExpr.getJavaTypeMapping());
                idx.setColumnPositions(cols);
                if (alias != null) {
                    resultAliases.add(alias);
                    idx.setColumnAlias(alias);
                }
                resultDefinition.addMappingForResultExpression(i, idx);
            } else if (resultExprs[i] instanceof PrimaryExpression) {
                PrimaryExpression primExpr = (PrimaryExpression) resultExprs[i];
                if (primExpr.getId().equals(candidateAlias)) {
                    // "this", so select fetch plan fields
                    if (unionsPresent) {
                        // Process the first union separately (in case they have TYPE/instanceof) and then handle remaining UNIONs below
                        stmt.setAllowUnions(false);
                    }
                    StatementClassMapping map = new StatementClassMapping(candidateCmd.getFullClassName(), null);
                    SQLStatementHelper.selectFetchPlanOfCandidateInStatement(stmt, map, candidateCmd, fetchPlan, 1);
                    resultDefinition.addMappingForResultExpression(i, map);
                    if (unionsPresent) {
                        // Process remaining UNIONs. Assumed that we have the same result mapping as the first UNION otherwise SQL wouldn't work anyway
                        stmt.setAllowUnions(true);
                        List<SelectStatement> unionStmts = stmt.getUnions();
                        SelectStatement originalStmt = stmt;
                        for (SelectStatement unionStmt : unionStmts) {
                            this.stmt = unionStmt;
                            unionStmt.setQueryGenerator(this);
                            unionStmt.setAllowUnions(false);
                            StatementClassMapping dummyClsMapping = new StatementClassMapping(candidateCmd.getFullClassName(), null);
                            SQLStatementHelper.selectFetchPlanOfCandidateInStatement(unionStmt, dummyClsMapping, candidateCmd, fetchPlan, 1);
                            unionStmt.setQueryGenerator(null);
                            unionStmt.setAllowUnions(true);
                        }
                        this.stmt = originalStmt;
                    }
                } else {
                    processPrimaryExpression(primExpr);
                    SQLExpression sqlExpr = stack.pop();
                    validateExpressionForResult(sqlExpr);
                    if (primExpr.getId().endsWith("#KEY") || primExpr.getId().endsWith("#VALUE")) {
                        // JPQL KEY(map) or VALUE(map), so select FetchPlan fields where persistable
                        if (sqlExpr.getJavaTypeMapping() instanceof PersistableMapping) {
                            // Method returns persistable object, so select the FetchPlan
                            String selectedType = ((PersistableMapping) sqlExpr.getJavaTypeMapping()).getType();
                            AbstractClassMetaData selectedCmd = ec.getMetaDataManager().getMetaDataForClass(selectedType, clr);
                            FetchPlanForClass fpForCmd = fetchPlan.getFetchPlanForClass(selectedCmd);
                            int[] membersToSelect = fpForCmd.getMemberNumbers();
                            ClassTable selectedTable = (ClassTable) sqlExpr.getSQLTable().getTable();
                            StatementClassMapping map = new StatementClassMapping(selectedCmd.getFullClassName(), null);
                            if (selectedCmd.getIdentityType() == IdentityType.DATASTORE) {
                                int[] cols = stmt.select(sqlExpr.getSQLTable(), selectedTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false), alias);
                                StatementMappingIndex idx = new StatementMappingIndex(selectedTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false));
                                idx.setColumnPositions(cols);
                                map.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), idx);
                            }
                            // Select the FetchPlan members
                            for (int memberToSelect : membersToSelect) {
                                AbstractMemberMetaData selMmd = selectedCmd.getMetaDataForManagedMemberAtAbsolutePosition(memberToSelect);
                                // TODO Arbitrary penultimate argument
                                SQLStatementHelper.selectMemberOfSourceInStatement(stmt, map, fetchPlan, sqlExpr.getSQLTable(), selMmd, clr, 1, null);
                            }
                            resultDefinition.addMappingForResultExpression(i, map);
                            continue;
                        } else if (sqlExpr.getJavaTypeMapping() instanceof EmbeddedMapping) {
                            // Method returns embedded object, so select the FetchPlan
                            EmbeddedMapping embMapping = (EmbeddedMapping) sqlExpr.getJavaTypeMapping();
                            AbstractClassMetaData selectedCmd = ec.getMetaDataManager().getMetaDataForClass(embMapping.getType(), clr);
                            // Select the FetchPlan members
                            StatementClassMapping map = new StatementClassMapping(selectedCmd.getFullClassName(), null);
                            int[] membersToSelect = fetchPlan.getFetchPlanForClass(selectedCmd).getMemberNumbers();
                            for (int memberToSelect : membersToSelect) {
                                AbstractMemberMetaData selMmd = selectedCmd.getMetaDataForManagedMemberAtAbsolutePosition(memberToSelect);
                                JavaTypeMapping selMapping = embMapping.getJavaTypeMapping(selMmd.getName());
                                if (selMapping.includeInFetchStatement()) {
                                    int[] cols = stmt.select(sqlExpr.getSQLTable(), selMapping, alias);
                                    StatementMappingIndex idx = new StatementMappingIndex(selMapping);
                                    idx.setColumnPositions(cols);
                                    map.addMappingForMember(memberToSelect, idx);
                                }
                            }
                            resultDefinition.addMappingForResultExpression(i, map);
                            continue;
                        }
                    }
                    // TODO If the user selects an alias here that is joined, should maybe respect FetchPlan for that (like above for candidate)
                    // TODO Cater for use of UNIONs (e.g "complete-table" inheritance) where mapping is different in other UNION
                    // The difficulty here is that processPrimaryExpression makes use of the sqlTableByPrimary lookup, which is based on the primary statement, so
                    // it still doesn't find the right table/mapping for the UNIONed statements.
                    int[] cols = null;
                    if (sqlExpr instanceof SQLLiteral) {
                        cols = stmt.select(sqlExpr, alias);
                    } else {
                        cols = stmt.select(sqlExpr.getSQLTable(), sqlExpr.getJavaTypeMapping(), alias);
                    }
                    StatementMappingIndex idx = new StatementMappingIndex(sqlExpr.getJavaTypeMapping());
                    idx.setColumnPositions(cols);
                    if (alias != null) {
                        resultAliases.add(alias);
                        idx.setColumnAlias(alias);
                    }
                    resultDefinition.addMappingForResultExpression(i, idx);
                }
            } else if (resultExprs[i] instanceof VariableExpression) {
                // Subquery?
                processVariableExpression((VariableExpression) resultExprs[i]);
                SQLExpression sqlExpr = stack.pop();
                validateExpressionForResult(sqlExpr);
                if (sqlExpr instanceof UnboundExpression) {
                    // Variable wasn't bound in the compilation so far, so handle as cross-join
                    processUnboundExpression((UnboundExpression) sqlExpr);
                    sqlExpr = stack.pop();
                    NucleusLogger.QUERY.debug("QueryToSQL.exprResult variable was still unbound, so binding via cross-join");
                }
                int[] cols = stmt.select(sqlExpr, alias);
                StatementMappingIndex idx = new StatementMappingIndex(sqlExpr.getJavaTypeMapping());
                idx.setColumnPositions(cols);
                if (alias != null) {
                    resultAliases.add(alias);
                    idx.setColumnAlias(alias);
                }
                resultDefinition.addMappingForResultExpression(i, idx);
            } else if (resultExprs[i] instanceof TypeExpression) {
                // TYPE(identification_variable | single_valued_path_expr | input_parameter)
                TypeExpression typeExpr = (TypeExpression) resultExprs[i];
                Expression containedExpr = typeExpr.getContainedExpression();
                if (containedExpr instanceof PrimaryExpression) {
                    processPrimaryExpression((PrimaryExpression) containedExpr);
                    SQLExpression sqlExpr = stack.pop();
                    JavaTypeMapping discrimMapping = sqlExpr.getSQLTable().getTable().getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
                    if (discrimMapping == null) {
                        // TODO If we have a UNIONED primary expression then it would be possible to just select the DN_TYPE from the particular union
                        throw new NucleusException("Result has call to " + typeExpr + " but contained expression has no discriminator. Not supported");
                    }
                    int[] cols = stmt.select(sqlExpr.getSQLTable(), discrimMapping, null, true);
                    StatementMappingIndex idx = new StatementMappingIndex(discrimMapping);
                    idx.setColumnPositions(cols);
                    resultDefinition.addMappingForResultExpression(i, idx);
                } else {
                    throw new NucleusException("Result has call to " + typeExpr + " but contained expression not supported");
                }
            } else if (resultExprs[i] instanceof CreatorExpression) {
                processCreatorExpression((CreatorExpression) resultExprs[i]);
                NewObjectExpression sqlExpr = (NewObjectExpression) stack.pop();
                StatementNewObjectMapping stmtMap = getStatementMappingForNewObjectExpression(sqlExpr, stmt);
                resultDefinition.addMappingForResultExpression(i, stmtMap);
            } else if (resultExprs[i] instanceof DyadicExpression || resultExprs[i] instanceof CaseExpression) {
                if (unionsPresent) {
                    // Process the first union separately (in case they have TYPE/instanceof) and then handle remaining UNIONs below
                    stmt.setAllowUnions(false);
                }
                resultExprs[i].evaluate(this);
                SQLExpression sqlExpr = stack.pop();
                int[] cols = stmt.select(sqlExpr, alias);
                StatementMappingIndex idx = new StatementMappingIndex(sqlExpr.getJavaTypeMapping());
                idx.setColumnPositions(cols);
                if (alias != null) {
                    resultAliases.add(alias);
                    idx.setColumnAlias(alias);
                }
                resultDefinition.addMappingForResultExpression(i, idx);
                if (unionsPresent) {
                    // Process remaining UNIONs. Assumed that we have the same result mapping as the first UNION otherwise SQL wouldn't work anyway
                    stmt.setAllowUnions(true);
                    List<SelectStatement> unionStmts = stmt.getUnions();
                    SelectStatement originalStmt = stmt;
                    for (SelectStatement unionStmt : unionStmts) {
                        this.stmt = unionStmt;
                        unionStmt.setQueryGenerator(this);
                        unionStmt.setAllowUnions(false);
                        resultExprs[i].evaluate(this);
                        sqlExpr = stack.pop();
                        unionStmt.select(sqlExpr, alias);
                        unionStmt.setQueryGenerator(null);
                        unionStmt.setAllowUnions(true);
                    }
                    this.stmt = originalStmt;
                }
            } else {
                throw new NucleusException("Dont currently support result clause containing expression of type " + resultExprs[i]);
            }
        }
        if (stmt.getNumberOfSelects() == 0) {
            // Nothing selected so likely the user had some "new MyClass()" expression, so select "1"
            stmt.select(exprFactory.newLiteral(stmt, storeMgr.getMappingManager().getMapping(Integer.class), 1), null);
        }
    } else {
        // Select of the candidate (no result)
        if (candidateCmd.getIdentityType() == IdentityType.NONDURABLE) {
            // Nondurable identity cases have no "id" for later fetching so get all fields now
            if (NucleusLogger.QUERY.isDebugEnabled()) {
                NucleusLogger.QUERY.debug(Localiser.msg("052520", candidateCmd.getFullClassName()));
            }
            fetchPlan.setGroup("all");
        }
        if (subclasses) {
        // TODO Check for special case of candidate+subclasses stores in same table with discriminator, so select FetchGroup of subclasses also
        }
        int maxFetchDepth = fetchPlan.getMaxFetchDepth();
        if (maxFetchDepth < 0) {
            NucleusLogger.QUERY.debug("No limit specified on query fetch so limiting to 3 levels from candidate. " + "Specify the '" + PropertyNames.PROPERTY_MAX_FETCH_DEPTH + "' to override this");
            // TODO Arbitrary
            maxFetchDepth = 3;
        }
        // This means that we then cater for a UNION using a different column name than the primary statement
        if (unionsPresent) {
            // Process the first union separately (in case they have TYPE/instanceof) and then handle remaining UNIONs below
            stmt.setAllowUnions(false);
        }
        selectFetchPlanForCandidate(stmt, resultDefinitionForClass, maxFetchDepth);
        if (unionsPresent) {
            // Process remaining UNIONs. Assumed that we have the same result mapping as the first UNION otherwise SQL wouldn't work anyway
            stmt.setAllowUnions(true);
            List<SelectStatement> unionStmts = stmt.getUnions();
            SelectStatement originalStmt = stmt;
            for (SelectStatement unionStmt : unionStmts) {
                this.stmt = unionStmt;
                unionStmt.setQueryGenerator(this);
                unionStmt.setAllowUnions(false);
                // We don't want to overwrite anything in the root StatementClassMapping
                StatementClassMapping dummyResClsMapping = new StatementClassMapping();
                selectFetchPlanForCandidate(unionStmt, dummyResClsMapping, maxFetchDepth);
                unionStmt.setQueryGenerator(null);
                unionStmt.setAllowUnions(true);
            }
            this.stmt = originalStmt;
        }
    }
    compileComponent = null;
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) PrimaryExpression(org.datanucleus.query.expression.PrimaryExpression) FetchPlanForClass(org.datanucleus.FetchPlanForClass) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLLiteral(org.datanucleus.store.rdbms.sql.expression.SQLLiteral) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) CreatorExpression(org.datanucleus.query.expression.CreatorExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) CaseExpression(org.datanucleus.query.expression.CaseExpression) NewObjectExpression(org.datanucleus.store.rdbms.sql.expression.NewObjectExpression) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) 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) ArrayList(java.util.ArrayList) List(java.util.List) InvokeExpression(org.datanucleus.query.expression.InvokeExpression) TypeExpression(org.datanucleus.query.expression.TypeExpression) VariableExpression(org.datanucleus.query.expression.VariableExpression) DyadicExpression(org.datanucleus.query.expression.DyadicExpression) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) 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) EmbeddedMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedMapping) ClassTable(org.datanucleus.store.rdbms.table.ClassTable) ParameterExpression(org.datanucleus.query.expression.ParameterExpression) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 29 with PersistableMapping

use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.

the class LocateBulkRequest method getStatement.

protected String getStatement(DatastoreClass table, ObjectProvider[] ops, boolean lock) {
    RDBMSStoreManager storeMgr = table.getStoreManager();
    ClassLoaderResolver clr = storeMgr.getNucleusContext().getClassLoaderResolver(null);
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    cmd = storeMgr.getMetaDataManager().getMetaDataForClass(table.getType(), clr);
    ExecutionContext ec = ops[0].getExecutionContext();
    SelectStatement sqlStatement = new SelectStatement(storeMgr, table, null, null);
    // SELECT fields we require
    resultMapping = new StatementClassMapping();
    // a). PK fields
    if (table.getIdentityType() == IdentityType.DATASTORE) {
        JavaTypeMapping datastoreIdMapping = table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
        SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), datastoreIdMapping);
        int[] cols = sqlStatement.select(expr, null);
        StatementMappingIndex datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
        datastoreIdx.setColumnPositions(cols);
        resultMapping.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
    } else if (table.getIdentityType() == IdentityType.APPLICATION) {
        int[] pkNums = cmd.getPKMemberPositions();
        for (int i = 0; i < pkNums.length; i++) {
            AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[i]);
            JavaTypeMapping pkMapping = table.getMemberMappingInDatastoreClass(mmd);
            if (pkMapping == null) {
                pkMapping = table.getMemberMapping(mmd);
            }
            SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), pkMapping);
            int[] cols = sqlStatement.select(expr, null);
            StatementMappingIndex pkIdx = new StatementMappingIndex(pkMapping);
            pkIdx.setColumnPositions(cols);
            resultMapping.addMappingForMember(mmd.getAbsoluteFieldNumber(), pkIdx);
        }
    } else {
        throw new NucleusUserException("Cannot locate objects using nondurable identity");
    }
    JavaTypeMapping verMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, false);
    if (verMapping != null) {
        VersionMetaData currentVermd = table.getVersionMetaData();
        if (currentVermd != null && currentVermd.getFieldName() == null) {
            // Surrogate version column
            SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), verMapping);
            int[] cols = sqlStatement.select(expr, null);
            StatementMappingIndex mapIdx = new StatementMappingIndex(verMapping);
            mapIdx.setColumnPositions(cols);
            resultMapping.addMappingForMember(SurrogateColumnType.VERSION.getFieldNumber(), mapIdx);
        }
    }
    int[] nonPkFieldNums = cmd.getNonPKMemberPositions();
    if (nonPkFieldNums != null) {
        for (int i = 0; i < nonPkFieldNums.length; i++) {
            AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(nonPkFieldNums[i]);
            JavaTypeMapping mapping = table.getMemberMapping(mmd);
            if (mapping != null && mapping.includeInFetchStatement()) {
                if (mapping instanceof PersistableMapping) {
                    // Ignore 1-1/N-1 for now
                    continue;
                }
                SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), mapping);
                int[] cols = sqlStatement.select(expr, null);
                StatementMappingIndex mapIdx = new StatementMappingIndex(mapping);
                mapIdx.setColumnPositions(cols);
                resultMapping.addMappingForMember(mmd.getAbsoluteFieldNumber(), mapIdx);
            }
        }
    }
    JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
    if (multitenancyMapping != null) {
        // Add WHERE clause restricting to tenant
        SQLExpression tenantExpr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), multitenancyMapping);
        SQLExpression tenantVal = exprFactory.newLiteral(sqlStatement, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, cmd));
        sqlStatement.whereAnd(tenantExpr.eq(tenantVal), true);
    }
    JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
    if (softDeleteMapping != null) {
        // Add WHERE clause restricting to soft-delete unset
        SQLExpression softDeleteExpr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), softDeleteMapping);
        SQLExpression softDeleteVal = exprFactory.newLiteral(sqlStatement, softDeleteMapping, Boolean.FALSE);
        sqlStatement.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
    }
    // Add WHERE clause restricting to the identities of the objects
    mappingDefinitions = new StatementClassMapping[ops.length];
    int inputParamNum = 1;
    for (int i = 0; i < ops.length; i++) {
        mappingDefinitions[i] = new StatementClassMapping();
        if (table.getIdentityType() == IdentityType.DATASTORE) {
            // Datastore identity value for input
            JavaTypeMapping datastoreIdMapping = table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
            SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), datastoreIdMapping);
            SQLExpression val = exprFactory.newLiteralParameter(sqlStatement, datastoreIdMapping, null, "ID");
            sqlStatement.whereOr(expr.eq(val), true);
            StatementMappingIndex datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
            mappingDefinitions[i].addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
            datastoreIdx.addParameterOccurrence(new int[] { inputParamNum++ });
        } else if (table.getIdentityType() == IdentityType.APPLICATION) {
            // Application identity value(s) for input
            BooleanExpression pkExpr = null;
            int[] pkNums = cmd.getPKMemberPositions();
            for (int j = 0; j < pkNums.length; j++) {
                AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[j]);
                JavaTypeMapping pkMapping = table.getMemberMappingInDatastoreClass(mmd);
                if (pkMapping == null) {
                    pkMapping = table.getMemberMapping(mmd);
                }
                SQLExpression expr = exprFactory.newExpression(sqlStatement, sqlStatement.getPrimaryTable(), pkMapping);
                SQLExpression val = exprFactory.newLiteralParameter(sqlStatement, pkMapping, null, "PK" + j);
                BooleanExpression fieldEqExpr = expr.eq(val);
                if (pkExpr == null) {
                    pkExpr = fieldEqExpr;
                } else {
                    pkExpr = pkExpr.and(fieldEqExpr);
                }
                StatementMappingIndex pkIdx = new StatementMappingIndex(pkMapping);
                mappingDefinitions[i].addMappingForMember(mmd.getAbsoluteFieldNumber(), pkIdx);
                int[] inputParams = new int[pkMapping.getNumberOfDatastoreMappings()];
                for (int k = 0; k < pkMapping.getNumberOfDatastoreMappings(); k++) {
                    inputParams[k] = inputParamNum++;
                }
                pkIdx.addParameterOccurrence(inputParams);
            }
            if (pkExpr == null) {
                throw new NucleusException("Unable to generate PK expression for WHERE clause of locate statement");
            }
            pkExpr = (BooleanExpression) pkExpr.encloseInParentheses();
            sqlStatement.whereOr(pkExpr, true);
        }
    }
    // Generate the appropriate JDBC statement allowing for locking
    if (lock) {
        sqlStatement.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, Boolean.TRUE);
        return sqlStatement.getSQLText().toSQL();
    }
    return sqlStatement.getSQLText().toSQL();
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) VersionMetaData(org.datanucleus.metadata.VersionMetaData) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) ExecutionContext(org.datanucleus.ExecutionContext) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 30 with PersistableMapping

use of org.datanucleus.store.rdbms.mapping.java.PersistableMapping in project datanucleus-rdbms by datanucleus.

the class ParameterSetter method storeObjectField.

public void storeObjectField(int fieldNumber, Object value) {
    StatementMappingIndex mapIdx = stmtMappings.getMappingForMemberPosition(fieldNumber);
    if (value == null && mapIdx.getMapping().getMemberMetaData().getNullValue() == NullValue.EXCEPTION) {
        throw new NucleusUserException(Localiser.msg("052400", mapIdx.getMapping().getMemberMetaData().getFullFieldName()));
    }
    try {
        JavaTypeMapping mapping = mapIdx.getMapping();
        boolean provideOwner = false;
        if (mapping instanceof EmbeddedPCMapping || mapping instanceof SerialisedPCMapping || mapping instanceof SerialisedReferenceMapping || mapping instanceof PersistableMapping || mapping instanceof InterfaceMapping) {
            // Pass in the owner ObjectProvider/field for any mappings that have relations
            provideOwner = true;
        }
        if (mapIdx.getNumberOfParameterOccurrences() > 0) {
            for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
                // Set this value for all occurrences of this parameter
                if (provideOwner) {
                    mapping.setObject(ec, statement, mapIdx.getParameterPositionsForOccurrence(i), value, op, fieldNumber);
                } else {
                    mapping.setObject(ec, statement, mapIdx.getParameterPositionsForOccurrence(i), value);
                }
            }
        } else {
            // Important : call setObject even if the paramIndices is null (reachability)
            if (provideOwner) {
                mapping.setObject(ec, statement, null, value, op, fieldNumber);
            } else {
                mapping.setObject(ec, statement, null, value);
            }
        }
        AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
        RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
        if (op.getClassMetaData().getSCOMutableMemberFlags()[fieldNumber]) {
            SCOUtils.wrapSCOField(op, fieldNumber, value, true);
        } else if (RelationType.isRelationSingleValued(relationType) && (mmd.getEmbeddedMetaData() != null && mmd.getEmbeddedMetaData().getOwnerMember() != null)) {
            // Embedded PC, so make sure the field is wrapped where appropriate TODO This should be part of ManagedRelationships
            op.updateOwnerFieldInEmbeddedField(fieldNumber, value);
        }
    } catch (NotYetFlushedException e) {
        if (op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber).getNullValue() == NullValue.EXCEPTION) {
            throw e;
        }
        op.updateFieldAfterInsert(e.getPersistable(), fieldNumber);
    }
}
Also used : InterfaceMapping(org.datanucleus.store.rdbms.mapping.java.InterfaceMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SerialisedReferenceMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedReferenceMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedPCMapping) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) NotYetFlushedException(org.datanucleus.exceptions.NotYetFlushedException) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) RelationType(org.datanucleus.metadata.RelationType) SerialisedPCMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedPCMapping) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)33 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)27 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)17 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)17 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)16 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)15 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)13 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)10 Collection (java.util.Collection)7 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)7 ArrayList (java.util.ArrayList)6 HashSet (java.util.HashSet)6 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)6 HashMap (java.util.HashMap)5 Iterator (java.util.Iterator)5 List (java.util.List)5 Map (java.util.Map)5 NucleusException (org.datanucleus.exceptions.NucleusException)5 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)5 FetchPlanForClass (org.datanucleus.FetchPlanForClass)4