@Override protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) throws DatabaseException, InvalidExampleException { Database database = snapshot.getDatabase(); Relation relation = ((Column) example).getRelation(); if (((Column) example).getComputed() != null && ((Column) example).getComputed()) { return example; } Schema schema = relation.getSchema(); List<CachedRow> columnMetadataRs = null; try { JdbcDatabaseSnapshot.CachingDatabaseMetaData databaseMetaData = ((JdbcDatabaseSnapshot) snapshot).getMetaData(); columnMetadataRs = databaseMetaData.getColumns( ((AbstractJdbcDatabase) database).getJdbcCatalogName(schema), ((AbstractJdbcDatabase) database).getJdbcSchemaName(schema), relation.getName(), example.getName()); if (columnMetadataRs.size() > 0) { CachedRow data = columnMetadataRs.get(0); Column column = readColumn(data, relation, database); if (column != null && database instanceof MSSQLDatabase && database.getDatabaseMajorVersion() >= 8) { String sql; if (database.getDatabaseMajorVersion() >= 9) { // SQL Server 2005 or later // https://technet.microsoft.com/en-us/library/ms177541.aspx sql = "SELECT CAST([ep].[value] AS [nvarchar](MAX)) AS [REMARKS] " + "FROM [sys].[extended_properties] AS [ep] " + "WHERE [ep].[class] = 1 " + "AND [ep].[major_id] = OBJECT_ID(N'" + database.escapeStringForDatabase( database.escapeTableName( schema.getCatalogName(), schema.getName(), relation.getName())) + "') " + "AND [ep].[minor_id] = COLUMNPROPERTY([ep].[major_id], N'" + database.escapeStringForDatabase(column.getName()) + "', 'ColumnId') " + "AND [ep].[name] = 'MS_Description'"; } else { // SQL Server 2000 // https://technet.microsoft.com/en-us/library/aa224810%28v=sql.80%29.aspx sql = "SELECT CAST([p].[value] AS [ntext]) AS [REMARKS] " + "FROM [dbo].[sysproperties] AS [p] " + "WHERE [p].[id] = OBJECT_ID(N'" + database.escapeStringForDatabase( database.escapeTableName( schema.getCatalogName(), schema.getName(), relation.getName())) + "') " + "AND [p].[smallid] = COLUMNPROPERTY([p].[id], N'" + database.escapeStringForDatabase(column.getName()) + "', 'ColumnId') " + "AND [p].[type] = 4 " + "AND [p].[name] = 'MS_Description'"; } List<String> remarks = ExecutorService.getInstance() .getExecutor(snapshot.getDatabase()) .queryForList(new RawSqlStatement(sql), String.class); if (remarks != null && remarks.size() > 0) { column.setRemarks(StringUtils.trimToNull(remarks.iterator().next())); } } return column; } else { return null; } } catch (Exception e) { throw new DatabaseException(e); } }
protected Column readColumn(CachedRow columnMetadataResultSet, Relation table, Database database) throws SQLException, DatabaseException { String rawTableName = (String) columnMetadataResultSet.get("TABLE_NAME"); String rawColumnName = (String) columnMetadataResultSet.get("COLUMN_NAME"); String rawSchemaName = StringUtils.trimToNull((String) columnMetadataResultSet.get("TABLE_SCHEM")); String rawCatalogName = StringUtils.trimToNull((String) columnMetadataResultSet.get("TABLE_CAT")); String remarks = StringUtils.trimToNull((String) columnMetadataResultSet.get("REMARKS")); if (remarks != null) { remarks = remarks.replace("''", "'"); // come back escaped sometimes } Column column = new Column(); column.setName(StringUtils.trimToNull(rawColumnName)); column.setRelation(table); column.setRemarks(remarks); if (database instanceof OracleDatabase) { String nullable = columnMetadataResultSet.getString("NULLABLE"); if (nullable.equals("Y")) { column.setNullable(true); } else { column.setNullable(false); } } else { int nullable = columnMetadataResultSet.getInt("NULLABLE"); if (nullable == DatabaseMetaData.columnNoNulls) { column.setNullable(false); } else if (nullable == DatabaseMetaData.columnNullable) { column.setNullable(true); } else if (nullable == DatabaseMetaData.columnNullableUnknown) { LogFactory.getLogger() .info("Unknown nullable state for column " + column.toString() + ". Assuming nullable"); column.setNullable(true); } } if (database.supportsAutoIncrement()) { if (table instanceof Table) { if (columnMetadataResultSet.containsColumn("IS_AUTOINCREMENT")) { String isAutoincrement = (String) columnMetadataResultSet.get("IS_AUTOINCREMENT"); isAutoincrement = StringUtils.trimToNull(isAutoincrement); if (isAutoincrement == null) { column.setAutoIncrementInformation(null); } else if (isAutoincrement.equals("YES")) { column.setAutoIncrementInformation(new Column.AutoIncrementInformation()); } else if (isAutoincrement.equals("NO")) { column.setAutoIncrementInformation(null); } else if (isAutoincrement.equals("")) { LogFactory.getLogger() .info( "Unknown auto increment state for column " + column.toString() + ". Assuming not auto increment"); column.setAutoIncrementInformation(null); } else { throw new UnexpectedLiquibaseException( "Unknown is_autoincrement value: '" + isAutoincrement + "'"); } } else { // probably older version of java, need to select from the column to find out if it is // auto-increment String selectStatement; if (database.getDatabaseProductName().startsWith("DB2 UDB for AS/400")) { selectStatement = "select " + database.escapeColumnName( rawCatalogName, rawSchemaName, rawTableName, rawColumnName) + " from " + rawSchemaName + "." + rawTableName + " where 0=1"; LogFactory.getLogger().debug("rawCatalogName : <" + rawCatalogName + ">"); LogFactory.getLogger().debug("rawSchemaName : <" + rawSchemaName + ">"); LogFactory.getLogger().debug("rawTableName : <" + rawTableName + ">"); LogFactory.getLogger().debug("raw selectStatement : <" + selectStatement + ">"); } else { selectStatement = "select " + database.escapeColumnName( rawCatalogName, rawSchemaName, rawTableName, rawColumnName) + " from " + database.escapeTableName(rawCatalogName, rawSchemaName, rawTableName) + " where 0=1"; } LogFactory.getLogger() .debug( "Checking " + rawTableName + "." + rawCatalogName + " for auto-increment with SQL: '" + selectStatement + "'"); Connection underlyingConnection = ((JdbcConnection) database.getConnection()).getUnderlyingConnection(); Statement statement = null; ResultSet columnSelectRS = null; try { statement = underlyingConnection.createStatement(); columnSelectRS = statement.executeQuery(selectStatement); if (columnSelectRS.getMetaData().isAutoIncrement(1)) { column.setAutoIncrementInformation(new Column.AutoIncrementInformation()); } else { column.setAutoIncrementInformation(null); } } finally { try { if (statement != null) { statement.close(); } } catch (SQLException ignore) { } if (columnSelectRS != null) { columnSelectRS.close(); } } } } } DataType type = readDataType(columnMetadataResultSet, column, database); column.setType(type); column.setDefaultValue(readDefaultValue(columnMetadataResultSet, column, database)); return column; }