Search in sources :

Example 1 with PrimaryKey

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

the class ClassTable method getExpectedCandidateKeys.

/**
 * Accessor for the expected candidate keys for this table.
 * @return The expected candidate keys.
 */
protected List<CandidateKey> getExpectedCandidateKeys() {
    assertIsInitialized();
    // The candidate keys required by the basic table
    List<CandidateKey> candidateKeys = super.getExpectedCandidateKeys();
    // Add any constraints required for a FK map
    Iterator<CandidateKey> cks = candidateKeysByMapField.values().iterator();
    while (cks.hasNext()) {
        CandidateKey ck = cks.next();
        candidateKeys.add(ck);
    }
    // Add on any user-required candidate keys for the fields
    Set fieldNumbersSet = memberMappingsMap.keySet();
    Iterator iter = fieldNumbersSet.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);
                UniqueMetaData umd = embFieldMapping.getMemberMetaData().getUniqueMetaData();
                if (umd != null) {
                    CandidateKey ck = TableUtils.getCandidateKeyForField(this, umd, embFieldMapping);
                    if (ck != null) {
                        candidateKeys.add(ck);
                    }
                }
            }
        } else {
            // Add any required candidate key for this field
            UniqueMetaData umd = fmd.getUniqueMetaData();
            if (umd != null) {
                CandidateKey ck = TableUtils.getCandidateKeyForField(this, umd, fieldMapping);
                if (ck != null) {
                    candidateKeys.add(ck);
                }
            }
        }
    }
    // Add on any user-required candidate keys for the class(es) as a whole (composite keys)
    Iterator<AbstractClassMetaData> cmdIter = managedClassMetaData.iterator();
    while (cmdIter.hasNext()) {
        AbstractClassMetaData thisCmd = cmdIter.next();
        List<UniqueMetaData> classCKs = thisCmd.getUniqueMetaData();
        if (classCKs != null) {
            for (UniqueMetaData unimd : classCKs) {
                CandidateKey ck = getCandidateKeyForUniqueMetaData(unimd);
                if (ck != null) {
                    candidateKeys.add(ck);
                }
            }
        }
    }
    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<CandidateKey> candidatesIter = candidateKeys.iterator();
        while (candidatesIter.hasNext()) {
            CandidateKey key = candidatesIter.next();
            if (key.getColumnList().equals(pk.getColumnList())) {
                NucleusLogger.DATASTORE_SCHEMA.debug("Candidate key " + key + " is for the same columns as the PrimaryKey so being removed from expected set of candidates. PK is always unique");
                candidatesIter.remove();
            }
        }
    }
    return candidateKeys;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) EmbeddedPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedPCMapping) PrimaryKey(org.datanucleus.store.rdbms.key.PrimaryKey) UniqueMetaData(org.datanucleus.metadata.UniqueMetaData) CandidateKey(org.datanucleus.store.rdbms.key.CandidateKey) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) Iterator(java.util.Iterator) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 2 with PrimaryKey

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

the class SecondaryTable method getPrimaryKey.

/**
 * Accessor for the primary key for this table. Overrides the method in TableImpl
 * to add on any specification of PK name in the metadata.
 * @return The primary key.
 */
public PrimaryKey getPrimaryKey() {
    PrimaryKey pk = super.getPrimaryKey();
    if (joinMetaData == null) {
        // TODO Localise this message
        throw new NucleusUserException("A relationship to a secondary table requires a <join> specification. " + "The secondary table is " + this.getDatastoreIdentifierFullyQualified() + " and the primary table is " + this.getPrimaryTable() + ". The fields mapped to this secondary table are: " + memberMappingsMap.keySet().toString());
    }
    PrimaryKeyMetaData pkmd = joinMetaData.getPrimaryKeyMetaData();
    if (pkmd != null && pkmd.getName() != null) {
        pk.setName(pkmd.getName());
    }
    return pk;
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) PrimaryKey(org.datanucleus.store.rdbms.key.PrimaryKey) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData)

Example 3 with PrimaryKey

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

the class TableImpl method getPrimaryKey.

/**
 * Accessor for the primary key for this table.
 * Will always return a PrimaryKey but if we have defined no columns,
 * the pk.size() will be 0.
 * @return The primary key.
 */
public PrimaryKey getPrimaryKey() {
    PrimaryKey pk = new PrimaryKey(this);
    Iterator i = columns.iterator();
    while (i.hasNext()) {
        Column col = (Column) i.next();
        if (col.isPrimaryKey()) {
            pk.addColumn(col);
        }
    }
    return pk;
}
Also used : Iterator(java.util.Iterator) PrimaryKey(org.datanucleus.store.rdbms.key.PrimaryKey)

Example 4 with PrimaryKey

use of org.datanucleus.store.rdbms.key.PrimaryKey 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 PrimaryKey

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

the class BaseDatastoreAdapter method getCreateTableStatement.

/**
 * Returns the appropriate SQL to create the given table having the given
 * columns. No column constraints or key definitions should be included.
 * It should return something like:
 * <pre>
 * CREATE TABLE FOO ( BAR VARCHAR(30), BAZ INTEGER )
 * </pre>
 *
 * @param table The table to create.
 * @param columns The columns of the table.
 * @param props Properties for controlling the table creation
 * @param factory Factory for identifiers
 * @return The text of the SQL statement.
 */
