Search in sources :

Example 1 with Index

use of org.datanucleus.store.rdbms.key.Index in project datanucleus-rdbms by datanucleus.

the class MapTable 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.
 * @param clr The ClassLoaderResolver
 * @return The indices
 */
protected Set getExpectedIndices(ClassLoaderResolver clr) {
    Set indices = new HashSet();
    // Index for FK back to owner
    if (mmd.getIndexMetaData() != null) {
        Index index = TableUtils.getIndexForField(this, mmd.getIndexMetaData(), ownerMapping);
        if (index != null) {
            indices.add(index);
        }
    } else if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getIndexMetaData() != null) {
        Index index = TableUtils.getIndexForField(this, mmd.getJoinMetaData().getIndexMetaData(), ownerMapping);
        if (index != null) {
            indices.add(index);
        }
    } else {
        // Fallback to an index for the foreign-key to the owner
        Index index = TableUtils.getIndexForField(this, null, ownerMapping);
        if (index != null) {
            indices.add(index);
        }
    }
    // Index for the key FK (if required)
    if (keyMapping instanceof EmbeddedKeyPCMapping) {
        // Add all indices required by fields of the embedded key
        EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
        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 {
        KeyMetaData keymd = mmd.getKeyMetaData();
        if (keymd != null && keymd.getIndexMetaData() != null) {
            IndexMetaData idxmd = mmd.getKeyMetaData().getIndexMetaData();
            Index index = TableUtils.getIndexForField(this, idxmd, keyMapping);
            if (index != null) {
                indices.add(index);
            }
        } else {
            // Fallback to an index for any foreign-key to the key
            if (keyMapping instanceof PersistableMapping) {
                Index index = TableUtils.getIndexForField(this, null, keyMapping);
                if (index != null) {
                    indices.add(index);
                }
            }
        }
    }
    // Index for the value FK (if required)
    if (valueMapping instanceof EmbeddedValuePCMapping) {
        // Add all indices required by fields of the embedded value
        EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
        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 {
        ValueMetaData valmd = mmd.getValueMetaData();
        if (valmd != null && valmd.getIndexMetaData() != null) {
            IndexMetaData idxmd = mmd.getValueMetaData().getIndexMetaData();
            Index index = TableUtils.getIndexForField(this, idxmd, valueMapping);
            if (index != null) {
                indices.add(index);
            }
        } else {
            // Fallback to an index for any foreign-key to the value
            if (valueMapping instanceof PersistableMapping) {
                Index index = TableUtils.getIndexForField(this, null, valueMapping);
                if (index != null) {
                    indices.add(index);
                }
            }
        }
    }
    return indices;
}
Also used : PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) HashSet(java.util.HashSet) Set(java.util.Set) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) KeyMetaData(org.datanucleus.metadata.KeyMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) ValueMetaData(org.datanucleus.metadata.ValueMetaData) Index(org.datanucleus.store.rdbms.key.Index) EmbeddedValuePCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedValuePCMapping) HashSet(java.util.HashSet) EmbeddedKeyPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedKeyPCMapping) IndexMetaData(org.datanucleus.metadata.IndexMetaData)

Example 2 with Index

use of org.datanucleus.store.rdbms.key.Index in project datanucleus-rdbms by datanucleus.

the class TableImpl method getExistingIndices.

/**
 * Accessor for indices on the actual table.
 * @param conn The JDBC Connection
 * @return Map of indices (keyed by the index name)
 * @throws SQLException Thrown when an error occurs in the JDBC call.
 */
