use of org.datanucleus.store.rdbms.key.PrimaryKey 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.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) {
// 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.PrimaryKey in project datanucleus-rdbms by datanucleus.
the class ClassTable 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();
PrimaryKeyMetaData pkmd = cmd.getPrimaryKeyMetaData();
if (pkmd != null && pkmd.getName() != null) {
pk.setName(pkmd.getName());
}
return pk;
}
use of org.datanucleus.store.rdbms.key.PrimaryKey in project datanucleus-rdbms by datanucleus.
the class ClassTable method getForeignKeyForForeignKeyMetaData.
/**
* Convenience method to create a FK for the specified ForeignKeyMetaData.
* Used for foreign-keys specified at <class> level.
* @param fkmd ForeignKey MetaData
* @return The ForeignKey
*/
private ForeignKey getForeignKeyForForeignKeyMetaData(ForeignKeyMetaData fkmd) {
if (fkmd == null) {
return null;
}
// Create the ForeignKey base details
ForeignKey fk = new ForeignKey(dba, fkmd.isDeferred());
fk.setForMetaData(fkmd);
if (fkmd.getFkDefinitionApplies()) {
// User-defined FK definition should be used
return fk;
}
// Find the target of the foreign-key
AbstractClassMetaData acmd = cmd;
if (fkmd.getTable() == null) {
// Can't create a FK if we don't know where it goes to
NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058105", acmd.getFullClassName()));
return null;
}
DatastoreIdentifier tableId = storeMgr.getIdentifierFactory().newTableIdentifier(fkmd.getTable());
ClassTable refTable = (ClassTable) storeMgr.getDatastoreClass(tableId);
if (refTable == null) {
// TODO Go to the datastore and query for this table to get the columns of the PK
NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058106", acmd.getFullClassName(), fkmd.getTable()));
return null;
}
PrimaryKey pk = refTable.getPrimaryKey();
List targetCols = pk.getColumns();
// Generate the columns for the source of the foreign-key
List<Column> sourceCols = new ArrayList<>();
ColumnMetaData[] colmds = fkmd.getColumnMetaData();
String[] memberNames = fkmd.getMemberNames();
if (colmds != null && colmds.length > 0) {
// FK specified via <column>
for (int i = 0; i < colmds.length; i++) {
// Find the column and add to the source columns for the FK
DatastoreIdentifier colId = storeMgr.getIdentifierFactory().newColumnIdentifier(colmds[i].getName());
Column sourceCol = columnsByIdentifier.get(colId);
if (sourceCol == null) {
NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058107", acmd.getFullClassName(), fkmd.getTable(), colmds[i].getName(), toString()));
return null;
}
sourceCols.add(sourceCol);
}
} else if (memberNames != null && memberNames.length > 0) {
// FK specified via <field>
for (int i = 0; i < memberNames.length; i++) {
// Find the metadata for the actual field with the same name as this "foreign-key" field
// and add all columns to the source columns for the FK
AbstractMemberMetaData realMmd = getMetaDataForMember(memberNames[i]);
if (realMmd == null) {
throw new NucleusUserException("Table " + this + " has foreign-key specified on member " + memberNames[i] + " but that member does not exist in the class that this table represents");
}
JavaTypeMapping fieldMapping = memberMappingsMap.get(realMmd);
int countCols = fieldMapping.getNumberOfDatastoreMappings();
for (int j = 0; j < countCols; j++) {
// Add each column of this field to the FK definition
sourceCols.add(fieldMapping.getDatastoreMapping(j).getColumn());
}
}
}
if (sourceCols.size() != targetCols.size()) {
// Different number of cols in this table and target table
NucleusLogger.DATASTORE_SCHEMA.warn(Localiser.msg("058108", acmd.getFullClassName(), fkmd.getTable(), "" + sourceCols.size(), "" + targetCols.size()));
}
// Add all column mappings to the ForeignKey
if (sourceCols.size() > 0) {
for (int i = 0; i < sourceCols.size(); i++) {
Column source = sourceCols.get(i);
String targetColName = (colmds != null && colmds[i] != null) ? colmds[i].getTarget() : null;
// Default to matching via the natural order
Column target = (Column) targetCols.get(i);
if (targetColName != null) {
// User has specified the target column for this col so try it in our target list
for (int j = 0; j < targetCols.size(); j++) {
Column targetCol = (Column) targetCols.get(j);
if (targetCol.getIdentifier().getName().equalsIgnoreCase(targetColName)) {
// Found the required column
target = targetCol;
break;
}
}
}
fk.addColumn(source, target);
}
}
return fk;
}
use of org.datanucleus.store.rdbms.key.PrimaryKey in project datanucleus-rdbms by datanucleus.
the class TableImpl method validatePrimaryKey.
/**
* Utility method to validate the primary key of the table.
* Will throw a WrongPrimaryKeyException if the PK is incorrect.
* TODO Add an auto_create parameter on this
* @param conn Connection to use
* @return Whether it validates
* @throws SQLException When an error occurs in the valdiation
*/
protected boolean validatePrimaryKey(Connection conn) throws SQLException {
Map actualPKs = getExistingPrimaryKeys(conn);
PrimaryKey expectedPK = getPrimaryKey();
if (expectedPK.size() == 0) {
if (!actualPKs.isEmpty()) {
throw new WrongPrimaryKeyException(this.toString(), expectedPK.toString(), StringUtils.collectionToString(actualPKs.values()));
}
} else {
if (actualPKs.size() != 1 || !actualPKs.values().contains(expectedPK)) {
throw new WrongPrimaryKeyException(this.toString(), expectedPK.toString(), StringUtils.collectionToString(actualPKs.values()));
}
}
return true;
}
use of org.datanucleus.store.rdbms.key.PrimaryKey in project datanucleus-rdbms by datanucleus.
the class TableImpl method getSQLCreateStatements.
/**
* Accessor for the SQL CREATE statements for this table.
* @param props Properties for controlling the table creation
* @return List of statements.
*/
protected List<String> getSQLCreateStatements(Properties props) {
assertIsInitialized();
Column[] cols = null;
// Pass 1 : populate positions defined in metadata as vendor extension "index"
Iterator<org.datanucleus.store.schema.table.Column> iter = columns.iterator();
while (iter.hasNext()) {
Column col = (Column) iter.next();
ColumnMetaData colmd = col.getColumnMetaData();
Integer colPos = (colmd != null ? colmd.getPosition() : null);
if (colPos != null) {
int index = colPos.intValue();
if (index < columns.size() && index >= 0) {
if (cols == null) {
cols = new Column[columns.size()];
}
if (cols[index] != null) {
throw new NucleusUserException("Column index " + index + " has been specified multiple times : " + cols[index] + " and " + col);
}
cols[index] = col;
}
}
}
// Pass 2 : fill in spaces for columns with undefined positions
if (cols != null) {
iter = columns.iterator();
while (iter.hasNext()) {
Column col = (Column) iter.next();
ColumnMetaData colmd = col.getColumnMetaData();
Integer colPos = (colmd != null ? colmd.getPosition() : null);
if (colPos == null) {
// No index set for this column, so assign to next free position
for (int i = 0; i < cols.length; i++) {
if (cols[i] == null) {
cols[i] = col;
}
}
}
}
} else {
cols = columns.toArray(new Column[columns.size()]);
}
List<String> stmts = new ArrayList<>();
stmts.add(dba.getCreateTableStatement(this, cols, props, storeMgr.getIdentifierFactory()));
PrimaryKey pk = getPrimaryKey();
if (pk.size() > 0) {
// Some databases define the primary key on the create table
// statement so we don't have a Statement for the primary key here.
String pkStmt = dba.getAddPrimaryKeyStatement(pk, storeMgr.getIdentifierFactory());
if (pkStmt != null) {
stmts.add(pkStmt);
}
}
return stmts;
}
Aggregations