use of org.datanucleus.store.rdbms.schema.RDBMSColumnInfo 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.rdbms.schema.RDBMSColumnInfo 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 autoCreateErrors) throws SQLException {
assertIsInitialized();
// 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);
}
long startTime = System.currentTimeMillis();
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
NucleusLogger.DATASTORE.debug(Localiser.msg("031004", this));
}
// 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.schema.RDBMSColumnInfo in project datanucleus-rdbms by datanucleus.
the class RDBMSStoreManager method printInformation.
/**
* Method to output particular information owned by this datastore.
* Supports "DATASTORE" and "SCHEMA" categories.
* @param category Category of information
* @param ps PrintStream
* @throws Exception Thrown if an error occurs in the output process
*/
public void printInformation(String category, PrintStream ps) throws Exception {
DatastoreAdapter dba = getDatastoreAdapter();
super.printInformation(category, ps);
if (category.equalsIgnoreCase("DATASTORE")) {
ps.println(dba.toString());
ps.println();
ps.println("Database TypeInfo");
RDBMSTypesInfo typesInfo = (RDBMSTypesInfo) schemaHandler.getSchemaData(null, "types", null);
if (typesInfo != null) {
Iterator iter = typesInfo.getChildren().keySet().iterator();
while (iter.hasNext()) {
String jdbcTypeStr = (String) iter.next();
short jdbcTypeNumber = 0;
try {
jdbcTypeNumber = Short.parseShort(jdbcTypeStr);
} catch (NumberFormatException nfe) {
}
JDBCTypeInfo jdbcType = (JDBCTypeInfo) typesInfo.getChild(jdbcTypeStr);
Collection<String> sqlTypeNames = jdbcType.getChildren().keySet();
StringBuilder sqlTypesName = new StringBuilder();
String defaultSqlTypeName = null;
for (String sqlTypeName : sqlTypeNames) {
if (!sqlTypeName.equals("DEFAULT")) {
if (sqlTypesName.length() > 0) {
sqlTypesName.append(',');
}
sqlTypesName.append(sqlTypeName);
} else {
defaultSqlTypeName = ((SQLTypeInfo) jdbcType.getChild(sqlTypeName)).getTypeName();
}
}
// SQL type names for JDBC type
String typeStr = "JDBC Type=" + dba.getNameForJDBCType(jdbcTypeNumber) + " sqlTypes=" + sqlTypesName + (defaultSqlTypeName != null ? (" (default=" + defaultSqlTypeName + ")") : "");
ps.println(typeStr);
for (String sqlTypeName : sqlTypeNames) {
// SQL type details
if (!sqlTypeName.equals("DEFAULT")) {
SQLTypeInfo sqlType = (SQLTypeInfo) jdbcType.getChild(sqlTypeName);
ps.println(sqlType.toString(" "));
}
}
}
}
ps.println("");
// Print out the keywords info
ps.println("Database Keywords");
Iterator reservedWordsIter = dba.iteratorReservedWords();
while (reservedWordsIter.hasNext()) {
Object words = reservedWordsIter.next();
ps.println(words);
}
ps.println("");
} else if (category.equalsIgnoreCase("SCHEMA")) {
ps.println(dba.toString());
ps.println();
ps.println("TABLES");
ManagedConnection mc = connectionMgr.getConnection(-1);
try {
Connection conn = (Connection) mc.getConnection();
RDBMSSchemaInfo schemaInfo = (RDBMSSchemaInfo) schemaHandler.getSchemaData(conn, "tables", new Object[] { this.catalogName, this.schemaName });
if (schemaInfo != null) {
Iterator tableIter = schemaInfo.getChildren().values().iterator();
while (tableIter.hasNext()) {
// Print out the table information
RDBMSTableInfo tableInfo = (RDBMSTableInfo) tableIter.next();
ps.println(tableInfo);
Iterator<StoreSchemaData> columnIter = tableInfo.getChildren().iterator();
while (columnIter.hasNext()) {
// Print out the column information
RDBMSColumnInfo colInfo = (RDBMSColumnInfo) columnIter.next();
ps.println(colInfo);
}
}
}
} finally {
if (mc != null) {
mc.release();
}
}
ps.println("");
}
}
use of org.datanucleus.store.rdbms.schema.RDBMSColumnInfo in project datanucleus-rdbms by datanucleus.
the class OracleAdapter method newRDBMSColumnInfo.
/**
* Method to create a column info for the current row.
* Overrides the dataType to cater for Oracle particularities.
* @param rs ResultSet from DatabaseMetaData.getColumns()
* @return column info
*/
public RDBMSColumnInfo newRDBMSColumnInfo(ResultSet rs) {
RDBMSColumnInfo info = new RDBMSColumnInfo(rs);
String typeName = info.getTypeName();
int dataType = -1;
if (typeName == null) {
dataType = Types.NULL;
} else if (typeName.equals("ROWID")) {
dataType = Types.INTEGER;
} else if (typeName.equals("NUMBER") || typeName.equals("VARNUM")) {
dataType = Types.NUMERIC;
} else if (typeName.equals("VARCHAR2")) {
dataType = Types.VARCHAR;
} else if (typeName.equals("CHAR")) {
dataType = Types.CHAR;
} else if (typeName.equals("DATE")) {
// should this be TIMESTAMP instead of DATE ??
dataType = Types.DATE;
} else if (typeName.equals("CLOB") || typeName.equals("NCLOB")) {
dataType = Types.CLOB;
} else if (typeName.equals("BLOB")) {
dataType = Types.BLOB;
} else if (typeName.equals("LONG")) {
dataType = Types.LONGVARCHAR;
} else if (typeName.equals("LONG RAW")) {
dataType = Types.LONGVARBINARY;
} else if (typeName.equals("RAW")) {
dataType = Types.VARBINARY;
} else if (typeName.startsWith("TIMESTAMP")) {
dataType = Types.TIMESTAMP;
} else if (typeName.equals("FLOAT")) {
dataType = Types.FLOAT;
} else {
NucleusLogger.DATASTORE.warn(Localiser.msg("020191", typeName));
dataType = Types.OTHER;
}
info.setDataType((short) dataType);
return info;
}
use of org.datanucleus.store.rdbms.schema.RDBMSColumnInfo in project tests by datanucleus.
the class SchemaHandlerTest method testColumnRetrieval.
/**
* Test of the retrieval of columns.
*/
public void testColumnRetrieval() {
addClassesToSchema(new Class[] { SchemaClass1.class, SchemaClass2.class });
PersistenceManager pm = pmf.getPersistenceManager();
RDBMSStoreManager databaseMgr = (RDBMSStoreManager) storeMgr;
StoreSchemaHandler handler = databaseMgr.getSchemaHandler();
ClassLoaderResolver clr = storeMgr.getNucleusContext().getClassLoaderResolver(null);
Connection con = (Connection) databaseMgr.getConnectionManager().getConnection(((JDOPersistenceManager) pm).getExecutionContext()).getConnection();
// Retrieve and check the table for SchemaClass1
DatastoreClass table1 = databaseMgr.getDatastoreClass(SchemaClass1.class.getName(), clr);
RDBMSTableInfo tableInfo1 = (RDBMSTableInfo) handler.getSchemaData(con, "columns", new Object[] { table1 });
assertNotNull("TableInfo from getColumns is NULL!", tableInfo1);
assertEquals("Number of columns for table " + table1 + " is wrong", 4, tableInfo1.getNumberOfChildren());
Iterator colsIter = tableInfo1.getChildren().iterator();
Collection colNamesPresent = new HashSet();
colNamesPresent.add("TABLE1_ID1");
colNamesPresent.add("TABLE1_ID2");
colNamesPresent.add("NAME");
colNamesPresent.add("OTHER_ID");
while (colsIter.hasNext()) {
RDBMSColumnInfo colInfo = (RDBMSColumnInfo) colsIter.next();
String colInfoName = colInfo.getColumnName().toUpperCase();
if (colInfoName.equals("TABLE1_ID1") || colInfoName.equals("TABLE1_ID2") || colInfoName.equals("NAME") || colInfoName.equals("OTHER_ID")) {
colNamesPresent.remove(colInfoName);
}
}
assertTrue("Some columns expected were not present in the datastore table : " + StringUtils.collectionToString(colNamesPresent), colNamesPresent.size() == 0);
// Retrieve and check the table for SchemaClass2
DatastoreClass table2 = databaseMgr.getDatastoreClass(SchemaClass2.class.getName(), clr);
RDBMSTableInfo tableInfo2 = (RDBMSTableInfo) handler.getSchemaData(con, "columns", new Object[] { table2 });
assertEquals("Number of columns for table " + table2 + " is wrong", 3, tableInfo2.getNumberOfChildren());
colsIter = tableInfo2.getChildren().iterator();
colNamesPresent.clear();
colNamesPresent.add("TABLE2_ID");
colNamesPresent.add("NAME");
colNamesPresent.add("VALUE");
while (colsIter.hasNext()) {
RDBMSColumnInfo colInfo = (RDBMSColumnInfo) colsIter.next();
String colInfoName = colInfo.getColumnName().toUpperCase();
if (colInfoName.equals("TABLE2_ID")) {
colNamesPresent.remove(colInfoName);
}
if (colInfoName.equals("NAME")) {
colNamesPresent.remove(colInfoName);
assertEquals("Length of column " + colInfo.getColumnName() + " has incorrect length", 20, colInfo.getColumnSize());
}
if (colInfoName.equals("VALUE")) {
colNamesPresent.remove(colInfoName);
}
}
assertTrue("Some columns expected were not present in the datastore table : " + StringUtils.collectionToString(colNamesPresent), colNamesPresent.size() == 0);
// Now check retrieval of a column for a table
RDBMSColumnInfo colInfo = (RDBMSColumnInfo) handler.getSchemaData(con, "column", new Object[] { table2, "VALUE" });
if (colInfo == null) {
colInfo = (RDBMSColumnInfo) handler.getSchemaData(con, "column", new Object[] { table2, "value" });
}
assertNotNull("Column VALUE for table " + table2 + " was not found", colInfo);
assertEquals("Column name is wrong", "VALUE", colInfo.getColumnName().toUpperCase());
}
Aggregations