Search in sources :

Example 1 with ForeignKey

use of org.datanucleus.store.rdbms.key.ForeignKey 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.getNumberOfColumns() > 0) {
            boolean includePk = true;
            if (supportsOption(IDENTITY_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)

Example 2 with ForeignKey

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

the class SQLAnywhereAdapter 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.getNumberOfColumns() > 0) {
            boolean includePk = true;
            if (supportsOption(IDENTITY_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) {
                // TODO Ensure that the other table exists, for now assume it does
                createStmt.append(",").append(getContinuationString());
                if (fk.getName() != null) {
                    String identifier = factory.getIdentifierInAdapterCase(fk.getName());
                    createStmt.append(indent).append("CONSTRAINT ").append(identifier).append(" ").append(fk.toString());
                } else {
                    createStmt.append(indent).append(fk.toString());
                }
            }
        }
        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)

Example 3 with ForeignKey

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

the class TableUtils method getForeignKeysForReferenceField.

/**
 * Convenience method to add foreign-keys for the specified reference field.
 * Adds FKs from the column(s) in this table to the ID column(s) of the PC table of the implementation type.
 * @param fieldMapping The field mapping (in this table)
 * @param mmd MetaData for this field
 * @param autoMode Whether we are in auto-create mode
 * @param storeMgr Store Manager
 * @param clr ClassLoader resolver
 * @return The foreign key(s) created
 */
public static Collection getForeignKeysForReferenceField(JavaTypeMapping fieldMapping, AbstractMemberMetaData mmd, boolean autoMode, RDBMSStoreManager storeMgr, ClassLoaderResolver clr) {
    final ReferenceMapping refMapping = (ReferenceMapping) fieldMapping;
    JavaTypeMapping[] refJavaTypeMappings = refMapping.getJavaTypeMapping();
    List fks = new ArrayList();
    for (int i = 0; i < refJavaTypeMappings.length; i++) {
        // If the implementation is of a PC class, look to add a FK to the PC class table
        final JavaTypeMapping implMapping = refJavaTypeMappings[i];
        if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(implMapping.getType(), clr) != null && implMapping.getNumberOfColumnMappings() > 0) {
            DatastoreClass referencedTable = storeMgr.getDatastoreClass(implMapping.getType(), clr);
            if (referencedTable != null) {
                ForeignKeyMetaData fkmd = mmd.getForeignKeyMetaData();
                if ((fkmd != null && fkmd.getDeleteAction() != ForeignKeyAction.NONE) || autoMode) {
                    // Either has been specified by user, or using autoMode, so add FK
                    ForeignKey fk = new ForeignKey(implMapping, storeMgr.getDatastoreAdapter(), referencedTable, true);
                    // Does nothing when no FK MetaData
                    fk.setForMetaData(fkmd);
                    fks.add(fk);
                }
            }
        }
    }
    return fks;
}
Also used : ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) ForeignKey(org.datanucleus.store.rdbms.key.ForeignKey)

Example 4 with ForeignKey

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

the class ElementContainerTable method getForeignKeyToOwner.

/**
 * Convenience method to generate a ForeignKey from this join table to an owner table.
 * @param ownerTable The owner table
 * @param autoMode Whether we are in auto mode (where we generate the keys regardless of what the metadata says)
 * @return The ForeignKey
 */
protected ForeignKey getForeignKeyToOwner(DatastoreClass ownerTable, boolean autoMode) {
    ForeignKey fk = null;
    if (ownerTable != null) {
        // Take <foreign-key> from <join>
        ForeignKeyMetaData fkmd = null;
        if (mmd.getJoinMetaData() != null) {
            fkmd = mmd.getJoinMetaData().getForeignKeyMetaData();
        }
        // TODO If in autoMode and there are multiple possible owner tables then don't create a FK
        if (fkmd != null || autoMode) {
            fk = new ForeignKey(ownerMapping, dba, ownerTable, true);
            fk.setForMetaData(fkmd);
        }
    }
    return fk;
}
Also used : ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) ForeignKey(org.datanucleus.store.rdbms.key.ForeignKey)

Example 5 with ForeignKey

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

the class ElementContainerTable method getExpectedForeignKeys.

/**
 * Accessor for the expected foreign keys for this table.
 * @param clr The ClassLoaderResolver
 * @return The expected foreign keys.
 */
