Skip to content

Commit

Permalink
Fixed validation to special scenarios for warehouse property to allow…
Browse files Browse the repository at this point in the history
… scaped quotes on value.

Refactoring of code for special cases.
  • Loading branch information
sfc-gh-jmartinezramirez committed Mar 18, 2024
1 parent 4d85588 commit 648f7cc
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 43 deletions.
4 changes: 2 additions & 2 deletions Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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())
Expand Down
41 changes: 38 additions & 3 deletions Snowflake.Data.Tests/UnitTests/SFSessionPropertyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SFSessionPropertyTest
public void TestThatPropertiesAreParsed(TestCase testcase)
{
// act
var properties = SFSessionProperties.parseConnectionString(
var properties = SFSessionProperties.ParseConnectionString(
testcase.ConnectionString,
testcase.SecurePassword);

Expand Down Expand Up @@ -60,7 +60,7 @@ public void TestThatItFailsForWrongConnectionParameter(string connectionString,
{
// act
var exception = Assert.Throws<SnowflakeDbException>(
() => SFSessionProperties.parseConnectionString(connectionString, null)
() => SFSessionProperties.ParseConnectionString(connectionString, null)
);

// assert
Expand All @@ -75,7 +75,7 @@ public void TestThatItFailsIfNoAccountSpecified(string connectionString)
{
// act
var exception = Assert.Throws<SnowflakeDbException>(
() => SFSessionProperties.parseConnectionString(connectionString, null)
() => SFSessionProperties.ParseConnectionString(connectionString, null)
);

// assert
Expand Down Expand Up @@ -134,6 +134,40 @@ public static IEnumerable<TestCase> 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",
Expand Down Expand Up @@ -438,6 +472,7 @@ public static IEnumerable<TestCase> ConnectionStringTestCases()
return new TestCase[]
{
simpleTestCase,
testCaseWithWrappedValuesWithQuotesAndAllowSpaces,
testCaseWithBrowserResponseTimeout,
testCaseWithProxySettings,
testCaseThatDefaultForUseProxyIsFalse,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public void TestExtractProperties(PropertiesTestCase testCase)
// arrange
var proxyExtractorMock = new Moq.Mock<SFSessionHttpClientProxyProperties.IExtractor>();
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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion Snowflake.Data/Core/Session/SFSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
86 changes: 51 additions & 35 deletions Snowflake.Data/Core/Session/SFSessionProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<keys.Length; i++)
for(var i=0; i<keys.Length; i++)
{
try
{
Expand All @@ -195,35 +195,8 @@ internal static SFSessionProperties parseConnectionString(String connectionStrin
logger.Warn($"Property {keys[i]} not found ignored.", e);
}
}

//handle DbConnectionStringBuilder missing cases
string[] propertyEntry = connectionString.Split(';');
foreach(string keyVal in propertyEntry)
{
if(keyVal.Length > 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))
Expand Down Expand Up @@ -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];
Expand Down

0 comments on commit 648f7cc

Please sign in to comment.