Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOW-1230345 Fix to support quoted values in object connection properties #891

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
43 changes: 39 additions & 4 deletions Snowflake.Data.Tests/UnitTests/SFSessionPropertyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@

namespace Snowflake.Data.Tests.UnitTests
{

class SFSessionPropertyTest
{

[Test, TestCaseSource(nameof(ConnectionStringTestCases))]
public void TestThatPropertiesAreParsed(TestCase testcase)
{
// act
var properties = SFSessionProperties.parseConnectionString(
var properties = SFSessionProperties.ParseConnectionString(
testcase.ConnectionString,
testcase.SecurePassword);

Expand All @@ -40,7 +41,7 @@ public void TestValidateCorrectAccountNames(string accountName, string expectedA
var connectionString = $"ACCOUNT={accountName};USER=test;PASSWORD=test;";

// act
var properties = SFSessionProperties.parseConnectionString(connectionString, null);
var properties = SFSessionProperties.ParseConnectionString(connectionString, null);

// assert
Assert.AreEqual(expectedAccountName, properties[SFSessionProperty.ACCOUNT]);
Expand All @@ -60,7 +61,7 @@ public void TestThatItFailsForWrongConnectionParameter(string connectionString,
{
// act
var exception = Assert.Throws<SnowflakeDbException>(
() => SFSessionProperties.parseConnectionString(connectionString, null)
() => SFSessionProperties.ParseConnectionString(connectionString, null)
);

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

// assert
Assert.AreEqual(SFError.MISSING_CONNECTION_PROPERTY.GetAttribute<SFErrorAttr>().errorCode, exception.ErrorCode);
}



[Test]
[TestCase("DB", SFSessionProperty.DB, "\"testdb\"")]
[TestCase("SCHEMA", SFSessionProperty.SCHEMA, "\"quotedSchema\"")]
[TestCase("ROLE", SFSessionProperty.ROLE, "\"userrole\"")]
[TestCase("WAREHOUSE", SFSessionProperty.WAREHOUSE, "\"warehouse test\"")]
public void TestValidateSupportEscapedQuotesValuesForObjectProperties(string propertyName, SFSessionProperty sessionProperty, string value)
{
// arrange
var connectionString = $"ACCOUNT=test;{propertyName}={value};USER=test;PASSWORD=test;";

// act
var properties = SFSessionProperties.ParseConnectionString(connectionString, null);

// assert
Assert.AreEqual(value, properties[sessionProperty]);
}

[Test]
public void TestProcessEmptyUserAndPasswordInConnectionString()
{
// arrange
var connectionString = $"ACCOUNT=test;USER=;PASSWORD=;";

// act
var properties = SFSessionProperties.ParseConnectionString(connectionString, null);

// assert
Assert.AreEqual(string.Empty, properties[SFSessionProperty.USER]);
Assert.AreEqual(string.Empty, properties[SFSessionProperty.PASSWORD]);
}

public static IEnumerable<TestCase> ConnectionStringTestCases()
{
string defAccount = "testaccount";
Expand Down Expand Up @@ -134,6 +168,7 @@ public static IEnumerable<TestCase> ConnectionStringTestCases()
{ SFSessionProperty.ALLOWUNDERSCORESINHOST, defAllowUnderscoresInHost }
}
};

var testCaseWithBrowserResponseTimeout = new TestCase()
{
ConnectionString = $"ACCOUNT={defAccount};BROWSER_RESPONSE_TIMEOUT=180;authenticator=externalbrowser",
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
88 changes: 52 additions & 36 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];
sfc-gh-knozderko marked this conversation as resolved.
Show resolved Hide resolved
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,37 +195,10 @@ internal static SFSessionProperties parseConnectionString(String connectionStrin
logger.Warn($"Property {keys[i]} not found ignored.", e);
}
}

UpdatePropertiesForSpecialCases(properties, connectionString);

//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, "");
}
}
}
}

bool useProxy = false;
var useProxy = false;
if (properties.ContainsKey(SFSessionProperty.USEPROXY))
{
try
Expand Down Expand Up @@ -292,6 +265,49 @@ internal static SFSessionProperties parseConnectionString(String connectionStrin
return properties;
}

private static void UpdatePropertiesForSpecialCases(SFSessionProperties properties, string connectionString)
{
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 sessionProperty = (SFSessionProperty)Enum.Parse(
typeof(SFSessionProperty), propertyName);
properties[sessionProperty]= tokens[1];
}

break;
}
case "USER":
case "PASSWORD":
{

var sessionProperty = (SFSessionProperty)Enum.Parse(
typeof(SFSessionProperty), propertyName);
if (!properties.ContainsKey(sessionProperty))
{
properties.Add(sessionProperty, "");
}

break;
}
}
}
}
}

private static void ValidateAccountDomain(SFSessionProperties properties)
{
var account = properties[SFSessionProperty.ACCOUNT];
Expand Down
Loading