Search in sources :

Example 16 with ReferenceMapping

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

the class QueryToSQLMapper method getSQLTableMappingForPrimaryExpression.

/**
 * Method to take in a PrimaryExpression and return the SQLTable mapping info that it signifies.
 * If the primary expression implies joining to other objects then adds the joins to the statement.
 * Only adds joins if necessary; so if there is a further component after the required join, or if
 * the "forceJoin" flag is set.
 * @param theStmt SQLStatement to use when looking for tables etc
 * @param exprName Name for an expression that this primary is relative to (optional)
 *                 If not specified then the tuples are relative to the candidate.
 *                 If specified then should have an entry in sqlTableByPrimary under this name.
 * @param primExpr The primary expression
 * @param forceJoin Whether to force a join if a relation member (or null if leaving to this method to decide)
 * @return The SQL table mapping information for the specified primary
 */
private SQLTableMapping getSQLTableMappingForPrimaryExpression(SQLStatement theStmt, String exprName, PrimaryExpression primExpr, Boolean forceJoin) {
    if (forceJoin == null && primExpr.getParent() != null) {
        if (primExpr.getParent().getOperator() == Expression.OP_IS || primExpr.getParent().getOperator() == Expression.OP_ISNOT) {
            // "instanceOf" needs to be in the table of the primary expression
            forceJoin = Boolean.TRUE;
        }
    }
    SQLTableMapping sqlMapping = null;
    List<String> tuples = primExpr.getTuples();
    // Find source object
    ListIterator<String> iter = tuples.listIterator();
    String first = tuples.get(0);
    boolean mapKey = false;
    boolean mapValue = false;
    if (first.endsWith("#KEY")) {
        first = first.substring(0, first.length() - 4);
        mapKey = true;
    } else if (first.endsWith("#VALUE")) {
        first = first.substring(0, first.length() - 6);
        mapValue = true;
    }
    String primaryName = null;
    if (exprName != null) {
        // Primary relative to some object etc
        sqlMapping = getSQLTableMappingForAlias(exprName);
        primaryName = exprName;
    } else {
        if (hasSQLTableMappingForAlias(first)) {
            // Start from a candidate (e.g JPQL alias)
            sqlMapping = getSQLTableMappingForAlias(first);
            primaryName = first;
            // Skip first tuple
            iter.next();
        }
        if (sqlMapping != null && first.equals(candidateAlias) && candidateCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
            // Special case of using COMPLETE_TABLE for candidate and picked wrong table
            // TODO Use OPTION_CASE_INSENSITIVE
            SQLTable firstSqlTbl = stmt.getTable(first.toUpperCase());
            if (firstSqlTbl != null && firstSqlTbl.getTable() != sqlMapping.table.getTable()) {
                // Cached the SQLTableMapping for one of the other inherited classes, so create our own
                sqlMapping = new SQLTableMapping(firstSqlTbl, sqlMapping.cmd, firstSqlTbl.getTable().getIdMapping());
            }
        }
        if (sqlMapping == null) {
            if (parentMapper != null) {
                QueryToSQLMapper theParentMapper = parentMapper;
                while (theParentMapper != null) {
                    if (theParentMapper.hasSQLTableMappingForAlias(first)) {
                        // Try parent query
                        sqlMapping = theParentMapper.getSQLTableMappingForAlias(first);
                        primaryName = first;
                        // Skip first tuple
                        iter.next();
                        // This expression is for the parent statement so any joins need to go on that statement
                        theStmt = sqlMapping.table.getSQLStatement();
                        break;
                    }
                    theParentMapper = theParentMapper.parentMapper;
                }
            }
        }
        if (sqlMapping == null) {
            // Field of candidate, so use candidate
            sqlMapping = getSQLTableMappingForAlias(candidateAlias);
            primaryName = candidateAlias;
        }
    }
    AbstractClassMetaData cmd = sqlMapping.cmd;
    JavaTypeMapping mapping = sqlMapping.mapping;
    if (sqlMapping.mmd != null && (mapKey || mapValue)) {
        // Special case of MAP#KEY or MAP#VALUE, so navigate from the Map "table" to the key or value
        SQLTable sqlTbl = sqlMapping.table;
        AbstractMemberMetaData mmd = sqlMapping.mmd;
        MapMetaData mapmd = mmd.getMap();
        // Find the table forming the Map. This may be a join table, or the key or value depending on the type
        if (mapKey) {
            // Cater for all case possibilities of table name/alias
            // TODO Use OPTION_CASE_INSENSITIVE
            SQLTable mapSqlTbl = stmt.getTable(first + "_MAP");
            if (mapSqlTbl == null) {
                mapSqlTbl = stmt.getTable((first + "_MAP").toUpperCase());
                if (mapSqlTbl == null) {
                    mapSqlTbl = stmt.getTable((first + "_MAP").toLowerCase());
                }
            }
            if (mapSqlTbl != null) {
                sqlTbl = mapSqlTbl;
            }
        }
        if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
            if (sqlTbl.getTable() instanceof MapTable) {
                MapTable mapTable = (MapTable) sqlTbl.getTable();
                if (mapKey) {
                    cmd = mapmd.getKeyClassMetaData(clr);
                    if (!mapmd.isEmbeddedKey() && !mapmd.isSerializedKey()) {
                        // Join to key table
                        DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
                        sqlTbl = stmt.join(getDefaultJoinTypeForNavigation(), sqlMapping.table, mapTable.getKeyMapping(), keyTable, null, keyTable.getIdMapping(), null, null, true);
                        mapping = keyTable.getIdMapping();
                    } else {
                        mapping = mapTable.getKeyMapping();
                    }
                } else {
                    cmd = mapmd.getValueClassMetaData(clr);
                    if (!mapmd.isEmbeddedValue() && !mapmd.isSerializedValue()) {
                        // Join to value table
                        DatastoreClass valueTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
                        sqlTbl = stmt.join(getDefaultJoinTypeForNavigation(), sqlMapping.table, mapTable.getValueMapping(), valueTable, null, valueTable.getIdMapping(), null, null, true);
                        mapping = valueTable.getIdMapping();
                    } else {
                        mapping = mapTable.getValueMapping();
                    }
                }
            } else {
                // TODO Document exactly which situation this is
                if (!mapmd.isEmbeddedValue() && !mapmd.isSerializedValue()) {
                    mapping = sqlTbl.getTable().getIdMapping();
                }
            }
        } else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
            if (mapKey) {
                AbstractClassMetaData keyCmd = mapmd.getKeyClassMetaData(clr);
                String keyMappedBy = mmd.getKeyMetaData().getMappedBy();
                mapping = ((DatastoreClass) sqlTbl.getTable()).getMemberMapping(keyMappedBy);
                if (keyCmd != null) {
                    // Join to key table
                    DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
                    sqlTbl = stmt.join(getDefaultJoinTypeForNavigation(), sqlMapping.table, mapping, keyTable, null, keyTable.getIdMapping(), null, null, true);
                    mapping = keyTable.getIdMapping();
                }
            } else {
            }
        } else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
            // TODO We maybe already have the VALUE TABLE from the original join
            if (!mapKey) {
                AbstractClassMetaData valCmd = mapmd.getValueClassMetaData(clr);
                String valMappedBy = mmd.getValueMetaData().getMappedBy();
                mapping = ((DatastoreClass) sqlTbl.getTable()).getMemberMapping(valMappedBy);
                if (valCmd != null) {
                    // Join to value table
                    DatastoreClass valueTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
                    sqlTbl = stmt.join(getDefaultJoinTypeForNavigation(), sqlMapping.table, mapping, valueTable, null, valueTable.getIdMapping(), null, null, true);
                    mapping = valueTable.getIdMapping();
                }
            }
        }
        sqlMapping = new SQLTableMapping(sqlTbl, cmd, mapping);
    }
    while (iter.hasNext()) {
        String component = iter.next();
        // fully-qualified primary name
        primaryName += "." + component;
        // Derive SQLTableMapping for this component
        SQLTableMapping sqlMappingNew = getSQLTableMappingForAlias(primaryName);
        if (sqlMappingNew == null) {
            // Table not present for this primary
            AbstractMemberMetaData mmd = cmd.getMetaDataForMember(component);
            if (mmd == null) {
                // Not valid member name
                throw new NucleusUserException(Localiser.msg("021062", component, cmd.getFullClassName()));
            } else if (mmd.getPersistenceModifier() != FieldPersistenceModifier.PERSISTENT) {
                throw new NucleusUserException("Field " + mmd.getFullFieldName() + " is not marked as persistent so cannot be queried");
            }
            RelationType relationType = mmd.getRelationType(clr);
            // Find the table and the mapping for this field in the table
            SQLTable sqlTbl = null;
            if (mapping instanceof EmbeddedMapping) {
                // Embedded into the current table
                sqlTbl = sqlMapping.table;
                mapping = ((EmbeddedMapping) mapping).getJavaTypeMapping(component);
            } else if (mapping instanceof PersistableMapping && cmd.isEmbeddedOnly()) {
                // JPA EmbeddedId into current table
                sqlTbl = sqlMapping.table;
                JavaTypeMapping[] subMappings = ((PersistableMapping) mapping).getJavaTypeMapping();
                if (subMappings.length == 1 && subMappings[0] instanceof EmbeddedPCMapping) {
                    mapping = ((EmbeddedPCMapping) subMappings[0]).getJavaTypeMapping(component);
                } else {
                // TODO What situation is this?
                }
            } else {
                DatastoreClass table = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr);
                if (table == null) {
                    if (cmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE && candidateCmd.getFullClassName().equals(cmd.getFullClassName())) {
                        // Special case of a candidate having no table of its own and using COMPLETE_TABLE, so we use the candidate class for this statement (or UNION)
                        table = storeMgr.getDatastoreClass(stmt.getCandidateClassName(), clr);
                    }
                }
                if (table == null) {
                    AbstractClassMetaData[] subCmds = storeMgr.getClassesManagingTableForClass(cmd, clr);
                    if (subCmds.length == 1) {
                        table = storeMgr.getDatastoreClass(subCmds[0].getFullClassName(), clr);
                    } else {
                        // all of UNIONs, and this primary expression refers to a mapping in each of subclass tables
                        throw new NucleusUserException("Unable to find table for primary " + primaryName + " since the class " + cmd.getFullClassName() + " is managed in multiple tables");
                    }
                }
                if (table == null) {
                    throw new NucleusUserException("Unable to find table for primary " + primaryName + ". Table for class=" + cmd.getFullClassName() + " is null : is the field correct? or using some inheritance pattern?");
                }
                mapping = table.getMemberMapping(mmd);
                sqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(theStmt, sqlMapping.table, mapping);
            }
            if (relationType == RelationType.NONE) {
                sqlMappingNew = new SQLTableMapping(sqlTbl, cmd, mapping);
                cmd = sqlMappingNew.cmd;
                setSQLTableMappingForAlias(primaryName, sqlMappingNew);
            } else if (relationType == RelationType.ONE_TO_ONE_UNI || relationType == RelationType.ONE_TO_ONE_BI) {
                if (mmd.getMappedBy() != null) {
                    // FK in other table so join to that first
                    AbstractMemberMetaData relMmd = mmd.getRelatedMemberMetaData(clr)[0];
                    if (relMmd.getAbstractClassMetaData().isEmbeddedOnly()) {
                        // Member is embedded, so keep same SQL table mapping
                        sqlMappingNew = sqlMapping;
                        cmd = relMmd.getAbstractClassMetaData();
                    } else {
                        // Member is in own table, so move to that SQL table mapping
                        DatastoreClass relTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
                        JavaTypeMapping relMapping = relTable.getMemberMapping(relMmd);
                        // Join to related table unless we already have the join in place
                        sqlTbl = theStmt.getTable(relTable, primaryName);
                        if (sqlTbl == null) {
                            sqlTbl = SQLStatementHelper.addJoinForOneToOneRelation(theStmt, sqlMapping.table.getTable().getIdMapping(), sqlMapping.table, relMapping, relTable, null, null, primaryName, getDefaultJoinTypeForNavigation());
                        }
                        if (iter.hasNext()) {
                            sqlMappingNew = new SQLTableMapping(sqlTbl, relMmd.getAbstractClassMetaData(), relTable.getIdMapping());
                            cmd = sqlMappingNew.cmd;
                        } else {
                            sqlMappingNew = new SQLTableMapping(sqlTbl, cmd, relTable.getIdMapping());
                            cmd = sqlMappingNew.cmd;
                        }
                    }
                } else {
                    // FK is at this side
                    if (forceJoin == null) {
                        if (!iter.hasNext()) {
                            // Further component provided, so check if we should force a join to the other side
                            if (primExpr.getParent() != null && primExpr.getParent().getOperator() == Expression.OP_CAST) {
                                // Cast and not an interface field, so do a join to the table of the persistable object
                                if (mapping instanceof ReferenceMapping) {
                                // Don't join with interface field since represents multiple implementations
                                // and the cast will be a restrict on which implementation to join to
                                } else {
                                    AbstractClassMetaData relCmd = ec.getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
                                    if (relCmd != null && !relCmd.isEmbeddedOnly()) {
                                        DatastoreClass relTable = storeMgr.getDatastoreClass(relCmd.getFullClassName(), clr);
                                        if (relTable == null) {
                                        } else {
                                            forceJoin = Boolean.TRUE;
                                        }
                                    } else {
                                        forceJoin = Boolean.TRUE;
                                    }
                                }
                            }
                        } else {
                            // TODO Add optimisation to omit join if the FK is at this side and only selecting PK of the related object
                            if (iter.hasNext()) {
                                // Peek ahead to see if just selecting "id" of the related (i.e candidate.related.id with related FK in candidate table, so don't join)
                                String next = iter.next();
                                if (!iter.hasNext()) {
                                    AbstractClassMetaData relCmd = storeMgr.getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
                                    if (relCmd != null) {
                                        AbstractMemberMetaData mmdOfRelCmd = relCmd.getMetaDataForMember(next);
                                        if (mmdOfRelCmd != null && mmdOfRelCmd.isPrimaryKey() && relCmd.getNoOfPrimaryKeyMembers() == 1 && !storeMgr.getMetaDataManager().isClassPersistable(mmdOfRelCmd.getTypeName())) {
                                            // We have something like "a.b.id" and have the FK to the "B" table in the "A" table, so just refer to A.FK rather than joining and using B.ID
                                            NucleusLogger.QUERY.debug("Found implicit join to member=" + mmdOfRelCmd.getFullFieldName() + " which is PK of the other type but FK is in this table so avoiding the join");
                                            JavaTypeMapping subMapping = ((PersistableMapping) mapping).getJavaTypeMapping()[0];
                                            // Component mappings of a PersistableMapping sometimes don't have table set, so fix it
                                            subMapping.setTable(mapping.getTable());
                                            return new SQLTableMapping(sqlMapping.table, relCmd, subMapping);
                                        }
                                    }
                                }
                                iter.previous();
                            }
                        }
                    }
                    if (iter.hasNext() || Boolean.TRUE.equals(forceJoin)) {
                        AbstractClassMetaData relCmd = null;
                        JavaTypeMapping relMapping = null;
                        DatastoreClass relTable = null;
                        if (relationType == RelationType.ONE_TO_ONE_BI) {
                            AbstractMemberMetaData relMmd = mmd.getRelatedMemberMetaData(clr)[0];
                            relCmd = relMmd.getAbstractClassMetaData();
                        } else {
                            String typeName = mmd.isSingleCollection() ? mmd.getCollection().getElementType() : mmd.getTypeName();
                            relCmd = ec.getMetaDataManager().getMetaDataForClass(typeName, clr);
                        }
                        if (relCmd != null && relCmd.isEmbeddedOnly()) {
                            // Member is embedded so use same table but embedded mapping
                            sqlMappingNew = new SQLTableMapping(sqlTbl, relCmd, mapping);
                            cmd = relCmd;
                        } else {
                            // Member is in own table, so move to that SQL table mapping
                            relTable = storeMgr.getDatastoreClass(relCmd.getFullClassName(), clr);
                            if (relTable == null) {
                                // No table for the related type (subclass-table), so see if this class has a single subclass with its own table
                                Collection<String> relSubclassNames = storeMgr.getSubClassesForClass(relCmd.getFullClassName(), false, clr);
                                if (relSubclassNames != null && relSubclassNames.size() == 1) {
                                    String relSubclassName = relSubclassNames.iterator().next();
                                    relTable = storeMgr.getDatastoreClass(relSubclassName, clr);
                                    // TODO Cater for this having no table and next level yes etc
                                    if (relTable != null) {
                                        relCmd = ec.getMetaDataManager().getMetaDataForClass(relSubclassName, clr);
                                    }
                                }
                                if (relTable == null) {
                                    // No table as such, so likely using subclass-table at other side and we don't know where to join to
                                    throw new NucleusUserException("Reference to PrimaryExpression " + primExpr + " yet this needs to join relation " + mmd.getFullFieldName() + " and the other type has no table (subclass-table?). Maybe use a CAST to the appropriate subclass?");
                                }
                            }
                            relMapping = relTable.getIdMapping();
                            // Join to other table unless we already have the join in place
                            sqlTbl = theStmt.getTable(relTable, primaryName);
                            if (sqlTbl == null) {
                                sqlTbl = SQLStatementHelper.addJoinForOneToOneRelation(theStmt, mapping, sqlMapping.table, relMapping, relTable, null, null, primaryName, getDefaultJoinTypeForNavigation());
                            }
                            sqlMappingNew = new SQLTableMapping(sqlTbl, relCmd, relMapping);
                            cmd = sqlMappingNew.cmd;
                            setSQLTableMappingForAlias(primaryName, sqlMappingNew);
                        }
                    } else {
                        sqlMappingNew = new SQLTableMapping(sqlTbl, cmd, mapping);
                        cmd = sqlMappingNew.cmd;
                    // Don't register the SQLTableMapping for this alias since only using FK
                    }
                }
            } else if (relationType == RelationType.MANY_TO_ONE_BI) {
                AbstractMemberMetaData relMmd = mmd.getRelatedMemberMetaData(clr)[0];
                DatastoreClass relTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
                if (mmd.getJoinMetaData() != null || relMmd.getJoinMetaData() != null) {
                    // Has join table so use that
                    sqlTbl = theStmt.getTable(relTable, primaryName);
                    if (sqlTbl == null) {
                        // Join to the join table
                        CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(relMmd);
                        JoinType defJoinType = getDefaultJoinTypeForNavigation();
                        if (defJoinType == JoinType.INNER_JOIN) {
                            SQLTable joinSqlTbl = theStmt.join(JoinType.INNER_JOIN, sqlMapping.table, sqlMapping.table.getTable().getIdMapping(), joinTbl, null, joinTbl.getElementMapping(), null, null, true);
                            sqlTbl = theStmt.join(JoinType.INNER_JOIN, joinSqlTbl, joinTbl.getOwnerMapping(), relTable, null, relTable.getIdMapping(), null, primaryName, true);
                        } else if (defJoinType == JoinType.LEFT_OUTER_JOIN || defJoinType == null) {
                            SQLTable joinSqlTbl = theStmt.join(JoinType.LEFT_OUTER_JOIN, sqlMapping.table, sqlMapping.table.getTable().getIdMapping(), joinTbl, null, joinTbl.getElementMapping(), null, null, true);
                            sqlTbl = theStmt.join(JoinType.LEFT_OUTER_JOIN, joinSqlTbl, joinTbl.getOwnerMapping(), relTable, null, relTable.getIdMapping(), null, primaryName, true);
                        }
                    }
                    sqlMappingNew = new SQLTableMapping(sqlTbl, relMmd.getAbstractClassMetaData(), relTable.getIdMapping());
                    cmd = sqlMappingNew.cmd;
                    setSQLTableMappingForAlias(primaryName, sqlMappingNew);
                } else {
                    // FK in this table
                    sqlTbl = theStmt.getTable(relTable, primaryName);
                    if (sqlTbl == null) {
                        if (mmd.getMappedBy() == null) {
                            // FK at this side so check for optimisations
                            if (iter.hasNext()) {
                                // Peek ahead to see if just selecting "id" of the related (i.e candidate.related.id with related FK in candidate table, so don't join)
                                String next = iter.next();
                                if (!iter.hasNext()) {
                                    AbstractClassMetaData relCmd = relMmd.getAbstractClassMetaData();
                                    AbstractMemberMetaData mmdOfRelCmd = relCmd.getMetaDataForMember(next);
                                    if (mmdOfRelCmd != null && mmdOfRelCmd.isPrimaryKey() && relCmd.getNoOfPrimaryKeyMembers() == 1 && !storeMgr.getMetaDataManager().isClassPersistable(mmdOfRelCmd.getTypeName())) {
                                        // We have something like "a.b.id" and have the FK to the "B" table in the "A" table, so just refer to A.FK rather than joining and using B.ID
                                        NucleusLogger.QUERY.debug("Found implicit join to member=" + mmdOfRelCmd.getFullFieldName() + " which is PK of the other type but FK is in this table so avoiding the join");
                                        JavaTypeMapping subMapping = ((PersistableMapping) mapping).getJavaTypeMapping()[0];
                                        // Component mappings of a PersistableMapping sometimes don't have table set, so fix it
                                        subMapping.setTable(mapping.getTable());
                                        return new SQLTableMapping(sqlMapping.table, relCmd, subMapping);
                                    }
                                }
                                iter.previous();
                            }
                        }
                        Operator op = (primExpr.getParent() != null ? primExpr.getParent().getOperator() : null);
                        if (!iter.hasNext() && (op == Expression.OP_EQ || op == Expression.OP_GT || op == Expression.OP_LT || op == Expression.OP_GTEQ || op == Expression.OP_LTEQ || op == Expression.OP_NOTEQ)) {
                            // Just return the FK mapping since in a "a.b == c.d" type expression and not needing to go further than the FK
                            sqlMappingNew = new SQLTableMapping(sqlMapping.table, relMmd.getAbstractClassMetaData(), mapping);
                        } else {
                            // Join to the related table
                            JoinType defJoinType = getDefaultJoinTypeForNavigation();
                            if (defJoinType == JoinType.INNER_JOIN) {
                                sqlTbl = theStmt.join(JoinType.INNER_JOIN, sqlMapping.table, mapping, relTable, null, relTable.getIdMapping(), null, primaryName, true);
                            } else if (defJoinType == JoinType.LEFT_OUTER_JOIN || defJoinType == null) {
                                sqlTbl = theStmt.join(JoinType.LEFT_OUTER_JOIN, sqlMapping.table, mapping, relTable, null, relTable.getIdMapping(), null, primaryName, true);
                            }
                            sqlMappingNew = new SQLTableMapping(sqlTbl, relMmd.getAbstractClassMetaData(), relTable.getIdMapping());
                            cmd = sqlMappingNew.cmd;
                            setSQLTableMappingForAlias(primaryName, sqlMappingNew);
                        }
                    } else {
                        sqlMappingNew = new SQLTableMapping(sqlTbl, relMmd.getAbstractClassMetaData(), relTable.getIdMapping());
                        cmd = sqlMappingNew.cmd;
                        setSQLTableMappingForAlias(primaryName, sqlMappingNew);
                    }
                }
            } else if (RelationType.isRelationMultiValued(relationType)) {
                // Can't reference further than a collection/map so just return its mapping here
                sqlMappingNew = new SQLTableMapping(sqlTbl, cmd, mapping);
                cmd = sqlMappingNew.cmd;
                setSQLTableMappingForAlias(primaryName, sqlMappingNew);
            }
        } else {
            cmd = sqlMappingNew.cmd;
        }
        sqlMapping = sqlMappingNew;
    }
    return sqlMapping;
}
Also used : Operator(org.datanucleus.store.query.expression.Expression.Operator) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedPCMapping) JoinType(org.datanucleus.store.rdbms.sql.SQLJoin.JoinType) MapMetaData(org.datanucleus.metadata.MapMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) MapTable(org.datanucleus.store.rdbms.table.MapTable) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) EmbeddedMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedMapping) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) RelationType(org.datanucleus.metadata.RelationType) Collection(java.util.Collection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 17 with ReferenceMapping

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

the class AbstractRDBMSQueryResult method registerMemberBulkResultSet.

public void registerMemberBulkResultSet(IteratorStatement iterStmt, ResultSet rs) {
    if (bulkLoadedValueByMemberNumber == null) {
        bulkLoadedValueByMemberNumber = new HashMap<>();
    }
    try {
        ExecutionContext ec = query.getExecutionContext();
        AbstractMemberMetaData mmd = iterStmt.getBackingStore().getOwnerMemberMetaData();
        if (mmd.hasCollection() || mmd.hasArray()) {
            ElementIteratorStatement elemIterStmt = (ElementIteratorStatement) iterStmt;
            ElementContainerStore backingStore = (ElementContainerStore) iterStmt.getBackingStore();
            if (backingStore.isElementsAreEmbedded() || backingStore.isElementsAreSerialised()) {
                int[] param = new int[backingStore.getElementMapping().getNumberOfColumnMappings()];
                for (int i = 0; i < param.length; ++i) {
                    param[i] = i + 1;
                }
                if (backingStore.getElementMapping() instanceof SerialisedPCMapping || backingStore.getElementMapping() instanceof SerialisedReferenceMapping || backingStore.getElementMapping() instanceof EmbeddedElementPCMapping) {
                    // Element = Serialised
                    while (rs.next()) {
                        Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
                        Object element = backingStore.getElementMapping().getObject(ec, rs, param, ec.findStateManager(owner), backingStore.getOwnerMemberMetaData().getAbsoluteFieldNumber());
                        addOwnerMemberCollectionElement(mmd, owner, element);
                    }
                } else {
                    // Element = Non-PC
                    while (rs.next()) {
                        Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
                        Object element = backingStore.getElementMapping().getObject(ec, rs, param);
                        addOwnerMemberCollectionElement(mmd, owner, element);
                    }
                }
            } else if (backingStore.getElementMapping() instanceof ReferenceMapping) {
                // Element is Reference (interface/Object) so just use elementMapping
                int[] param = new int[backingStore.getElementMapping().getNumberOfColumnMappings()];
                for (int i = 0; i < param.length; ++i) {
                    param[i] = i + 1;
                }
                while (rs.next()) {
                    Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
                    Object element = backingStore.getElementMapping().getObject(ec, rs, param);
                    addOwnerMemberCollectionElement(mmd, owner, element);
                }
            } else {
                String elementType = mmd.hasCollection() ? backingStore.getOwnerMemberMetaData().getCollection().getElementType() : backingStore.getOwnerMemberMetaData().getArray().getElementType();
                ResultObjectFactory<E> scoROF = new PersistentClassROF(ec, rs, query.getIgnoreCache(), fp, elemIterStmt.getElementClassMapping(), backingStore.getElementClassMetaData(), ec.getClassLoaderResolver().classForName(elementType));
                while (rs.next()) {
                    Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
                    Object element = scoROF.getObject();
                    addOwnerMemberCollectionElement(mmd, owner, element);
                }
            }
        } else if (mmd.hasMap()) {
        // TODO Cater for maps
        }
    } catch (SQLException sqle) {
        NucleusLogger.DATASTORE.error("Exception thrown processing bulk loaded field " + iterStmt.getBackingStore().getOwnerMemberMetaData().getFullFieldName(), sqle);
    } finally {
        // Close the ResultSet (and its Statement)
        try {
            Statement stmt = null;
            try {
                stmt = rs.getStatement();
                // Close the result set
                rs.close();
            } catch (SQLException e) {
                NucleusLogger.DATASTORE.error(Localiser.msg("052605", e));
            } finally {
                try {
                    if (stmt != null) {
                        // Close the original statement
                        stmt.close();
                    }
                } catch (SQLException e) {
                // Do nothing
                }
            }
        } finally {
            rs = null;
        }
    }
}
Also used : SerialisedReferenceMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedReferenceMapping) SQLException(java.sql.SQLException) ElementIteratorStatement(org.datanucleus.store.rdbms.scostore.ElementIteratorStatement) Statement(java.sql.Statement) IteratorStatement(org.datanucleus.store.rdbms.scostore.IteratorStatement) ElementIteratorStatement(org.datanucleus.store.rdbms.scostore.ElementIteratorStatement) ElementContainerStore(org.datanucleus.store.rdbms.scostore.ElementContainerStore) EmbeddedElementPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedElementPCMapping) ExecutionContext(org.datanucleus.ExecutionContext) SerialisedReferenceMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedReferenceMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) SerialisedPCMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedPCMapping) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 18 with ReferenceMapping

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

