diff --git a/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs b/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs index 816e064b3..8d69fe606 100644 --- a/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs +++ b/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs @@ -1652,7 +1652,7 @@ public void testMulitpleConnectionInParallel() } [Test] - [Ignore("Ignore this test, please test this manual with breakpoint at SFSessionProperty::parseConnectionString() to verify")] + [Ignore("Ignore this test, please test this manual with breakpoint at SFSessionProperty::ParseConnectionString() to verify")] public void TestEscapeChar() { using (IDbConnection conn = new SnowflakeDbConnection()) @@ -1679,7 +1679,7 @@ public void TestEscapeChar() } [Test] - [Ignore("Ignore this test, please test this manual with breakpoint at SFSessionProperty::parseConnectionString() to verify")] + [Ignore("Ignore this test, please test this manual with breakpoint at SFSessionProperty::ParseConnectionString() to verify")] public void TestEscapeChar1() { using (IDbConnection conn = new SnowflakeDbConnection()) diff --git a/Snowflake.Data.Tests/UnitTests/SFSessionPropertyTest.cs b/Snowflake.Data.Tests/UnitTests/SFSessionPropertyTest.cs index 694af9b5e..3a3590077 100644 --- a/Snowflake.Data.Tests/UnitTests/SFSessionPropertyTest.cs +++ b/Snowflake.Data.Tests/UnitTests/SFSessionPropertyTest.cs @@ -18,7 +18,7 @@ class SFSessionPropertyTest public void TestThatPropertiesAreParsed(TestCase testcase) { // act - var properties = SFSessionProperties.parseConnectionString( + var properties = SFSessionProperties.ParseConnectionString( testcase.ConnectionString, testcase.SecurePassword); @@ -60,7 +60,7 @@ public void TestThatItFailsForWrongConnectionParameter(string connectionString, { // act var exception = Assert.Throws( - () => SFSessionProperties.parseConnectionString(connectionString, null) + () => SFSessionProperties.ParseConnectionString(connectionString, null) ); // assert @@ -75,7 +75,7 @@ public void TestThatItFailsIfNoAccountSpecified(string connectionString) { // act var exception = Assert.Throws( - () => SFSessionProperties.parseConnectionString(connectionString, null) + () => SFSessionProperties.ParseConnectionString(connectionString, null) ); // assert @@ -134,6 +134,40 @@ public static IEnumerable ConnectionStringTestCases() { SFSessionProperty.ALLOWUNDERSCORESINHOST, defAllowUnderscoresInHost } } }; + + var warehouseWithSpaces = "\"warehouse test\""; + var dbWithQuotes = "\"testdb\""; + var testCaseWithWrappedValuesWithQuotesAndAllowSpaces = new TestCase() + { + ConnectionString = $"ACCOUNT={defAccount};USER={defUser};PASSWORD={defPassword};WAREHOUSE={warehouseWithSpaces};DB={dbWithQuotes}", + ExpectedProperties = new SFSessionProperties() + { + { SFSessionProperty.ACCOUNT, defAccount }, + { SFSessionProperty.USER, defUser }, + { SFSessionProperty.HOST, defHost }, + { SFSessionProperty.WAREHOUSE, warehouseWithSpaces }, + { SFSessionProperty.DB, dbWithQuotes }, + { SFSessionProperty.AUTHENTICATOR, defAuthenticator }, + { SFSessionProperty.SCHEME, defScheme }, + { SFSessionProperty.CONNECTION_TIMEOUT, defConnectionTimeout }, + { SFSessionProperty.PASSWORD, defPassword }, + { SFSessionProperty.PORT, defPort }, + { SFSessionProperty.VALIDATE_DEFAULT_PARAMETERS, "true" }, + { SFSessionProperty.USEPROXY, "false" }, + { SFSessionProperty.INSECUREMODE, "false" }, + { SFSessionProperty.DISABLERETRY, "false" }, + { SFSessionProperty.FORCERETRYON404, "false" }, + { SFSessionProperty.CLIENT_SESSION_KEEP_ALIVE, "false" }, + { SFSessionProperty.FORCEPARSEERROR, "false" }, + { SFSessionProperty.BROWSER_RESPONSE_TIMEOUT, defBrowserResponseTime }, + { SFSessionProperty.RETRY_TIMEOUT, defRetryTimeout }, + { SFSessionProperty.MAXHTTPRETRIES, defMaxHttpRetries }, + { SFSessionProperty.INCLUDERETRYREASON, defIncludeRetryReason }, + { SFSessionProperty.DISABLEQUERYCONTEXTCACHE, defDisableQueryContextCache }, + { SFSessionProperty.DISABLE_CONSOLE_LOGIN, defDisableConsoleLogin }, + { SFSessionProperty.ALLOWUNDERSCORESINHOST, defAllowUnderscoresInHost } + } + }; var testCaseWithBrowserResponseTimeout = new TestCase() { ConnectionString = $"ACCOUNT={defAccount};BROWSER_RESPONSE_TIMEOUT=180;authenticator=externalbrowser", @@ -438,6 +472,7 @@ public static IEnumerable ConnectionStringTestCases() return new TestCase[] { simpleTestCase, + testCaseWithWrappedValuesWithQuotesAndAllowSpaces, testCaseWithBrowserResponseTimeout, testCaseWithProxySettings, testCaseThatDefaultForUseProxyIsFalse, diff --git a/Snowflake.Data.Tests/UnitTests/Session/SFHttpClientPropertiesTest.cs b/Snowflake.Data.Tests/UnitTests/Session/SFHttpClientPropertiesTest.cs index 72421f588..617e3d429 100644 --- a/Snowflake.Data.Tests/UnitTests/Session/SFHttpClientPropertiesTest.cs +++ b/Snowflake.Data.Tests/UnitTests/Session/SFHttpClientPropertiesTest.cs @@ -115,7 +115,7 @@ public void TestExtractProperties(PropertiesTestCase testCase) // arrange var proxyExtractorMock = new Moq.Mock(); var extractor = new SFSessionHttpClientProperties.Extractor(proxyExtractorMock.Object); - var properties = SFSessionProperties.parseConnectionString(testCase.conectionString, null); + var properties = SFSessionProperties.ParseConnectionString(testCase.conectionString, null); var proxyProperties = new SFSessionHttpClientProxyProperties(); proxyExtractorMock .Setup(e => e.ExtractProperties(properties)) diff --git a/Snowflake.Data.Tests/UnitTests/Session/SFHttpClientProxyPropertiesTest.cs b/Snowflake.Data.Tests/UnitTests/Session/SFHttpClientProxyPropertiesTest.cs index a39d9bede..53941cc27 100644 --- a/Snowflake.Data.Tests/UnitTests/Session/SFHttpClientProxyPropertiesTest.cs +++ b/Snowflake.Data.Tests/UnitTests/Session/SFHttpClientProxyPropertiesTest.cs @@ -17,7 +17,7 @@ public void ShouldExtractProxyProperties(ProxyPropertiesTestCase testCase) { // given var extractor = new SFSessionHttpClientProxyProperties.Extractor(); - var properties = SFSessionProperties.parseConnectionString(testCase.conectionString, null); + var properties = SFSessionProperties.ParseConnectionString(testCase.conectionString, null); // when var proxyProperties = extractor.ExtractProperties(properties); diff --git a/Snowflake.Data/Core/Session/SFSession.cs b/Snowflake.Data/Core/Session/SFSession.cs index e39370f19..8f56fdda4 100755 --- a/Snowflake.Data/Core/Session/SFSession.cs +++ b/Snowflake.Data/Core/Session/SFSession.cs @@ -152,7 +152,7 @@ internal SFSession( { _easyLoggingStarter = easyLoggingStarter; connStr = connectionString; - properties = SFSessionProperties.parseConnectionString(connectionString, password); + properties = SFSessionProperties.ParseConnectionString(connectionString, password); _disableQueryContextCache = bool.Parse(properties[SFSessionProperty.DISABLEQUERYCONTEXTCACHE]); _disableConsoleLogin = bool.Parse(properties[SFSessionProperty.DISABLE_CONSOLE_LOGIN]); ValidateApplicationName(properties); diff --git a/Snowflake.Data/Core/Session/SFSessionProperty.cs b/Snowflake.Data/Core/Session/SFSessionProperty.cs index 4311fe88f..bb874fcee 100644 --- a/Snowflake.Data/Core/Session/SFSessionProperty.cs +++ b/Snowflake.Data/Core/Session/SFSessionProperty.cs @@ -160,10 +160,10 @@ public override int GetHashCode() return base.GetHashCode(); } - internal static SFSessionProperties parseConnectionString(String connectionString, SecureString password) + internal static SFSessionProperties ParseConnectionString(string connectionString, SecureString password) { logger.Info("Start parsing connection string."); - DbConnectionStringBuilder builder = new DbConnectionStringBuilder(); + var builder = new DbConnectionStringBuilder(); try { builder.ConnectionString = connectionString; @@ -175,14 +175,14 @@ internal static SFSessionProperties parseConnectionString(String connectionStrin SFError.INVALID_CONNECTION_STRING, e.Message); } - SFSessionProperties properties = new SFSessionProperties(); + var properties = new SFSessionProperties(); - string[] keys = new string[builder.Keys.Count]; - string[] values = new string[builder.Values.Count]; + var keys = new string[builder.Keys.Count]; + var values = new string[builder.Values.Count]; builder.Keys.CopyTo(keys, 0); builder.Values.CopyTo(values,0); - for(int i=0; i 0) - { - string[] tokens = keyVal.Split(new string[] { "=" }, StringSplitOptions.None); - if(tokens[0].ToUpper() == "DB" || tokens[0].ToUpper() == "SCHEMA" || - tokens[0].ToLower() == "WAREHOUSE" || tokens[0].ToUpper() == "ROLE") - { - if (tokens.Length == 2) - { - SFSessionProperty p = (SFSessionProperty)Enum.Parse( - typeof(SFSessionProperty), tokens[0].ToUpper()); - properties[p]= tokens[1]; - } - } - if(tokens[0].ToUpper() == "USER" || tokens[0].ToUpper() == "PASSWORD") - { - SFSessionProperty p = (SFSessionProperty)Enum.Parse( - typeof(SFSessionProperty), tokens[0].ToUpper()); - if (!properties.ContainsKey(p)) - { - properties.Add(p, ""); - } - } - } - } + + ProcessPropertySpecialCases(connectionString, properties); bool useProxy = false; if (properties.ContainsKey(SFSessionProperty.USEPROXY)) @@ -292,6 +265,49 @@ internal static SFSessionProperties parseConnectionString(String connectionStrin return properties; } + private static void ProcessPropertySpecialCases(string connectionString, SFSessionProperties properties) + { + var propertyEntry = connectionString.Split(';'); + foreach(var keyVal in propertyEntry) + { + if(keyVal.Length > 0) + { + var tokens = keyVal.Split(new string[] { "=" }, StringSplitOptions.None); + var propertyName = tokens[0].ToUpper(); + switch (propertyName) + { + case "DB": + case "SCHEMA": + case "WAREHOUSE": + case "ROLE": + { + if (tokens.Length == 2) + { + var p = (SFSessionProperty)Enum.Parse( + typeof(SFSessionProperty), propertyName); + properties[p]= tokens[1]; + } + + break; + } + case "USER": + case "PASSWORD": + { + + var p = (SFSessionProperty)Enum.Parse( + typeof(SFSessionProperty), propertyName); + if (!properties.ContainsKey(p)) + { + properties.Add(p, ""); + } + + break; + } + } + } + } + } + private static void ValidateAccountDomain(SFSessionProperties properties) { var account = properties[SFSessionProperty.ACCOUNT];