Search in sources :

Example 1 with RDBMSColumnInfo

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;
}
Also used : RDBMSColumnInfo(org.datanucleus.store.rdbms.schema.RDBMSColumnInfo) HashMap(java.util.HashMap) SQLException(java.sql.SQLException) MissingColumnException(org.datanucleus.store.rdbms.exceptions.MissingColumnException) ArrayList(java.util.ArrayList) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) Iterator(java.util.Iterator) StoreSchemaData(org.datanucleus.store.schema.StoreSchemaData) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with RDBMSColumnInfo

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;
}
Also used : RDBMSColumnInfo(org.datanucleus.store.rdbms.schema.RDBMSColumnInfo) NotAViewException(org.datanucleus.store.rdbms.exceptions.NotAViewException) HashMap(java.util.HashMap) MissingColumnException(org.datanucleus.store.rdbms.exceptions.MissingColumnException) RDBMSSchemaHandler(org.datanucleus.store.rdbms.schema.RDBMSSchemaHandler) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) Iterator(java.util.Iterator) MissingTableException(org.datanucleus.store.rdbms.exceptions.MissingTableException) UnexpectedColumnException(org.datanucleus.store.rdbms.exceptions.UnexpectedColumnException)

Example 3 with RDBMSColumnInfo

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("");
    }
}
Also used : RDBMSColumnInfo(org.datanucleus.store.rdbms.schema.RDBMSColumnInfo) RDBMSTableInfo(org.datanucleus.store.rdbms.schema.RDBMSTableInfo) Connection(java.sql.Connection) NucleusConnection(org.datanucleus.store.NucleusConnection) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) MacroString(org.datanucleus.util.MacroString) SQLTypeInfo(org.datanucleus.store.rdbms.schema.SQLTypeInfo) JDBCTypeInfo(org.datanucleus.store.rdbms.schema.JDBCTypeInfo) ListIterator(java.util.ListIterator) Iterator(java.util.Iterator) DatastoreAdapter(org.datanucleus.store.rdbms.adapter.DatastoreAdapter) RDBMSTypesInfo(org.datanucleus.store.rdbms.schema.RDBMSTypesInfo) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) RDBMSSchemaInfo(org.datanucleus.store.rdbms.schema.RDBMSSchemaInfo)

Example 4 with RDBMSColumnInfo

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;
}
Also used : RDBMSColumnInfo(org.datanucleus.store.rdbms.schema.RDBMSColumnInfo)

Example 5 with RDBMSColumnInfo

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());
}
Also used : RDBMSColumnInfo(org.datanucleus.store.rdbms.schema.RDBMSColumnInfo) RDBMSTableInfo(org.datanucleus.store.rdbms.schema.RDBMSTableInfo) JDOPersistenceManager(org.datanucleus.api.jdo.JDOPersistenceManager) PersistenceManager(javax.jdo.PersistenceManager) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) Connection(java.sql.Connection) SchemaClass1(org.jpox.samples.rdbms.schema.SchemaClass1) StoreSchemaHandler(org.datanucleus.store.schema.StoreSchemaHandler) SchemaClass2(org.jpox.samples.rdbms.schema.SchemaClass2) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) Iterator(java.util.Iterator) Collection(java.util.Collection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) HashSet(java.util.HashSet)

Aggregations

RDBMSColumnInfo (org.datanucleus.store.rdbms.schema.RDBMSColumnInfo)12 Iterator (java.util.Iterator)5 HashMap (java.util.HashMap)3 DatastoreIdentifier (org.datanucleus.store.rdbms.identifier.DatastoreIdentifier)3 Connection (java.sql.Connection)2 MissingColumnException (org.datanucleus.store.rdbms.exceptions.MissingColumnException)2 RDBMSTableInfo (org.datanucleus.store.rdbms.schema.RDBMSTableInfo)2 SQLException (java.sql.SQLException)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 HashSet (java.util.HashSet)1 ListIterator (java.util.ListIterator)1 Map (java.util.Map)1 PersistenceManager (javax.jdo.PersistenceManager)1 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)1 JDOPersistenceManager (org.datanucleus.api.jdo.JDOPersistenceManager)1 NucleusConnection (org.datanucleus.store.NucleusConnection)1 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)1 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)1 DatastoreAdapter (org.datanucleus.store.rdbms.adapter.DatastoreAdapter)1