diff --git a/src/main/java/org/utplsql/cli/LocaleInitializer.java b/src/main/java/org/utplsql/cli/LocaleInitializer.java index 830c742..75d5366 100644 --- a/src/main/java/org/utplsql/cli/LocaleInitializer.java +++ b/src/main/java/org/utplsql/cli/LocaleInitializer.java @@ -1,5 +1,7 @@ package org.utplsql.cli; +import org.utplsql.api.EnvironmentVariableUtil; + import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -7,10 +9,9 @@ /** This class makes sure the java locale is set according to the environment variables LC_ALL and LANG * We experienced that, in some cases, the locale was not set as expected, therefore this class implements some clear * rules: - * 1. If environment variable NLS_LANG is set, we try to parse its content and set locale according to its value if valid - * 2. If environment variable LC_ALL is set, we try to parse its content and set locale according to its value if valid - * 3. If environment variable LANG is set, we try to parse its content and set locale according to its value if valid - * 4. Otherwise we use default locale + * 1. If environment variable LC_ALL is set, we try to parse its content and set locale according to its value if valid + * 2. If environment variable LANG is set, we try to parse its content and set locale according to its value if valid + * 3. Otherwise we use default locale * * @author pesse */ @@ -23,12 +24,9 @@ class LocaleInitializer { */ static void initLocale() { - boolean localeChanged = setDefaultLocale(System.getenv("NLS_LANG")); - - if ( !localeChanged ) - localeChanged = setDefaultLocale(System.getenv("LC_ALL")); + boolean localeChanged = setDefaultLocale(EnvironmentVariableUtil.getEnvValue("LC_ALL")); if ( !localeChanged ) - setDefaultLocale(System.getenv("LANG")); + setDefaultLocale(EnvironmentVariableUtil.getEnvValue("LANG")); } /** Set the default locale from a given string like LC_ALL or LANG environment variable diff --git a/src/main/java/org/utplsql/cli/datasource/TestedDataSourceProvider.java b/src/main/java/org/utplsql/cli/datasource/TestedDataSourceProvider.java index 4ad5d62..f30cd91 100644 --- a/src/main/java/org/utplsql/cli/datasource/TestedDataSourceProvider.java +++ b/src/main/java/org/utplsql/cli/datasource/TestedDataSourceProvider.java @@ -1,14 +1,16 @@ package org.utplsql.cli.datasource; import com.zaxxer.hikari.HikariDataSource; +import org.utplsql.api.EnvironmentVariableUtil; import org.utplsql.cli.ConnectionConfig; import org.utplsql.cli.exception.DatabaseConnectionFailed; -import java.io.File; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class TestedDataSourceProvider { @@ -17,7 +19,6 @@ interface ConnectStringPossibility { String getMaskedConnectString(ConnectionConfig config); } - private final ConnectionConfig config; private List possibilities = new ArrayList<>(); @@ -32,12 +33,13 @@ public HikariDataSource getDataSource() throws SQLException { HikariDataSource ds = new HikariDataSource(); - testAndSetJdbcUrl(ds); + setInitSqlFrom_NLS_LANG(ds); + setThickOrThinJdbcUrl(ds); return ds; } - public void testAndSetJdbcUrl( HikariDataSource ds ) throws SQLException + private void setThickOrThinJdbcUrl(HikariDataSource ds ) throws SQLException { List errors = new ArrayList<>(); Throwable lastException = null; @@ -55,6 +57,33 @@ public void testAndSetJdbcUrl( HikariDataSource ds ) throws SQLException throw new DatabaseConnectionFailed(lastException); } + private void setInitSqlFrom_NLS_LANG(HikariDataSource ds ) { + String nls_lang = EnvironmentVariableUtil.getEnvValue("NLS_LANG"); + + if ( nls_lang != null ) { + Pattern pattern = Pattern.compile("^([a-zA-Z ]+)?_?([a-zA-Z ]+)?\\.?([a-zA-Z0-9]+)?$"); + Matcher matcher = pattern.matcher(nls_lang); + + List sqlCommands = new ArrayList<>(2); + if (matcher.matches()) { + if ( matcher.group(1) != null) + sqlCommands.add(String.format("ALTER SESSION SET NLS_LANGUAGE='%s'", matcher.group(1))); + if ( matcher.group(2) != null) + sqlCommands.add(String.format("ALTER SESSION SET NLS_TERRITORY='%s'", matcher.group(2))); + + if ( sqlCommands.size() > 0 ) { + StringBuilder sb = new StringBuilder(); + sb.append("BEGIN\n"); + for (String command : sqlCommands) + sb.append(String.format("EXECUTE IMMEDIATE q'[%s]';\n", command)); + sb.append("END;"); + + ds.setConnectionInitSql(sb.toString()); + } + } + } + } + private static class ThickConnectStringPossibility implements ConnectStringPossibility { @Override public String getConnectString(ConnectionConfig config) { diff --git a/src/test/java/org/utplsql/cli/DataSourceProviderIT.java b/src/test/java/org/utplsql/cli/DataSourceProviderIT.java index 56a254c..2aab023 100644 --- a/src/test/java/org/utplsql/cli/DataSourceProviderIT.java +++ b/src/test/java/org/utplsql/cli/DataSourceProviderIT.java @@ -5,19 +5,75 @@ import javax.sql.DataSource; import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; -public class DataSourceProviderIT { +class DataSourceProviderIT { @Test - public void connectToDatabase() throws IOException, SQLException { + void connectToDatabase() throws SQLException { + DataSource dataSource = getDataSource(); - ConnectionConfig config = new ConnectionConfig(TestHelper.getConnectionString()); + assertNotNull(dataSource); + } + + @Test + void initNlsLang() throws SQLException { + System.setProperty("NLS_LANG", "BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1"); + DataSource dataSource = getDataSource(); + + assertNotNull(dataSource); + checkNlsSessionParameter(dataSource, "NLS_LANGUAGE", "BRAZILIAN PORTUGUESE"); + checkNlsSessionParameter(dataSource, "NLS_TERRITORY", "BRAZIL"); + } + + @Test + void initPartialNlsLangTerritory() throws SQLException { + System.setProperty("NLS_LANG", "_SOMALIA"); + DataSource dataSource = getDataSource(); + + assertNotNull(dataSource); + checkNlsSessionParameter(dataSource, "NLS_TERRITORY", "SOMALIA"); + } + + @Test + void initPartialNlsLangLanguage() throws SQLException { + System.setProperty("NLS_LANG", "HINDI"); + DataSource dataSource = getDataSource(); + + assertNotNull(dataSource); + checkNlsSessionParameter(dataSource, "NLS_LANGUAGE", "HINDI"); + } - DataSource dataSource = new TestedDataSourceProvider(config).getDataSource(); + @Test + void initNlsLangEmpty() throws SQLException { + System.setProperty("NLS_LANG", ""); + DataSource dataSource = getDataSource(); assertNotNull(dataSource); } + + private DataSource getDataSource() throws SQLException { + ConnectionConfig config = new ConnectionConfig(TestHelper.getConnectionString()); + return new TestedDataSourceProvider(config).getDataSource(); + } + + private void checkNlsSessionParameter( DataSource dataSource, String parameterName, String expectedValue ) throws SQLException { + try ( Connection con = dataSource.getConnection() ) { + try (PreparedStatement stmt = con.prepareStatement("select value from nls_session_parameters where parameter = ?")) { + stmt.setString(1, parameterName); + ResultSet rs = stmt.executeQuery(); + if ( rs.next() ) + assertEquals(expectedValue, rs.getString(1)); + else + fail("Could not get NLS Session parameter value for '" + parameterName + "'"); + } + } + } }