@Override
public List<ForeignKey> getExpectedForeignKeys(ClassLoaderResolver clr) {
    assertIsInitialized();
    // Find the mode that we're operating in for FK addition
    boolean autoMode = false;
    if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus")) {
        autoMode = true;
    }
    List<ForeignKey> foreignKeys = new ArrayList();
    try {
        // FK from join table to owner table
        DatastoreClass referencedTable = storeMgr.getDatastoreClass(ownerType, clr);
        if (referencedTable != null) {
            // Single owner table, so add a single FK to the owner as appropriate
            ForeignKey fk = getForeignKeyToOwner(referencedTable, autoMode);
            if (fk != null) {
                foreignKeys.add(fk);
            }
        } else {
        // No single owner so we don't bother with the FK since referential integrity by FK cannot work
        // if we don't have a single owner at the other end of the FK(s).
        }
        // FK from join table to element table(s)
        if (elementMapping instanceof SerialisedPCMapping) {
        // Do nothing since no element table
        } else if (elementMapping instanceof EmbeddedElementPCMapping) {
            // Add any FKs for the fields of the (embedded) element
            EmbeddedElementPCMapping embMapping = (EmbeddedElementPCMapping) elementMapping;
            for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
                JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
                AbstractMemberMetaData embFmd = embFieldMapping.getMemberMetaData();
                if (ClassUtils.isReferenceType(embFmd.getType()) && embFieldMapping instanceof ReferenceMapping) {
                    // Field is a reference type, so add a FK to the table of the PC for each PC implementation
                    Collection fks = TableUtils.getForeignKeysForReferenceField(embFieldMapping, embFmd, autoMode, storeMgr, clr);
                    foreignKeys.addAll(fks);
                } else if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(embFmd.getType(), clr) != null && embFieldMapping.getNumberOfColumnMappings() > 0 && embFieldMapping instanceof PersistableMapping) {
                    // Field is for a PC class with the FK at this side, so add a FK to the table of this PC
                    ForeignKey fk = TableUtils.getForeignKeyForPCField(embFieldMapping, embFmd, autoMode, storeMgr, clr);
                    if (fk != null) {
                        foreignKeys.add(fk);
                    }
                }
            }
        } else if (elementMapping instanceof ReferenceMapping) {
            JavaTypeMapping[] implJavaTypeMappings = ((ReferenceMapping) elementMapping).getJavaTypeMapping();
            for (int i = 0; i < implJavaTypeMappings.length; i++) {
                JavaTypeMapping implMapping = implJavaTypeMappings[i];
                if (storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(implMapping.getType(), clr) != null && implMapping.getNumberOfColumnMappings() > 0) {
                    referencedTable = storeMgr.getDatastoreClass(implMapping.getType(), clr);
                    if (referencedTable != null) {
                        ForeignKey fk = getForeignKeyToElement(referencedTable, autoMode, implMapping);
                        if (fk != null) {
                            foreignKeys.add(fk);
                        }
                    }
                }
            }
        } else {
            referencedTable = storeMgr.getDatastoreClass(getElementType(), clr);
            if (referencedTable != null) {
                ForeignKey fk = getForeignKeyToElement(referencedTable, autoMode, elementMapping);
                if (fk != null) {
                    foreignKeys.add(fk);
                }
            } else {
            // Either no element table or multiple (where the user has element with "subclass-table" strategy, or using "complete-table")
            // so do nothing since referential integrity will not allow multiple FKs.
            }
        }
    } catch (NoTableManagedException e) {
    // expected when no table exists
    }
    return foreignKeys;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ArrayList(java.util.ArrayList) ForeignKey(org.datanucleus.store.rdbms.key.ForeignKey) EmbeddedElementPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedElementPCMapping) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) Collection(java.util.Collection) SerialisedPCMapping(org.datanucleus.store.rdbms.mapping.java.SerialisedPCMapping) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException)

Aggregations

ForeignKey (org.datanucleus.store.rdbms.key.ForeignKey)18 ArrayList (java.util.ArrayList)9 ForeignKeyMetaData (org.datanucleus.metadata.ForeignKeyMetaData)9 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)6 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)5 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)5 Collection (java.util.Collection)4 NoTableManagedException (org.datanucleus.store.rdbms.exceptions.NoTableManagedException)4 PrimaryKey (org.datanucleus.store.rdbms.key.PrimaryKey)4 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)4 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 Iterator (java.util.Iterator)3 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)3 DatastoreIdentifier (org.datanucleus.store.rdbms.identifier.DatastoreIdentifier)3 List (java.util.List)2 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)2 IdentifierFactory (org.datanucleus.store.rdbms.identifier.IdentifierFactory)2 EmbeddedPCMapping (org.datanucleus.store.rdbms.mapping.java.EmbeddedPCMapping)2 Column (org.datanucleus.store.rdbms.table.Column)2