use of org.datanucleus.store.schema.StoreSchemaData in project datanucleus-rdbms by datanucleus.
the class TableImpl method validateColumns.
/**
* Utility to validate the columns of the table.
* Will throw a MissingColumnException if a column is not found (and is not required to auto create it)
* @param conn Connection to use for validation
* @param validateColumnStructure Whether to validate down to the structure of the columns, or just their existence
* @param autoCreate Whether to auto create any missing columns
* @param autoCreateErrors Exceptions found in the "auto-create" process
* @return Whether it validates
* @throws SQLException Thrown if an error occurs in the validation process
*/
public boolean validateColumns(Connection conn, boolean validateColumnStructure, boolean autoCreate, Collection autoCreateErrors) throws SQLException {
Map<DatastoreIdentifier, Column> unvalidated = new HashMap(columnsByIdentifier);
List<StoreSchemaData> tableColInfo = storeMgr.getColumnInfoForTable(this, conn);
Iterator i = tableColInfo.iterator();
while (i.hasNext()) {
RDBMSColumnInfo ci = (RDBMSColumnInfo) i.next();
// Create an identifier to use for the real column - use "CUSTOM" because we don't want truncation
DatastoreIdentifier colIdentifier = storeMgr.getIdentifierFactory().newColumnIdentifier(ci.getColumnName(), this.storeMgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(String.class), null, true);
Column col = unvalidated.get(colIdentifier);
if (col != null) {
if (validateColumnStructure) {
col.initializeColumnInfoFromDatastore(ci);
col.validate(ci);
unvalidated.remove(colIdentifier);
} else {
unvalidated.remove(colIdentifier);
}
}
}
if (unvalidated.size() > 0) {
if (autoCreate) {
// Add all missing columns
List<String> stmts = new ArrayList<>();
Iterator<Map.Entry<DatastoreIdentifier, Column>> columnsIter = unvalidated.entrySet().iterator();
while (columnsIter.hasNext()) {
Map.Entry<DatastoreIdentifier, Column> entry = columnsIter.next();
Column col = entry.getValue();
String addColStmt = dba.getAddColumnStatement(this, col);
stmts.add(addColStmt);
}
try {
executeDdlStatementList(stmts, conn);
} catch (SQLException sqle) {
if (autoCreateErrors != null) {
autoCreateErrors.add(sqle);
} else {
throw sqle;
}
}
// Invalidate the cached information for this table since it now has a new column
storeMgr.invalidateColumnInfoForTable(this);
} else {
MissingColumnException mce = new MissingColumnException(this, unvalidated.values());
if (autoCreateErrors != null) {
autoCreateErrors.add(mce);
} else {
throw mce;
}
}
}
state = TABLE_STATE_VALIDATED;
return true;
}
use of org.datanucleus.store.schema.StoreSchemaData in project datanucleus-rdbms by datanucleus.
the class RDBMSStoreManager method getColumnInfoForTable.
/**
* Returns the column info for a database table. This should be used instead
* of making direct calls to DatabaseMetaData.getColumns().
* <p>
* Where possible, this method loads and caches column info for more than
* just the table being requested, improving performance by reducing the
* overall number of calls made to DatabaseMetaData.getColumns() (each of
* which usually results in one or more database queries).
* </p>
* @param table The table/view
* @param conn JDBC connection to the database.
* @return A list of ColumnInfo objects describing the columns of the table.
* The list is in the same order as was supplied by getColumns(). If no
* column info is found for the given table, an empty list is returned.
* @throws SQLException Thrown if an error occurs
*/
public List<StoreSchemaData> getColumnInfoForTable(Table table, Connection conn) throws SQLException {
RDBMSTableInfo tableInfo = (RDBMSTableInfo) schemaHandler.getSchemaData(conn, "columns", new Object[] { table });
if (tableInfo == null) {
return Collections.EMPTY_LIST;
}
List<StoreSchemaData> cols = new ArrayList(tableInfo.getNumberOfChildren());
cols.addAll(tableInfo.getChildren());
return cols;
}
use of org.datanucleus.store.schema.StoreSchemaData in project datanucleus-rdbms by datanucleus.
the class DeleteTablesSchemaTransaction method run.
/* (non-Javadoc)
* @see org.datanucleus.store.rdbms.AbstractSchemaTransaction#run(org.datanucleus.ClassLoaderResolver)
*/
protected void run(ClassLoaderResolver clr) throws SQLException {
synchronized (rdbmsMgr) {
boolean success = true;
try {
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("050045", rdbmsMgr.getCatalogName(), rdbmsMgr.getSchemaName()));
// Build up map of tables and views TODO Why use maps?
Map baseTablesByName = new HashMap();
Map viewsByName = new HashMap();
for (Iterator i = storeDataMgr.getManagedStoreData().iterator(); i.hasNext(); ) {
RDBMSStoreData data = (RDBMSStoreData) i.next();
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled()) {
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("050046", data.getName()));
}
// If the class has a table/view to remove, add it to the list
if (data.hasTable()) {
if (data.mapsToView()) {
viewsByName.put(data.getDatastoreIdentifier(), data.getTable());
} else {
baseTablesByName.put(data.getDatastoreIdentifier(), data.getTable());
}
}
}
// Remove views
Iterator viewsIter = viewsByName.values().iterator();
while (viewsIter.hasNext()) {
ViewImpl view = (ViewImpl) viewsIter.next();
if (writer != null) {
try {
if (view instanceof ClassView) {
writer.write("-- ClassView " + view.toString() + " for classes " + StringUtils.objectArrayToString(((ClassView) view).getManagedClasses()) + "\n");
}
} catch (IOException ioe) {
NucleusLogger.DATASTORE_SCHEMA.error("error writing DDL into file", ioe);
}
((ViewImpl) viewsIter.next()).drop(getCurrentConnection());
} else {
// Drop view if exists in the datastore
StoreSchemaData info = rdbmsMgr.getSchemaHandler().getSchemaData(getCurrentConnection(), RDBMSSchemaHandler.TYPE_COLUMNS, new Object[] { view });
if (info != null) {
((ViewImpl) viewsIter.next()).drop(getCurrentConnection());
}
}
}
// Remove table constraints
Map<TableImpl, Boolean> schemaExistsForTableMap = new HashMap();
Iterator tablesIter = baseTablesByName.values().iterator();
while (tablesIter.hasNext()) {
TableImpl tbl = (TableImpl) tablesIter.next();
if (writer != null) {
try {
if (tbl instanceof ClassTable) {
writer.write("-- Constraints for ClassTable " + tbl.toString() + " for classes " + StringUtils.objectArrayToString(((ClassTable) tbl).getManagedClasses()) + "\n");
} else if (tbl instanceof JoinTable) {
writer.write("-- Constraints for JoinTable " + tbl.toString() + " for join relationship\n");
}
} catch (IOException ioe) {
NucleusLogger.DATASTORE_SCHEMA.error("error writing DDL into file", ioe);
}
tbl.dropConstraints(getCurrentConnection());
} else {
// Drop constraints if exists in the datastore
boolean exists = false;
try {
// Check table type as way of detecting existence
String tableType = ((RDBMSSchemaHandler) rdbmsMgr.getSchemaHandler()).getTableType(getCurrentConnection(), tbl);
if (tableType != null) {
exists = true;
}
} catch (Exception e) {
exists = false;
}
schemaExistsForTableMap.put(tbl, exists);
if (exists) {
tbl.dropConstraints(getCurrentConnection());
}
}
}
// Remove tables
tablesIter = baseTablesByName.values().iterator();
while (tablesIter.hasNext()) {
TableImpl tbl = (TableImpl) tablesIter.next();
if (writer != null) {
try {
if (tbl instanceof ClassTable) {
writer.write("-- ClassTable " + tbl.toString() + " for classes " + StringUtils.objectArrayToString(((ClassTable) tbl).getManagedClasses()) + "\n");
} else if (tbl instanceof JoinTable) {
writer.write("-- JoinTable " + tbl.toString() + " for join relationship\n");
}
} catch (IOException ioe) {
NucleusLogger.DATASTORE_SCHEMA.error("error writing DDL into file", ioe);
}
tbl.drop(getCurrentConnection());
} else {
// Drop table if exists in the datastore
Boolean schemaExists = schemaExistsForTableMap.get(tbl);
if (schemaExists != null && schemaExists == Boolean.TRUE) {
tbl.drop(getCurrentConnection());
}
}
}
} catch (Exception e) {
success = false;
String errorMsg = Localiser.msg("050047", e);
NucleusLogger.DATASTORE_SCHEMA.error(errorMsg);
throw new NucleusUserException(errorMsg, e);
}
if (!success) {
throw new NucleusException("DeleteTables operation failed");
}
}
}
Aggregations