the class JoinArrayStore method iterator.

@Override
public Iterator<E> iterator(DNStateManager ownerSM) {
    ExecutionContext ec = ownerSM.getExecutionContext();
    // Generate the statement, and statement mapping/parameter information
    ElementIteratorStatement iterStmt = getIteratorStatement(ec, ec.getFetchPlan(), true);
    SelectStatement sqlStmt = iterStmt.sqlStmt;
    StatementClassMapping iteratorMappingClass = iterStmt.elementClassMapping;
    // Input parameter(s) - the owner
    int inputParamNum = 1;
    StatementMappingIndex ownerIdx = new StatementMappingIndex(ownerMapping);
    if (sqlStmt.getNumberOfUnions() > 0) {
        // Add parameter occurrence for each union of statement
        for (int j = 0; j < sqlStmt.getNumberOfUnions() + 1; j++) {
            int[] paramPositions = new int[ownerMapping.getNumberOfColumnMappings()];
            for (int k = 0; k < paramPositions.length; k++) {
                paramPositions[k] = inputParamNum++;
            }
            ownerIdx.addParameterOccurrence(paramPositions);
        }
    } else {
        int[] paramPositions = new int[ownerMapping.getNumberOfColumnMappings()];
        for (int k = 0; k < paramPositions.length; k++) {
            paramPositions[k] = inputParamNum++;
        }
        ownerIdx.addParameterOccurrence(paramPositions);
    }
    StatementParameterMapping iteratorMappingParams = new StatementParameterMapping();
    iteratorMappingParams.addMappingForParameter("owner", ownerIdx);
    if (ec.getTransaction().getSerializeRead() != null && ec.getTransaction().getSerializeRead()) {
        sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
    }
    String stmt = sqlStmt.getSQLText().toSQL();
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            // Create the statement
            PreparedStatement ps = sqlControl.getStatementForQuery(mconn, stmt);
            // Set the owner
            DNStateManager stmtOwnerSM = BackingStoreHelper.getOwnerStateManagerForBackingStore(ownerSM);
            int numParams = ownerIdx.getNumberOfParameterOccurrences();
            for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
                ownerIdx.getMapping().setObject(ec, ps, ownerIdx.getParameterPositionsForOccurrence(paramInstance), stmtOwnerSM.getObject());
            }
            try {
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, stmt, ps);
                try {
                    if (elementsAreEmbedded || elementsAreSerialised) {
                        // No ResultObjectFactory needed - handled by SetStoreIterator
                        return new ArrayStoreIterator(ownerSM, rs, null, this);
                    } else if (elementMapping instanceof ReferenceMapping) {
                        // No ResultObjectFactory needed - handled by SetStoreIterator
                        return new ArrayStoreIterator(ownerSM, rs, null, this);
                    } else {
                        ResultObjectFactory rof = new PersistentClassROF(ec, rs, false, ec.getFetchPlan(), iteratorMappingClass, elementCmd, clr.classForName(elementType));
                        return new ArrayStoreIterator(ownerSM, rs, rof, this);
                    }
                } finally {
                    rs.close();
                }
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException e) {
        throw new NucleusDataStoreException(Localiser.msg("056006", stmt), e);
    }
}
Also used : StatementParameterMapping(org.datanucleus.store.rdbms.query.StatementParameterMapping) SQLException(java.sql.SQLException) ResultObjectFactory(org.datanucleus.store.rdbms.query.ResultObjectFactory) PreparedStatement(java.sql.PreparedStatement) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) SQLController(org.datanucleus.store.rdbms.SQLController) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) PersistentClassROF(org.datanucleus.store.rdbms.query.PersistentClassROF) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) DNStateManager(org.datanucleus.state.DNStateManager)

