Skip to content

Commit 1ffdebd

Browse files
quipsy-kargfilipelautert
authored andcommitted
mssql.bytesPerChar
1 parent ffca867 commit 1ffdebd

File tree

5 files changed

+51
-5
lines changed

5 files changed

+51
-5
lines changed

liquibase-cli/src/test/groovy/liquibase/integration/commandline/LiquibaseCommandLineTest.groovy

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,13 @@ Global Options
353353
environment variable:
354354
'LIQUIBASE_MONITOR_PERFORMANCE')
355355
356+
--mssql-bytes-per-char=PARAM
357+
Number of bytes needed to store one character
358+
(depends on database's character encoding)
359+
DEFAULT: 1
360+
(defaults file: 'mssql.bytesPerChar', environment
361+
variable: 'MSSQL_BYTES_PER_CHAR')
362+
356363
--on-missing-include-changelog=PARAM
357364
If set to WARN, then liquibase will not throw
358365
exception on missing changelog file, instead

liquibase-standard/src/main/java/liquibase/database/core/MSSQLDatabase.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import liquibase.change.AbstractSQLChange;
77
import liquibase.change.Change;
88
import liquibase.changelog.DatabaseChangeLog;
9+
import liquibase.configuration.AutoloadedConfigurations;
10+
import liquibase.configuration.ConfigurationDefinition;
911
import liquibase.database.AbstractJdbcDatabase;
1012
import liquibase.database.DatabaseConnection;
1113
import liquibase.database.OfflineConnection;
@@ -50,6 +52,8 @@ private MSSQL_SERVER_VERSIONS() {
5052
}
5153
}
5254

55+
public static final Pattern CHAR_PATTERN = Pattern.compile("^(\\d+)\\s*(?i)CHAR$");
56+
5357
private final HashMap<String, Integer> defaultDataTypeParameters = new HashMap<>();
5458

5559
protected static final int MSSQL_DEFAULT_TCP_PORT = 1433;
@@ -709,4 +713,22 @@ private static List<String> createReservedWordsCollection() {
709713
public boolean supportsDatabaseChangeLogHistory() {
710714
return true;
711715
}
716+
717+
/**
718+
* Calculates the number of bytes needed to hold the given number of characters.
719+
*
720+
* @param charCount The number of characters to hold.
721+
* @return The number of bytes needed to hold the given number of characters.
722+
*/
723+
public int byteSize(final int charCount) {
724+
return charCount * SpecificConfiguration.BYTES_PER_CHAR.getCurrentValue();
725+
}
726+
727+
public static class SpecificConfiguration implements AutoloadedConfigurations {
728+
public static final ConfigurationDefinition<Integer> BYTES_PER_CHAR = new ConfigurationDefinition.Builder("mssql")
729+
.define("bytesPerChar", Integer.class)
730+
.setDefaultValue(1)
731+
.setDescription("Number of bytes needed to store one character (depends on database's character encoding)")
732+
.build();
733+
}
712734
}

liquibase-standard/src/main/java/liquibase/datatype/core/CharType.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,24 @@
1818
import java.util.Arrays;
1919
import java.util.List;
2020
import java.util.Locale;
21+
import java.util.regex.Matcher;
2122

2223
@DataTypeInfo(name="char", aliases = {"java.sql.Types.CHAR", "bpchar", "character"}, minParameters = 0, maxParameters = 1, priority = LiquibaseDataType.PRIORITY_DEFAULT)
2324
public class CharType extends LiquibaseDataType {
2425
@Override
2526
public DatabaseDataType toDatabaseDataType(Database database) {
2627
if (database instanceof MSSQLDatabase) {
28+
final MSSQLDatabase mssqlDatabase = (MSSQLDatabase) database;
2729
Object[] parameters = getParameters();
2830
if (parameters.length > 0) {
29-
// MSSQL only supports (n) syntax but not (n CHAR) syntax, so we need to remove CHAR.
30-
final String param1 = parameters[0].toString().replaceFirst("(?<=\\d+)\\s*(?i)CHAR$", "");
31+
// MSSQL only supports (n) syntax but not (n CHAR) syntax, so we need to remove CHAR and apply bytes-per-char factor
32+
String param1 = parameters[0].toString();
33+
final Matcher matcher = MSSQLDatabase.CHAR_PATTERN.matcher(param1);
34+
if (matcher.find()) {
35+
final int characterCount = Integer.parseInt(matcher.group(1));
36+
final int byteCount = mssqlDatabase.byteSize(characterCount);
37+
param1 = String.valueOf(byteCount);
38+
}
3139
parameters[0] = param1;
3240
if (!param1.matches("\\d+") || (new BigInteger(param1).compareTo(BigInteger.valueOf(8000)) > 0)) {
3341

liquibase-standard/src/main/java/liquibase/datatype/core/VarcharType.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.math.BigInteger;
1010
import java.util.Arrays;
1111
import java.util.Locale;
12+
import java.util.regex.Matcher;
1213

1314
@DataTypeInfo(name="varchar", aliases = {"java.sql.Types.VARCHAR", "java.lang.String", "varchar2", "character varying"}, minParameters = 0, maxParameters = 1, priority = LiquibaseDataType.PRIORITY_DEFAULT)
1415
public class VarcharType extends CharType {
@@ -25,10 +26,17 @@ public DatabaseDataType toDatabaseDataType(Database database) {
2526
}
2627

2728
if (database instanceof MSSQLDatabase) {
29+
final MSSQLDatabase mssqlDatabase = (MSSQLDatabase) database;
2830
Object[] parameters = getParameters();
2931
if (parameters.length > 0) {
30-
// MSSQL only supports (n) syntax but not (n CHAR) syntax, so we need to remove CHAR.
31-
final String param1 = parameters[0].toString().replaceFirst("(?<=\\d+)\\s*(?i)CHAR$", "");
32+
// MSSQL only supports (n) syntax but not (n CHAR) syntax, so we need to remove CHAR and apply bytes-per-char factor
33+
String param1 = parameters[0].toString();
34+
final Matcher matcher = MSSQLDatabase.CHAR_PATTERN.matcher(param1);
35+
if (matcher.find()) {
36+
final int characterCount = Integer.parseInt(matcher.group(1));
37+
final int byteCount = mssqlDatabase.byteSize(characterCount);
38+
param1 = String.valueOf(byteCount);
39+
}
3240
parameters[0] = param1;
3341
if (!param1.matches("\\d+") || (new BigInteger(param1).compareTo(BigInteger.valueOf(8000L)) > 0)) {
3442

liquibase-standard/src/main/resources/META-INF/services/liquibase.configuration.AutoloadedConfigurations

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ liquibase.logging.core.DefaultLoggerConfiguration
44
liquibase.sql.SqlConfiguration
55
liquibase.parser.ChangeLogParserConfiguration
66
liquibase.analytics.configuration.AnalyticsArgs
7-
liquibase.license.LicenseTrackingArgs
7+
liquibase.license.LicenseTrackingArgs
8+
liquibase.database.core.MSSQLDatabase$SpecificConfiguration

0 commit comments

Comments
 (0)