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();
}
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();
}
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;
}
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;
}
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;
}
Aggregations