Example 19 with ReferenceMapping

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

the class FetchRequest method processMemberToFetch.

/**
 * Method to process the specified member.
 * @param mmd MetaData for the member
 * @param fpClass FetchPlan for class
 * @param clr ClassLoader resolver
 * @param fetchCallbacks Any fetch callbacks to register the mapping with
 * @param sqlStmt The SELECT statement
 * @param sqlTbl The SQL table (of the candidate)
 * @param mappingDef The mapping definition for this statement
 * @param store Whether we are just selecting the value of this member for storing (rather than fetching)
 * @param memberNumbersToStore List of member numbers that are approved to be stored (any fetched ones will be added if recursionDepth=0)
 * @return Whether this member is selected in the statement
 */
boolean processMemberToFetch(AbstractMemberMetaData mmd, FetchPlanForClass fpClass, ClassLoaderResolver clr, Collection fetchCallbacks, SelectStatement sqlStmt, SQLTable sqlTbl, StatementClassMapping mappingDef, List<Integer> memberNumbersToStore) {
    boolean selected = false;
    JavaTypeMapping mapping = table.getMemberMapping(mmd);
    if (mapping != null) {
        if (!mmd.isPrimaryKey() && mapping.includeInFetchStatement()) {
            // The depth is the number of levels down to load in this statement : 0 is to load just this objects fields
            int depth = 0;
            AbstractMemberMetaData mmdToUse = mmd;
            JavaTypeMapping mappingToUse = mapping;
            if (mapping instanceof SingleCollectionMapping) {
                // Check the wrapped type
                mappingToUse = ((SingleCollectionMapping) mapping).getWrappedMapping();
                mmdToUse = ((SingleCollectionMapping) mapping).getWrappedMapping().getMemberMetaData();
            }
            boolean fetchAndSaveFK = false;
            if (mappingToUse instanceof PersistableMapping) {
                if (RelationType.isRelationSingleValued(mmd.getRelationType(clr)) && fpClass.getRecursionDepthForMember(mmd.getAbsoluteFieldNumber()) == 0) {
                    // Special case of 1-1/N-1 and recursion-depth set as 0 (just retrieve the FK and don't instantiate the related object in the field)
                    depth = 0;
                    fetchAndSaveFK = true;
                } else if (mmd.fetchFKOnly()) {
                    // Special case of 1-1/N-1 and fetch-fk-only extension - same as above
                    depth = 0;
                    fetchAndSaveFK = true;
                } else {
                    // Special case of 1-1/N-1 where we know the other side type so know what to join to and can load the related object
                    depth = 1;
                    if (Modifier.isAbstract(mmdToUse.getType().getModifiers())) {
                        String typeName = mmdToUse.getTypeName();
                        DatastoreClass relTable = table.getStoreManager().getDatastoreClass(typeName, clr);
                        if (relTable != null && relTable.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, false) == null) {
                            // 1-1 relation to base class with no discriminator and has subclasses
                            // hence no way of determining the exact type, hence no point in fetching it
                            String[] subclasses = table.getStoreManager().getMetaDataManager().getSubclassesForClass(typeName, false);
                            if (subclasses != null && subclasses.length > 0) {
                                depth = 0;
                            }
                        }
                    }
                }
            } else if (mappingToUse instanceof ReferenceMapping) {
                ReferenceMapping refMapping = (ReferenceMapping) mappingToUse;
                if (refMapping.getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
                    JavaTypeMapping[] subMappings = refMapping.getJavaTypeMapping();
                    if (subMappings != null && subMappings.length == 1) {
                        // Support special case of reference mapping with single implementation possible
                        depth = 1;
                    }
                }
            }
            // TODO We should use the actual FetchPlan, and the max fetch depth, so then it can pull in all related objects within reach.
            // But this will mean we cannot cache the statement, since it is for a specific ExecutionContext
            // TODO If this field is a 1-1 and the other side has a discriminator or version then we really ought to fetch it
            SQLStatementHelper.selectMemberOfSourceInStatement(sqlStmt, mappingDef, null, sqlTbl, mmd, clr, depth, null);
            if (fetchAndSaveFK) {
                memberNumbersToStore.add(mmd.getAbsoluteFieldNumber());
            }
            selected = true;
        }
        if (mapping instanceof MappingCallbacks) {
            // TODO Need to add that this mapping is for base object or base.field1, etc
            fetchCallbacks.add(mapping);
        }
    }
    return selected;
}
Also used : PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) MappingCallbacks(org.datanucleus.store.rdbms.mapping.MappingCallbacks) SingleCollectionMapping(org.datanucleus.store.rdbms.mapping.java.SingleCollectionMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 20 with ReferenceMapping

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

the class ClassTable method getExpectedIndices.

/**
 * Accessor for the indices for this table. This includes both the
 * user-defined indices (via MetaData), and the ones required by foreign
 * keys (required by relationships).
 * @param clr The ClassLoaderResolver
 * @return The indices
 */
@Override
protected Set<Index> getExpectedIndices(ClassLoaderResolver clr) {
    // Auto mode allows us to decide which indices are needed as well as using what is in the users MetaData
    boolean autoMode = false;
    if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus")) {
        autoMode = true;
    }
    Set<Index> indices = new HashSet();
    // Add on any user-required indices for the fields/properties
    Set memberNumbersSet = memberMappingsMap.keySet();
    Iterator iter = memberNumbersSet.iterator();
    while (iter.hasNext()) {
        AbstractMemberMetaData fmd = (AbstractMemberMetaData) iter.next();
        JavaTypeMapping fieldMapping = memberMappingsMap.get(fmd);
        if (fieldMapping instanceof EmbeddedPCMapping) {
            // Add indexes for fields of this embedded PC object
            EmbeddedPCMapping embMapping = (EmbeddedPCMapping) fieldMapping;
            for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
                JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
                IndexMetaData imd = embFieldMapping.getMemberMetaData().getIndexMetaData();
                if (imd != null) {
                    Index index = TableUtils.getIndexForField(this, imd, embFieldMapping);
                    if (index != null) {
                        indices.add(index);
                    }
                }
            }
        } else if (fieldMapping instanceof SerialisedMapping) {
        // Don't index these
        } else {
            // Add any required index for this field
            IndexMetaData imd = fmd.getIndexMetaData();
            if (imd != null) {
                // Index defined so add it
                Index index = TableUtils.getIndexForField(this, imd, fieldMapping);
                if (index != null) {
                    indices.add(index);
                }
            } else if (autoMode) {
                if (fmd.getIndexed() == null) {
                    // Indexing not set, so add where we think it is appropriate
                    if (// Ignore PKs since they will be indexed anyway
                    !fmd.isPrimaryKey()) {
                        // TODO Some RDBMS create index automatically for all FK cols so we don't need to really
                        RelationType relationType = fmd.getRelationType(clr);
                        if (relationType == RelationType.ONE_TO_ONE_UNI) {
                            // 1-1 with FK at this side so index the FK
                            if (fieldMapping instanceof ReferenceMapping) {
                                ReferenceMapping refMapping = (ReferenceMapping) fieldMapping;
                                if (refMapping.getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
                                    // Cols per implementation : index each of implementations
                                    if (refMapping.getJavaTypeMapping() != null) {
                                        int colNum = 0;
                                        JavaTypeMapping[] implMappings = refMapping.getJavaTypeMapping();
                                        for (int i = 0; i < implMappings.length; i++) {
                                            int numColsInImpl = implMappings[i].getNumberOfColumnMappings();
                                            Index index = new Index(this, false, null);
                                            for (int j = 0; j < numColsInImpl; j++) {
                                                index.setColumn(j, fieldMapping.getColumnMapping(colNum++).getColumn());
                                            }
                                            indices.add(index);
                                        }
                                    }
                                }
                            } else {
                                Index index = new Index(this, false, null);
                                for (int i = 0; i < fieldMapping.getNumberOfColumnMappings(); i++) {
                                    index.setColumn(i, fieldMapping.getColumnMapping(i).getColumn());
                                }
                                indices.add(index);
                            }
                        } else if (relationType == RelationType.ONE_TO_ONE_BI && fmd.getMappedBy() == null) {
                            // 1-1 with FK at this side so index the FK
                            Index index = new Index(this, false, null);
                            for (int i = 0; i < fieldMapping.getNumberOfColumnMappings(); i++) {
                                index.setColumn(i, fieldMapping.getColumnMapping(i).getColumn());
                            }
                            indices.add(index);
                        } else if (relationType == RelationType.MANY_TO_ONE_BI) {
                            // N-1 with FK at this side so index the FK
                            AbstractMemberMetaData relMmd = fmd.getRelatedMemberMetaData(clr)[0];
                            if (relMmd.getJoinMetaData() == null && fmd.getJoinMetaData() == null) {
                                if (fieldMapping.getNumberOfColumnMappings() > 0) {
                                    Index index = new Index(this, false, null);
                                    for (int i = 0; i < fieldMapping.getNumberOfColumnMappings(); i++) {
                                        index.setColumn(i, fieldMapping.getColumnMapping(i).getColumn());
                                    }
                                    indices.add(index);
                                } else {
                                    // TODO How do we get this?
                                    NucleusLogger.DATASTORE_SCHEMA.warn("Table " + this + " manages member " + fmd.getFullFieldName() + " which is a N-1 but there is no column for this mapping so not adding index!");
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    // Check if any version column needs indexing
    if (versionMapping != null) {
        IndexMetaData idxmd = getVersionMetaData().getIndexMetaData();
        if (idxmd != null) {
            Index index = new Index(this, idxmd.isUnique(), idxmd.getExtensions());
            if (idxmd.getName() != null) {
                index.setName(idxmd.getName());
            }
            int countVersionFields = versionMapping.getNumberOfColumnMappings();
            for (int i = 0; i < countVersionFields; i++) {
                index.addColumn(versionMapping.getColumnMapping(i).getColumn());
            }
            indices.add(index);
        }
    }
    // Check if any discriminator column needs indexing
    if (discriminatorMapping != null) {
        DiscriminatorMetaData dismd = getDiscriminatorMetaData();
        IndexMetaData idxmd = dismd.getIndexMetaData();
        if (idxmd != null) {
            Index index = new Index(this, idxmd.isUnique(), idxmd.getExtensions());
            if (idxmd.getName() != null) {
                index.setName(idxmd.getName());
            }
            int numCols = discriminatorMapping.getNumberOfColumnMappings();
            for (int i = 0; i < numCols; i++) {
                index.addColumn(discriminatorMapping.getColumnMapping(i).getColumn());
            }
            indices.add(index);
        }
    }
    // Check if multitenancy discriminator present and needs indexing
    if (multitenancyMapping != null) {
        MultitenancyMetaData mtmd = cmd.getMultitenancyMetaData();
        IndexMetaData idxmd = mtmd.getIndexMetaData();
        if (idxmd != null) {
            Index index = new Index(this, false, null);
            if (idxmd.getName() != null) {
                index.setName(idxmd.getName());
            }
            int numCols = multitenancyMapping.getNumberOfColumnMappings();
            for (int i = 0; i < numCols; i++) {
                index.addColumn(multitenancyMapping.getColumnMapping(i).getColumn());
            }
            indices.add(index);
        }
    }
    // Check if soft delete column present and needs indexing
    if (softDeleteMapping != null) {
        SoftDeleteMetaData sdmd = cmd.getSoftDeleteMetaData();
        IndexMetaData idxmd = sdmd.getIndexMetaData();
        if (idxmd != null) {
            Index index = new Index(this, false, null);
            if (idxmd.getName() != null) {
                index.setName(idxmd.getName());
            }
            int numCols = softDeleteMapping.getNumberOfColumnMappings();
            for (int i = 0; i < numCols; i++) {
                index.addColumn(softDeleteMapping.getColumnMapping(i).getColumn());
            }
            indices.add(index);
        }
    }
    // Add on any order fields (for lists, arrays, collections) that need indexing
    Set orderMappingsEntries = getExternalOrderMappings().entrySet();
    Iterator orderMappingsEntriesIter = orderMappingsEntries.iterator();
    while (orderMappingsEntriesIter.hasNext()) {
        Map.Entry entry = (Map.Entry) orderMappingsEntriesIter.next();
        AbstractMemberMetaData fmd = (AbstractMemberMetaData) entry.getKey();
        JavaTypeMapping mapping = (JavaTypeMapping) entry.getValue();
        OrderMetaData omd = fmd.getOrderMetaData();
        if (omd != null && omd.getIndexMetaData() != null) {
            Index index = getIndexForIndexMetaDataAndMapping(omd.getIndexMetaData(), mapping);
            if (index != null) {
                indices.add(index);
            }
        }
    }
    // Add on any user-required indices for the class(es) as a whole (subelement of <class>)
    Iterator<AbstractClassMetaData> cmdIter = managedClassMetaData.iterator();
    while (cmdIter.hasNext()) {
        AbstractClassMetaData thisCmd = cmdIter.next();
        List<IndexMetaData> classIndices = thisCmd.getIndexMetaData();
        if (classIndices != null) {
            for (IndexMetaData idxmd : classIndices) {
                Index index = getIndexForIndexMetaData(idxmd);
                if (index != null) {
                    indices.add(index);
                }
            }
        }
    }
    if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        // Make sure there is no reuse of PK fields that cause a duplicate index for the PK. Remove it if required
        PrimaryKey pk = getPrimaryKey();
        Iterator<Index> indicesIter = indices.iterator();
        while (indicesIter.hasNext()) {
            Index idx = indicesIter.next();
            if (idx.getColumnList().equals(pk.getColumnList())) {
                NucleusLogger.DATASTORE_SCHEMA.debug("Index " + idx + " is for the same columns as the PrimaryKey so being removed from expected set of indices. PK is always indexed");
                indicesIter.remove();
            }
        }
    }
    return indices;
}
Also used : SoftDeleteMetaData(org.datanucleus.metadata.SoftDeleteMetaData) Set(java.util.Set) HashSet(java.util.HashSet) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) PrimaryKey(org.datanucleus.store.rdbms.key.PrimaryKey) Index(org.datanucleus.store.rdbms.key.Index) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) OrderMetaData(org.datanucleus.metadata.OrderMetaData) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) RelationType(org.datanucleus.metadata.RelationType) Iterator(java.util.Iterator) MultitenancyMetaData(org.datanucleus.metadata.MultitenancyMetaData) HashSet(java.util.HashSet) EmbeddedPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedPCMapping) IndexMetaData(org.datanucleus.metadata.IndexMetaData) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) SerialisedMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedMapping) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)38 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)23 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)16 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)14 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)13 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)13 ExecutionContext (org.datanucleus.ExecutionContext)12 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)12 SQLException (java.sql.SQLException)11 PersistentClassROF (org.datanucleus.store.rdbms.query.PersistentClassROF)11 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)11 PreparedStatement (java.sql.PreparedStatement)10 ResultSet (java.sql.ResultSet)10 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)10 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)10 SQLController (org.datanucleus.store.rdbms.SQLController)10 ResultObjectFactory (org.datanucleus.store.rdbms.query.ResultObjectFactory)10 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)10 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)8 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)7