use of org.datanucleus.store.rdbms.identifier.DatastoreIdentifier in project datanucleus-rdbms by datanucleus.
the class TableImpl method getSQLAddFKStatements.
/**
* Get SQL statements to add expected Foreign Keys that are not yet at the table.
* If the returned Map is empty, the current FK setup is correct.
* @param actualForeignKeysByName Actual Map of foreign keys
* @param clr The ClassLoaderResolver
* @return a Map with the SQL statements
*/
protected Map<String, String> getSQLAddFKStatements(Map actualForeignKeysByName, ClassLoaderResolver clr) {
assertIsInitialized();
Map<String, String> stmtsByFKName = new HashMap<>();
List<ForeignKey> expectedForeignKeys = getExpectedForeignKeys(clr);
Iterator<ForeignKey> i = expectedForeignKeys.iterator();
int n = 1;
IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
while (i.hasNext()) {
ForeignKey fk = i.next();
if (!actualForeignKeysByName.containsValue(fk)) {
// If no name assigned, make one up
if (fk.getName() == null) {
// Use the ForeignKeyIdentifier to generate the name
DatastoreIdentifier fkName;
do {
fkName = idFactory.newForeignKeyIdentifier(this, n++);
} while (actualForeignKeysByName.containsKey(fkName));
fk.setName(fkName.getName());
}
String stmtText = dba.getAddForeignKeyStatement(fk, idFactory);
if (stmtText != null) {
stmtsByFKName.put(fk.getName(), stmtText);
}
}
}
return stmtsByFKName;
}
use of org.datanucleus.store.rdbms.identifier.DatastoreIdentifier in project datanucleus-rdbms by datanucleus.
the class TableImpl method getSQLCreateIndexStatements.
/**
* Accessor for the CREATE INDEX statements for this table.
* @param actualIndicesByName Map of actual indexes
* @param clr The ClassLoaderResolver
* @return Map of statements
*/
protected Map<String, String> getSQLCreateIndexStatements(Map actualIndicesByName, ClassLoaderResolver clr) {
assertIsInitialized();
Map<String, String> stmtsByIdxName = new HashMap<>();
Set<Index> expectedIndices = getExpectedIndices(clr);
int n = 1;
Iterator<Index> indexIter = expectedIndices.iterator();
IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
while (indexIter.hasNext()) {
Index idx = indexIter.next();
if (isIndexReallyNeeded(idx, actualIndicesByName.values())) {
// If no name assigned, make one up
if (idx.getName() == null) {
// Use IndexIdentifier to generate the name.
DatastoreIdentifier idxName;
do {
idxName = idFactory.newIndexIdentifier(this, idx.getUnique(), n++);
idx.setName(idxName.getName());
} while (actualIndicesByName.containsKey(idxName));
}
String stmtText = dba.getCreateIndexStatement(idx, idFactory);
stmtsByIdxName.put(idx.getName(), stmtText);
}
}
return stmtsByIdxName;
}
use of org.datanucleus.store.rdbms.identifier.DatastoreIdentifier in project datanucleus-rdbms by datanucleus.
the class TableImpl method getExistingForeignKeys.
/**
* Accessor for the foreign keys for this table.
* @param conn The JDBC Connection
* @return Map of foreign keys
* @throws SQLException Thrown when an error occurs in the JDBC call.
*/
private Map<DatastoreIdentifier, ForeignKey> getExistingForeignKeys(Connection conn) throws SQLException {
Map<DatastoreIdentifier, ForeignKey> foreignKeysByName = new HashMap<>();
if (tableExistsInDatastore(conn)) {
StoreSchemaHandler handler = storeMgr.getSchemaHandler();
IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
RDBMSTableFKInfo tableFkInfo = (RDBMSTableFKInfo) handler.getSchemaData(conn, RDBMSSchemaHandler.TYPE_FKS, new Object[] { this });
Iterator fksIter = tableFkInfo.getChildren().iterator();
while (fksIter.hasNext()) {
ForeignKeyInfo fkInfo = (ForeignKeyInfo) fksIter.next();
DatastoreIdentifier fkIdentifier;
String fkName = (String) fkInfo.getProperty("fk_name");
if (fkName == null) {
fkIdentifier = idFactory.newForeignKeyIdentifier(this, foreignKeysByName.size());
} else {
fkIdentifier = idFactory.newIdentifier(IdentifierType.FOREIGN_KEY, fkName);
}
short deferrability = ((Short) fkInfo.getProperty("deferrability")).shortValue();
boolean initiallyDeferred = deferrability == DatabaseMetaData.importedKeyInitiallyDeferred;
ForeignKey fk = foreignKeysByName.get(fkIdentifier);
if (fk == null) {
fk = new ForeignKey(dba, initiallyDeferred);
fk.setName(fkIdentifier.getName());
foreignKeysByName.put(fkIdentifier, fk);
}
// Find the referenced table from the provided name
String pkTableName = (String) fkInfo.getProperty("pk_table_name");
DatastoreIdentifier refTableId = idFactory.newTableIdentifier(pkTableName);
DatastoreClass refTable = storeMgr.getDatastoreClass(refTableId);
if (refTable == null) {
// Try with same catalog/schema as this table since some JDBC don't provide this info
if (getSchemaName() != null) {
refTableId.setSchemaName(getSchemaName());
}
if (getCatalogName() != null) {
refTableId.setCatalogName(getCatalogName());
}
refTable = storeMgr.getDatastoreClass(refTableId);
}
if (refTable != null) {
String fkColumnName = (String) fkInfo.getProperty("fk_column_name");
String pkColumnName = (String) fkInfo.getProperty("pk_column_name");
DatastoreIdentifier colName = idFactory.newIdentifier(IdentifierType.COLUMN, fkColumnName);
DatastoreIdentifier refColName = idFactory.newIdentifier(IdentifierType.COLUMN, pkColumnName);
Column col = columnsByIdentifier.get(colName);
Column refCol = refTable.getColumn(refColName);
if (col != null && refCol != null) {
fk.addColumn(col, refCol);
} else {
// TODO throw exception?
}
} else {
NucleusLogger.DATASTORE_SCHEMA.warn("Retrieved ForeignKey from datastore for table=" + toString() + " referencing table " + pkTableName + " but not found internally. Is there some catalog/schema or quoting causing problems?");
}
}
}
return foreignKeysByName;
}
use of org.datanucleus.store.rdbms.identifier.DatastoreIdentifier in project datanucleus-rdbms by datanucleus.
the class ViewImpl method validate.
/**
* Method to validate the view in the datastore. Validates the existence of the table, and then the specifications of the Columns.
* @param conn The JDBC Connection
* @param validateColumnStructure Whether to validate down to column structure, or just their existence
* @param autoCreate Whether to update the view to fix errors (not used).
* @param autoCreateErrors Errors found during the auto-create process
* @return Whether the database was modified
* @throws SQLException Thrown when an error occurs in the JDBC calls
*/
public boolean validate(Connection conn, boolean validateColumnStructure, boolean autoCreate, Collection<Throwable> autoCreateErrors) throws SQLException {
assertIsInitialized();
long startTime = System.currentTimeMillis();
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
NucleusLogger.DATASTORE.debug(Localiser.msg("031004", this));
}
// Check existence and validity
RDBMSSchemaHandler handler = (RDBMSSchemaHandler) storeMgr.getSchemaHandler();
String tableType = handler.getTableType(conn, this);
if (tableType == null) {
throw new MissingTableException(getCatalogName(), getSchemaName(), this.toString());
} else if (// TODO Allow "MATERIALIZED VIEW" that some RDBMS support (e.g PostgreSQL)
!tableType.equals("VIEW")) {
throw new NotAViewException(this.toString(), tableType);
}
// Validate the column(s)
Map<DatastoreIdentifier, Column> unvalidated = new HashMap(columnsByIdentifier);
Iterator i = storeMgr.getColumnInfoForTable(this, conn).iterator();
while (i.hasNext()) {
RDBMSColumnInfo ci = (RDBMSColumnInfo) i.next();
DatastoreIdentifier colIdentifier = storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, ci.getColumnName());
Column col = unvalidated.get(colIdentifier);
if (col == null) {
if (!hasColumnName(colIdentifier)) {
throw new UnexpectedColumnException(this.toString(), ci.getColumnName(), this.getSchemaName(), this.getCatalogName());
}
// Otherwise it's a duplicate column name in the metadata and we ignore it. Cloudscape is known to do this, although I think that's probably a bug.
} else {
if (validateColumnStructure) {
col.validate(ci);
unvalidated.remove(colIdentifier);
} else {
unvalidated.remove(colIdentifier);
}
}
}
if (unvalidated.size() > 0) {
throw new MissingColumnException(this, unvalidated.values());
}
state = TABLE_STATE_VALIDATED;
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
NucleusLogger.DATASTORE.debug(Localiser.msg("045000", (System.currentTimeMillis() - startTime)));
}
return false;
}
use of org.datanucleus.store.rdbms.identifier.DatastoreIdentifier in project datanucleus-rdbms by datanucleus.
the class TableGenerator method initialiseSequenceTable.
/**
* Method to initialise the sequence table used for storing the sequence values.
*/
protected synchronized void initialiseSequenceTable() {
// Set catalog/schema name (using properties, and if not specified using the values for the table)
String catalogName = properties.getProperty(ValueGenerator.PROPERTY_SEQUENCETABLE_CATALOG);
if (catalogName == null) {
catalogName = properties.getProperty(ValueGenerator.PROPERTY_CATALOG_NAME);
}
String schemaName = properties.getProperty(ValueGenerator.PROPERTY_SEQUENCETABLE_SCHEMA);
if (schemaName == null) {
schemaName = properties.getProperty(ValueGenerator.PROPERTY_SCHEMA_NAME);
}
String tableName = (properties.getProperty(ValueGenerator.PROPERTY_SEQUENCETABLE_TABLE) == null ? DEFAULT_TABLE_NAME : properties.getProperty(ValueGenerator.PROPERTY_SEQUENCETABLE_TABLE));
RDBMSStoreManager storeMgr = (RDBMSStoreManager) this.storeMgr;
DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
DatastoreIdentifier identifier = storeMgr.getIdentifierFactory().newTableIdentifier(tableName);
if (dba.supportsOption(DatastoreAdapter.CATALOGS_IN_TABLE_DEFINITIONS) && catalogName != null) {
identifier.setCatalogName(catalogName);
}
if (dba.supportsOption(DatastoreAdapter.SCHEMAS_IN_TABLE_DEFINITIONS) && schemaName != null) {
identifier.setSchemaName(schemaName);
}
DatastoreClass table = storeMgr.getDatastoreClass(identifier);
if (table != null) {
sequenceTable = (SequenceTable) table;
} else {
String sequenceNameColumnName = DEFAULT_SEQUENCE_COLUMN_NAME;
if (properties.containsKey(ValueGenerator.PROPERTY_SEQUENCETABLE_NAME_COLUMN)) {
sequenceNameColumnName = properties.getProperty(ValueGenerator.PROPERTY_SEQUENCETABLE_NAME_COLUMN);
}
String nextValColumnName = DEFAULT_NEXTVALUE_COLUMN_NAME;
if (properties.containsKey(ValueGenerator.PROPERTY_SEQUENCETABLE_NEXTVAL_COLUMN)) {
nextValColumnName = properties.getProperty(ValueGenerator.PROPERTY_SEQUENCETABLE_NEXTVAL_COLUMN);
}
sequenceTable = new SequenceTable(identifier, storeMgr, sequenceNameColumnName, nextValColumnName);
sequenceTable.initialize(storeMgr.getNucleusContext().getClassLoaderResolver(null));
}
}
Aggregations