Skip to content

Commit

Permalink
SNOW-937188 fixes to the unquoting and comparison of final session re…
Browse files Browse the repository at this point in the history
…turned by the server in case of values \"final\"
  • Loading branch information
sfc-gh-mhofman committed May 7, 2024
1 parent a73b38d commit 2849369
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 29 deletions.
30 changes: 30 additions & 0 deletions Snowflake.Data.Tests/UnitTests/SFSessionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,35 @@ public void TestThatConfiguresEasyLogging(string configPath)
// assert
easyLoggingStarter.Verify(starter => starter.Init(configPath));
}

[TestCase(null, "accountDefault", "accountDefault", false)]
[TestCase("initial", "initial", "initial", false)]
[TestCase("initial", null, "initial", false)]
[TestCase("initial", "IniTiaL", "initial", false)]
[TestCase("initial", "final", "final", true)]
[TestCase("initial", "\\\"final\\\"", "\"final\"", true)]
[TestCase("initial", "\\\"Final\\\"", "\"Final\"", true)]
[TestCase("\"Ini\\t\"ial\"", "\\\"Ini\\t\"ial\\\"", "\"Ini\\t\"ial\"", false)]
[TestCase("\"initial\"", "initial", "initial", true)]
[TestCase("\"initial\"", "\\\"initial\\\"", "\"initial\"", false)]
[TestCase("init\"ial", "init\"ial", "init\"ial", false)]
[TestCase("\"init\"ial\"", "\\\"init\"ial\\\"", "\"init\"ial\"", false)]
[TestCase("\"init\"ial\"", "\\\"Init\"ial\\\"", "\"Init\"ial\"", true)]
public void TestSessionPropertyQuotationSafeUpdateOnServerResponse(string sessionInitialValue, string serverResponseFinalSessionValue, string unquotedExpectedFinalValue, bool wasChanged)
{
// Arrange
SFSession sfSession = new SFSession("account=test;user=test;password=test", null);
var changedSessionValue = sessionInitialValue;

// Act
sfSession.UpdateSessionProperty(ref changedSessionValue, serverResponseFinalSessionValue);

// Assert
Assert.AreEqual(sfSession.SessionPropertiesChanged, wasChanged);
if (wasChanged || sessionInitialValue is null)
Assert.AreEqual(unquotedExpectedFinalValue, changedSessionValue);
else
Assert.AreEqual(sessionInitialValue, changedSessionValue);
}
}
}
46 changes: 17 additions & 29 deletions Snowflake.Data/Core/Session/SFSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -473,47 +473,35 @@ internal void UpdateSessionProperties(QueryExecResponseData responseData)
UpdateSessionProperty(ref warehouse, responseData.finalWarehouseName);
}

private void UpdateSessionProperty(ref string initialSessionValue, string finalSessionValue)
internal void UpdateSessionProperty(ref string initialSessionValue, string finalSessionValue)
{
// with HTAP session metadata removal database/schema might be not returned in query result
if (!string.IsNullOrEmpty(finalSessionValue))
{
if (!string.IsNullOrEmpty(initialSessionValue) && !IsEqualSkippingQuotes(initialSessionValue, finalSessionValue))
bool quoted = false;
string unquotedFinalValue = UnquoteJson(finalSessionValue, ref quoted);
if (!string.IsNullOrEmpty(initialSessionValue))
{
sessionPropertiesChanged = true;
quoted |= initialSessionValue.StartsWith('\"');

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net472, AZURE)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net472, AZURE)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net472, GCP)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net472, GCP)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net471, GCP)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net471, GCP)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net471, AWS)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net471, AWS)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net471, AZURE)

Argument 1: cannot convert from 'char' to 'string'

Check failure on line 485 in Snowflake.Data/Core/Session/SFSession.cs

View workflow job for this annotation

GitHub Actions / Tests on Windows (net471, AZURE)

Argument 1: cannot convert from 'char' to 'string'
if (!string.Equals(initialSessionValue, unquotedFinalValue, quoted ? StringComparison.Ordinal : StringComparison.InvariantCultureIgnoreCase))
{
sessionPropertiesChanged = true;
initialSessionValue = unquotedFinalValue;
}
}
else // null session value gets populated and is not treated as a session property change
{
initialSessionValue = unquotedFinalValue;
}
initialSessionValue = finalSessionValue;
}
}

private static bool IsEqualSkippingQuotes(string value1, string value2)
{
bool wasUnquoted1 = false, wasUnquoted2 = false;
var unquotedValue1 = Unquote(value1, ref wasUnquoted1);
var unquotedValue2 = Unquote(value2, ref wasUnquoted2);
return string.Equals(unquotedValue1,
unquotedValue2,
wasUnquoted1 || wasUnquoted2 ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase);
}

private static string Unquote(string value, ref bool unquoted)
private static string UnquoteJson(string value, ref bool unquoted)
{
if (value is null)
return value;
var valueLength = value.Length;
var unquotedJson = valueLength >= 4 && value.StartsWith("\\\"") && value.EndsWith("\\\"");
var unquotedStr = valueLength >= 2 && value[0] == '"' && value[valueLength-1] == '"';

var ret = value;
if (unquotedJson)
{
ret = value.Substring(2, valueLength - 4);
} else if (unquotedStr)
{
ret = value.Substring(1, valueLength - 2);
}
unquoted = unquotedJson || unquotedStr;
return ret;
unquoted = value.Length >= 2 && value.StartsWith("\\\"") && value.EndsWith("\\\"");
return unquoted ? value.Replace("\\\"", "\"") : value;
}

internal bool SessionPropertiesChanged => sessionPropertiesChanged;
Expand Down

0 comments on commit 2849369

Please sign in to comment.