public String getCreateTableStatement(TableImpl table, Column[] columns, Properties props, IdentifierFactory factory) {
    StringBuilder createStmt = new StringBuilder();
    String indent = "    ";
    if (getContinuationString().length() == 0) {
        indent = "";
    }
    // CREATE TABLE with column specifiers
    createStmt.append("CREATE TABLE ").append(table.toString()).append(getContinuationString()).append("(").append(getContinuationString());
    for (int i = 0; i < columns.length; ++i) {
        if (i > 0) {
            createStmt.append(",").append(getContinuationString());
        }
        createStmt.append(indent).append(columns[i].getSQLDefinition());
    }
    // PRIMARY KEY(col[,col])
    if (supportsOption(PRIMARYKEY_IN_CREATE_STATEMENTS)) {
        PrimaryKey pk = table.getPrimaryKey();
        if (pk != null && pk.size() > 0) {
            boolean includePk = true;
            if (supportsOption(AUTO_INCREMENT_PK_IN_CREATE_TABLE_COLUMN_DEF)) {
                for (Column pkCol : pk.getColumns()) {
                    if (pkCol.isIdentity()) {
                        // This column is auto-increment and is specified in the column def so ignore here
                        includePk = false;
                        break;
                    }
                }
            }
            if (includePk) {
                createStmt.append(",").append(getContinuationString());
                if (pk.getName() != null) {
                    String identifier = factory.getIdentifierInAdapterCase(pk.getName());
                    createStmt.append(indent).append("CONSTRAINT ").append(identifier).append(" ").append(pk.toString());
                } else {
                    createStmt.append(indent).append(pk.toString());
                }
            }
        }
    }
    // UNIQUE( col [,col] )
    if (supportsOption(UNIQUE_IN_END_CREATE_STATEMENTS)) {
        StringBuilder uniqueConstraintStmt = new StringBuilder();
        for (int i = 0; i < columns.length; ++i) {
            if (columns[i].isUnique()) {
                if (uniqueConstraintStmt.length() < 1) {
                    uniqueConstraintStmt.append(",").append(getContinuationString());
                    uniqueConstraintStmt.append(indent).append(" UNIQUE (");
                } else {
                    uniqueConstraintStmt.append(",");
                }
                uniqueConstraintStmt.append(columns[i].getIdentifier().toString());
            }
        }
        if (uniqueConstraintStmt.length() > 1) {
            uniqueConstraintStmt.append(")");
            createStmt.append(uniqueConstraintStmt.toString());
        }
    }
    // FOREIGN KEY(col [,col] ) REFERENCES {TBL} (col [,col])
    if (supportsOption(FK_IN_END_CREATE_STATEMENTS)) {
        StringBuilder fkConstraintStmt = new StringBuilder();
        ClassLoaderResolver clr = table.getStoreManager().getNucleusContext().getClassLoaderResolver(null);
        List<ForeignKey> fks = table.getExpectedForeignKeys(clr);
        if (fks != null && !fks.isEmpty()) {
            for (ForeignKey fk : fks) {
                NucleusLogger.GENERAL.debug(">> TODO Add FK in CREATE TABLE as " + fk);
            // TODO Add the FK. Make sure that the other table exists
            }
        }
        if (fkConstraintStmt.length() > 1) {
            createStmt.append(fkConstraintStmt.toString());
        }
    }
    // CHECK (column_identifier IN (literal[,literal]))
    if (supportsOption(CHECK_IN_END_CREATE_STATEMENTS)) {
        StringBuilder checkConstraintStmt = new StringBuilder();
        for (int i = 0; i < columns.length; ++i) {
            if (columns[i].getCheckConstraints() != null) {
                checkConstraintStmt.append(",").append(getContinuationString());
                checkConstraintStmt.append(indent).append(columns[i].getCheckConstraints());
            }
        }
        if (checkConstraintStmt.length() > 1) {
            createStmt.append(checkConstraintStmt.toString());
        }
    }
    createStmt.append(getContinuationString()).append(")");
    return createStmt.toString();
}
Also used : Column(org.datanucleus.store.rdbms.table.Column) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) PrimaryKey(org.datanucleus.store.rdbms.key.PrimaryKey) ForeignKey(org.datanucleus.store.rdbms.key.ForeignKey)

Aggregations

PrimaryKey (org.datanucleus.store.rdbms.key.PrimaryKey)12 Iterator (java.util.Iterator)4 ForeignKey (org.datanucleus.store.rdbms.key.ForeignKey)4 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)3 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)3 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)3 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)3 ArrayList (java.util.ArrayList)2 Map (java.util.Map)2 Set (java.util.Set)2 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)2 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)2 PrimaryKeyMetaData (org.datanucleus.metadata.PrimaryKeyMetaData)2 DatastoreIdentifier (org.datanucleus.store.rdbms.identifier.DatastoreIdentifier)2 Index (org.datanucleus.store.rdbms.key.Index)2 EmbeddedPCMapping (org.datanucleus.store.rdbms.mapping.java.EmbeddedPCMapping)2 Column (org.datanucleus.store.rdbms.table.Column)2 List (java.util.List)1