private Map<DatastoreIdentifier, Index> getExistingIndices(Connection conn) throws SQLException {
    Map<DatastoreIdentifier, Index> indicesByName = new HashMap<>();
    if (tableExistsInDatastore(conn)) {
        StoreSchemaHandler handler = storeMgr.getSchemaHandler();
        RDBMSTableIndexInfo tableIndexInfo = (RDBMSTableIndexInfo) handler.getSchemaData(conn, "indices", new Object[] { this });
        IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
        Iterator indexIter = tableIndexInfo.getChildren().iterator();
        while (indexIter.hasNext()) {
            IndexInfo indexInfo = (IndexInfo) indexIter.next();
            short idxType = ((Short) indexInfo.getProperty("type")).shortValue();
            if (idxType == DatabaseMetaData.tableIndexStatistic) {
                // Ignore
                continue;
            }
            String indexName = (String) indexInfo.getProperty("index_name");
            DatastoreIdentifier indexIdentifier = idFactory.newIdentifier(IdentifierType.CANDIDATE_KEY, indexName);
            Index idx = indicesByName.get(indexIdentifier);
            if (idx == null) {
                boolean isUnique = !((Boolean) indexInfo.getProperty("non_unique")).booleanValue();
                idx = new Index(this, isUnique, null);
                idx.setName(indexName);
                indicesByName.put(indexIdentifier, idx);
            }
            // Set the column
            int colSeq = ((Short) indexInfo.getProperty("ordinal_position")).shortValue() - 1;
            DatastoreIdentifier colName = idFactory.newIdentifier(IdentifierType.COLUMN, (String) indexInfo.getProperty("column_name"));
            Column col = columnsByIdentifier.get(colName);
            if (col != null) {
                idx.setColumn(colSeq, col);
            }
        }
    }
    return indicesByName;
}
Also used : HashMap(java.util.HashMap) RDBMSTableIndexInfo(org.datanucleus.store.rdbms.schema.RDBMSTableIndexInfo) Index(org.datanucleus.store.rdbms.key.Index) StoreSchemaHandler(org.datanucleus.store.schema.StoreSchemaHandler) RDBMSTableIndexInfo(org.datanucleus.store.rdbms.schema.RDBMSTableIndexInfo) IndexInfo(org.datanucleus.store.rdbms.schema.IndexInfo) IdentifierFactory(org.datanucleus.store.rdbms.identifier.IdentifierFactory) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) Iterator(java.util.Iterator)

Example 3 with Index

use of org.datanucleus.store.rdbms.key.Index in project datanucleus-rdbms by datanucleus.

the class TableUtils method getIndexForField.

/**
 * Convenience method to create an Index for a field.
 * @param table Container for the index
 * @param imd The Index MetaData
 * @param fieldMapping Mapping for the field
 * @return The Index
 */
public static Index getIndexForField(Table table, IndexMetaData imd, JavaTypeMapping fieldMapping) {
    if (fieldMapping.getNumberOfDatastoreMappings() == 0) {
        // No columns in this mapping so we can hardly index it!
        return null;
    }
    if (!table.getStoreManager().getDatastoreAdapter().validToIndexMapping(fieldMapping)) {
        return null;
    }
    // Verify if a unique index is needed
    boolean unique = (imd == null ? false : imd.isUnique());
    Index index = new Index(table, unique, (imd != null ? imd.getExtensions() : null));
    // Set the index name if required
    if (imd != null && imd.getName() != null) {
        IdentifierFactory idFactory = table.getStoreManager().getIdentifierFactory();
        DatastoreIdentifier idxId = idFactory.newIdentifier(IdentifierType.INDEX, imd.getName());
        index.setName(idxId.toString());
    }
    // Field-level index so use all columns for the field
    int countFields = fieldMapping.getNumberOfDatastoreMappings();
    for (int j = 0; j < countFields; j++) {
        index.addColumn(fieldMapping.getDatastoreMapping(j).getColumn());
    }
    return index;
}
Also used : DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) Index(org.datanucleus.store.rdbms.key.Index) IdentifierFactory(org.datanucleus.store.rdbms.identifier.IdentifierFactory)

Example 4 with Index

