diff --git a/liquibase-standard/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java b/liquibase-standard/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java index 26a339593c9..4829ce6a7dd 100644 --- a/liquibase-standard/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java +++ b/liquibase-standard/src/main/java/liquibase/snapshot/JdbcDatabaseSnapshot.java @@ -400,7 +400,7 @@ public List fastFetchQuery() throws SQLException, DatabaseException { SQL_FILTER_MATCH_ALL) ); // - // IF MARIADB + // IF MARIADB OR SQL ANYWHERE // Query to get actual data types and then map each column to its CachedRow // determineActualDataTypes(returnList, tableName); @@ -431,7 +431,7 @@ public List bulkFetchQuery() throws SQLException, DatabaseException { escapeForLike(((AbstractJdbcDatabase) database).getJdbcSchemaName(catalogAndSchema), database), SQL_FILTER_MATCH_ALL, SQL_FILTER_MATCH_ALL)); // - // IF MARIADB + // IF MARIADB OR SQL ANYWHERE // Query to get actual data types and then map each column to its CachedRow // determineActualDataTypes(returnList, null); @@ -449,11 +449,58 @@ public List bulkFetchQuery() throws SQLException, DatabaseException { // For MariaDB, query for the data type column so that we can correctly // set the DATETIME(6) type if specified // + // For SQL Anywhere, query for the scale column so we can correctly + // set the size unit + // private void determineActualDataTypes(List returnList, String tableName) { // - // If not MariaDB then just return + // If not MariaDB / SQL Anywhere then just return // - if (!(database instanceof MariaDBDatabase)) { + if (!(database instanceof MariaDBDatabase || database instanceof SybaseASADatabase)) { + return; + } + + if (database instanceof SybaseASADatabase) { + // + // Query for actual data type for column. The actual SYSTABCOL.scale column value is + // not reported by the DatabaseMetadata.getColumns() query for CHAR-limited (in contrast + // to BYTE-limited) columns, and it is needed to capture the kind if limitation. + // + // See https://help.sap.com/docs/SAP_SQL_Anywhere/93079d4ba8e44920ae63ffb4def91f5b/3beaa3956c5f1014883cb0c3e3559cc9.html. + // + String selectStatement = + "SELECT table_name, column_name, scale FROM SYSTABCOL KEY JOIN SYSTAB KEY JOIN SYSUSER " + + "WHERE user_name = ? AND ? IS NULL OR table_name = ?"; + Connection underlyingConnection = ((JdbcConnection) database.getConnection()).getUnderlyingConnection(); + try (PreparedStatement stmt = underlyingConnection.prepareStatement(selectStatement)) { + stmt.setString(1, schemaName); + stmt.setString(2, tableName); + stmt.setString(3, tableName); + try (ResultSet columnSelectRS = stmt.executeQuery()) { + while (columnSelectRS.next()) { + String selectedTableName = columnSelectRS.getString("table_name"); + String selectedColumnName = columnSelectRS.getString("column_name"); + int selectedScale = columnSelectRS.getInt("scale"); + for (CachedRow row : returnList) { + String rowTableName = row.getString("TABLE_NAME"); + String rowColumnName = row.getString("COLUMN_NAME"); + if (rowTableName.equalsIgnoreCase(selectedTableName) && + rowColumnName.equalsIgnoreCase(selectedColumnName)) { + int rowDataType = row.getInt("DATA_TYPE"); + if (rowDataType == Types.VARCHAR || rowDataType == Types.CHAR) { + row.set("scale", selectedScale); + } + break; + } + } + } + } + } catch (SQLException sqle) { + throw new RuntimeException(sqle); + // + // Do not stop + // + } return; } diff --git a/liquibase-standard/src/main/java/liquibase/snapshot/jvm/ColumnSnapshotGenerator.java b/liquibase-standard/src/main/java/liquibase/snapshot/jvm/ColumnSnapshotGenerator.java index 5350642c8d0..8a58866bb4e 100644 --- a/liquibase-standard/src/main/java/liquibase/snapshot/jvm/ColumnSnapshotGenerator.java +++ b/liquibase-standard/src/main/java/liquibase/snapshot/jvm/ColumnSnapshotGenerator.java @@ -411,6 +411,12 @@ protected DataType readDataType(CachedRow columnMetadataResultSet, Column column DataType.ColumnSizeUnit columnSizeUnit = DataType.ColumnSizeUnit.BYTE; + if (database instanceof SybaseASADatabase && + (columnMetadataResultSet.getInt("DATA_TYPE") == Types.VARCHAR || columnMetadataResultSet.getInt("DATA_TYPE") == Types.CHAR) && + columnMetadataResultSet.getInt("scale") == 1) { + columnSizeUnit = DataType.ColumnSizeUnit.CHAR; + } + int dataType = columnMetadataResultSet.getInt("DATA_TYPE"); Integer columnSize = null; Integer decimalDigits = null;