use of org.datanucleus.store.rdbms.key.Index 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
 */
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].getNumberOfDatastoreMappings();
                                            Index index = new Index(this, false, null);
                                            for (int j = 0; j < numColsInImpl; j++) {
                                                index.setColumn(j, fieldMapping.getDatastoreMapping(colNum++).getColumn());
                                            }
                                            indices.add(index);
                                        }
                                    }
                                }
                            } else {
                                Index index = new Index(this, false, null);
                                for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
                                    index.setColumn(i, fieldMapping.getDatastoreMapping(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.getNumberOfDatastoreMappings(); i++) {
                                index.setColumn(i, fieldMapping.getDatastoreMapping(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.getNumberOfDatastoreMappings() > 0) {
                                    Index index = new Index(this, false, null);
                                    for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
                                        index.setColumn(i, fieldMapping.getDatastoreMapping(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.getNumberOfDatastoreMappings();
            for (int i = 0; i < countVersionFields; i++) {
                index.addColumn(versionMapping.getDatastoreMapping(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 countDiscrimFields = discriminatorMapping.getNumberOfDatastoreMappings();
            for (int i = 0; i < countDiscrimFields; i++) {
                index.addColumn(discriminatorMapping.getDatastoreMapping(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 : 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) 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)

Example 5 with Index

use of org.datanucleus.store.rdbms.key.Index in project datanucleus-rdbms by datanucleus.

the class ClassTable method getIndexForIndexMetaData.

/**
 * Convenience method to convert an IndexMetaData into an Index.
 * @param imd The Index MetaData
 * @return The Index
 */
private Index getIndexForIndexMetaData(IndexMetaData imd) {
    // Verify if a unique index is needed
    boolean unique = imd.isUnique();
    Index index = new Index(this, unique, imd.getExtensions());
    // Set the index name if required
    if (imd.getName() != null) {
        index.setName(imd.getName());
    }
    // Class-level index so use its column definition
    if (imd.getNumberOfColumns() > 0) {
        // a). Columns specified directly
        String[] columnNames = imd.getColumnNames();
        for (String columnName : columnNames) {
            DatastoreIdentifier colName = storeMgr.getIdentifierFactory().newColumnIdentifier(columnName);
            Column col = columnsByIdentifier.get(colName);
            if (col == null) {
                NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058001", toString(), index.getName(), columnName));
                break;
            }
            index.addColumn(col);
        }
        // Apply any user-provided ordering of the columns
        String idxOrdering = imd.getValueForExtension(Index.EXTENSION_INDEX_COLUMN_ORDERING);
        if (!StringUtils.isWhitespace(idxOrdering)) {
            index.setColumnOrdering(idxOrdering);
        }
    } else if (imd.getNumberOfMembers() > 0) {
        // b). Columns specified using members
        String[] memberNames = imd.getMemberNames();
        for (int i = 0; i < memberNames.length; i++) {
            // Find the metadata for the actual field with the same name as this "index" field
            AbstractMemberMetaData realMmd = getMetaDataForMember(memberNames[i]);
            if (realMmd == null) {
                throw new NucleusUserException("Table " + this + " has index specified on member " + memberNames[i] + " but that member does not exist in the class that this table represents");
            }
            JavaTypeMapping fieldMapping = memberMappingsMap.get(realMmd);
            int countFields = fieldMapping.getNumberOfDatastoreMappings();
            for (int j = 0; j < countFields; j++) {
                index.addColumn(fieldMapping.getDatastoreMapping(j).getColumn());
            }
            // Apply any user-provided ordering of the columns
            String idxOrdering = imd.getValueForExtension(Index.EXTENSION_INDEX_COLUMN_ORDERING);
            if (!StringUtils.isWhitespace(idxOrdering)) {
                index.setColumnOrdering(idxOrdering);
            }
        }
    } else {
        // We can't have an index of no columns
        NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058002", toString(), index.getName()));
        return null;
    }
    return index;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) Index(org.datanucleus.store.rdbms.key.Index) MacroString(org.datanucleus.util.MacroString) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

Index (org.datanucleus.store.rdbms.key.Index)13 HashMap (java.util.HashMap)4 HashSet (java.util.HashSet)4 DatastoreIdentifier (org.datanucleus.store.rdbms.identifier.DatastoreIdentifier)4 IdentifierFactory (org.datanucleus.store.rdbms.identifier.IdentifierFactory)4 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)4 Iterator (java.util.Iterator)3 IndexMetaData (org.datanucleus.metadata.IndexMetaData)3 Map (java.util.Map)2 Set (java.util.Set)2 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)2 PrimaryKey (org.datanucleus.store.rdbms.key.PrimaryKey)2 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)2 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)1 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)1 DiscriminatorMetaData (org.datanucleus.metadata.DiscriminatorMetaData)1 ElementMetaData (org.datanucleus.metadata.ElementMetaData)1 ForeignKeyMetaData (org.datanucleus.metadata.ForeignKeyMetaData)1 KeyMetaData (org.datanucleus.metadata.KeyMetaData)1 OrderMetaData (org.datanucleus.metadata.OrderMetaData)1