Skip to content

Commit

Permalink
SNOW-1729244 fixes after CR
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-dstempniak committed Oct 14, 2024
1 parent 067ecd1 commit c8098f0
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 34 deletions.
2 changes: 0 additions & 2 deletions Snowflake.Data.Tests/IntegrationTests/SFBindTestIT.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/*
* Copyright (c) 2012-2024 Snowflake Computing Inc. All rights reserved.
*/
#nullable enable

using System;
using System.Data;
using System.Linq;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,41 @@ internal static IEnumerable<object[]> DateTimeConversionCases()
null,
DateTime.Parse("2024-07-11 21:20:05.1234568").ToLocalTime()
};
yield return new object[]
{
"9999-12-31 23:59:59.999999",
SFDataType.TIMESTAMP_NTZ.ToString(),
DateTime.Parse("9999-12-31 23:59:59.999999"),
DateTime.Parse("9999-12-31 23:59:59.999999")
};
yield return new object[]
{
"9999-12-31 23:59:59.999999 +1:00",
SFDataType.TIMESTAMP_TZ.ToString(),
null,
DateTime.SpecifyKind(DateTime.Parse("9999-12-31 22:59:59.999999"), DateTimeKind.Utc)
};
yield return new object[]
{
"9999-12-31 23:59:59.999999 +13:00",
SFDataType.TIMESTAMP_LTZ.ToString(),
null,
DateTime.Parse("9999-12-31 10:59:59.999999").ToLocalTime()
};
yield return new object[]
{
"0001-01-01 00:00:00",
SFDataType.TIMESTAMP_NTZ.ToString(),
DateTime.Parse("0001-01-01 00:00:00"),
DateTime.Parse("0001-01-01 00:00:00")
};
yield return new object[]
{
"0001-01-01 00:00:00 -1:00",
SFDataType.TIMESTAMP_TZ.ToString(),
null,
DateTime.SpecifyKind(DateTime.Parse("0001-01-01 01:00:00"), DateTimeKind.Utc)
};
}

[Test]
Expand Down Expand Up @@ -445,6 +480,41 @@ internal static IEnumerable<object[]> DateTimeOffsetConversionCases()
null,
DateTimeOffset.Parse("2024-07-11 14:20:05.1234568 -7:00")
};
yield return new object[]
{
"9999-12-31 23:59:59.999999",
SFDataType.TIMESTAMP_NTZ.ToString(),
DateTime.Parse("9999-12-31 23:59:59.999999"),
DateTimeOffset.Parse("9999-12-31 23:59:59.999999Z")
};
yield return new object[]
{
"9999-12-31 23:59:59.999999 +1:00",
SFDataType.TIMESTAMP_TZ.ToString(),
null,
DateTimeOffset.Parse("9999-12-31 23:59:59.999999 +1:00")
};
yield return new object[]
{
"9999-12-31 23:59:59.999999 +1:00",
SFDataType.TIMESTAMP_LTZ.ToString(),
null,
DateTimeOffset.Parse("9999-12-31 23:59:59.999999 +1:00")
};
yield return new object[]
{
"0001-01-01 00:00:00",
SFDataType.TIMESTAMP_NTZ.ToString(),
DateTime.Parse("0001-01-01 00:00:00"),
DateTimeOffset.Parse("0001-01-01 00:00:00Z")
};
yield return new object[]
{
"0001-01-01 00:00:00 -1:00",
SFDataType.TIMESTAMP_TZ.ToString(),
null,
DateTimeOffset.Parse("0001-01-01 00:00:00 -1:00")
};
}

private TimeZoneInfo GetTimeZone(SnowflakeDbConnection connection)
Expand Down
10 changes: 5 additions & 5 deletions Snowflake.Data.Tests/UnitTests/SFBindUploaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public void TestCsvDataConversionForDate(SFDataType dbType, string input, string
{
// Arrange
var dateExpected = DateTime.Parse(expected);
var check = SFDataConverter.csharpValToSfVal(SFDataType.DATE, dateExpected);
var check = SFDataConverter.CSharpValToSfVal(SFDataType.DATE, dateExpected);
Assert.AreEqual(check, input);
// Act
DateTime dateActual = DateTime.Parse(_bindUploader.GetCSVData(dbType.ToString(), input));
Expand All @@ -37,7 +37,7 @@ public void TestCsvDataConversionForTime(SFDataType dbType, string input, string
{
// Arrange
DateTime timeExpected = DateTime.Parse(expected);
var check = SFDataConverter.csharpValToSfVal(SFDataType.TIME, timeExpected);
var check = SFDataConverter.CSharpValToSfVal(SFDataType.TIME, timeExpected);
Assert.AreEqual(check, input);
// Act
DateTime timeActual = DateTime.Parse(_bindUploader.GetCSVData(dbType.ToString(), input));
Expand All @@ -56,7 +56,7 @@ public void TestCsvDataConversionForTimestampLtz(SFDataType dbType, string input
{
// Arrange
var timestampExpected = DateTimeOffset.Parse(expected);
var check = SFDataConverter.csharpValToSfVal(SFDataType.TIMESTAMP_LTZ, timestampExpected);
var check = SFDataConverter.CSharpValToSfVal(SFDataType.TIMESTAMP_LTZ, timestampExpected);
Assert.AreEqual(check, input);
// Act
var timestampActual = DateTimeOffset.Parse(_bindUploader.GetCSVData(dbType.ToString(), input));
Expand All @@ -73,7 +73,7 @@ public void TestCsvDataConversionForTimestampTz(SFDataType dbType, string input,
{
// Arrange
DateTimeOffset timestampExpected = DateTimeOffset.Parse(expected);
var check = SFDataConverter.csharpValToSfVal(SFDataType.TIMESTAMP_TZ, timestampExpected);
var check = SFDataConverter.CSharpValToSfVal(SFDataType.TIMESTAMP_TZ, timestampExpected);
Assert.AreEqual(check, input);
// Act
DateTimeOffset timestampActual = DateTimeOffset.Parse(_bindUploader.GetCSVData(dbType.ToString(), input));
Expand All @@ -90,7 +90,7 @@ public void TestCsvDataConversionForTimestampNtz(SFDataType dbType, string input
{
// Arrange
DateTime timestampExpected = DateTime.Parse(expected);
var check = SFDataConverter.csharpValToSfVal(SFDataType.TIMESTAMP_NTZ, timestampExpected);
var check = SFDataConverter.CSharpValToSfVal(SFDataType.TIMESTAMP_NTZ, timestampExpected);
Assert.AreEqual(check, input);
// Act
DateTime timestampActual = DateTime.Parse(_bindUploader.GetCSVData(dbType.ToString(), input));
Expand Down
8 changes: 4 additions & 4 deletions Snowflake.Data.Tests/UnitTests/SFDataConverterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void TestConvertBindToSFValFinlandLocale()
Thread.CurrentThread.CurrentCulture = ci;

System.Tuple<string, string> t =
SFDataConverter.csharpTypeValToSfTypeVal(System.Data.DbType.Double, 1.2345);
SFDataConverter.CSharpTypeValToSfTypeVal(System.Data.DbType.Double, 1.2345);

Assert.AreEqual("REAL", t.Item1);
Assert.AreEqual("1.2345", t.Item2);
Expand Down Expand Up @@ -150,7 +150,7 @@ public void TestConvertDate(string inputTimeStr, object kind = null)

private void internalTestConvertDate(DateTime dtExpected, DateTime testValue)
{
var result = SFDataConverter.csharpTypeValToSfTypeVal(System.Data.DbType.Date, testValue);
var result = SFDataConverter.CSharpTypeValToSfTypeVal(System.Data.DbType.Date, testValue);
// Convert result to DateTime for easier interpretation
var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime dtResult = unixEpoch.AddMilliseconds(Int64.Parse(result.Item2));
Expand Down Expand Up @@ -344,8 +344,8 @@ public void TestInvalidTimestampConversion(SFDataType dataType, Type unsupported
else
unsupportedObject = null;

Assert.NotNull(unsupportedType);
SnowflakeDbException ex = Assert.Throws<SnowflakeDbException>(() => SFDataConverter.csharpValToSfVal(dataType, unsupportedObject));
Assert.NotNull(unsupportedObject);
SnowflakeDbException ex = Assert.Throws<SnowflakeDbException>(() => SFDataConverter.CSharpValToSfVal(dataType, unsupportedObject));
SnowflakeDbExceptionAssert.HasErrorCode(ex, SFError.INVALID_DATA_CONVERSION);
}
}
Expand Down
12 changes: 12 additions & 0 deletions Snowflake.Data.Tests/UnitTests/StructuredTypesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ internal static IEnumerable<object[]> TimeConversionCases()
yield return new object[] {"2024-07-11 14:20:05.123456 -7:00", SFDataType.TIMESTAMP_LTZ.ToString(), DateTimeOffset.Parse("2024-07-11 14:20:05.123456 -7:00")};
yield return new object[] {"2024-07-11 14:20:05.123456 -7:00", SFDataType.TIMESTAMP_LTZ.ToString(), DateTime.Parse("2024-07-11 21:20:05.123456").ToLocalTime()};
yield return new object[] {"14:20:05.123456", SFDataType.TIME.ToString(), TimeSpan.Parse("14:20:05.123456")};
yield return new object[] {"9999-12-31 23:59:59.999999", SFDataType.TIMESTAMP_NTZ.ToString(), DateTime.Parse("9999-12-31 23:59:59.999999")};
yield return new object[] {"9999-12-31 23:59:59.999999", SFDataType.TIMESTAMP_NTZ.ToString(), DateTimeOffset.Parse("9999-12-31 23:59:59.999999Z")};
yield return new object[] {"9999-12-31 23:59:59.999999 +1:00", SFDataType.TIMESTAMP_TZ.ToString(), DateTimeOffset.Parse("9999-12-31 23:59:59.999999 +1:00")};
yield return new object[] {"9999-12-31 23:59:59.999999 +1:00", SFDataType.TIMESTAMP_TZ.ToString(), DateTime.SpecifyKind(DateTime.Parse("9999-12-31 22:59:59.999999"), DateTimeKind.Utc)};
yield return new object[] {"9999-12-31 23:59:59.999999 +1:00", SFDataType.TIMESTAMP_LTZ.ToString(), DateTimeOffset.Parse("9999-12-31 23:59:59.999999 +1:00")};
yield return new object[] {"9999-12-31 23:59:59.999999 +13:00", SFDataType.TIMESTAMP_LTZ.ToString(), DateTime.Parse("9999-12-31 10:59:59.999999").ToLocalTime()};
yield return new object[] {"0001-01-01 00:00:00.123456", SFDataType.TIMESTAMP_NTZ.ToString(), DateTime.Parse("0001-01-01 00:00:00.123456")};
yield return new object[] {"0001-01-01 00:00:00.123456", SFDataType.TIMESTAMP_NTZ.ToString(), DateTimeOffset.Parse("0001-01-01 00:00:00.123456Z")};
yield return new object[] {"0001-01-01 00:00:00.123456 -1:00", SFDataType.TIMESTAMP_TZ.ToString(), DateTimeOffset.Parse("0001-01-01 00:00:00.123456 -1:00")};
yield return new object[] {"0001-01-01 00:00:00.123456 -1:00", SFDataType.TIMESTAMP_TZ.ToString(), DateTime.SpecifyKind(DateTime.Parse("0001-01-01 01:00:00.123456"), DateTimeKind.Utc)};
yield return new object[] {"0001-01-01 00:00:00.123456 -1:00", SFDataType.TIMESTAMP_LTZ.ToString(), DateTimeOffset.Parse("0001-01-01 00:00:00.123456 -1:00")};
yield return new object[] {"0001-01-01 00:00:00.123456 -13:00", SFDataType.TIMESTAMP_LTZ.ToString(), DateTime.Parse("0001-01-01 13:00:00.123456").ToLocalTime()};
}
}
}
8 changes: 4 additions & 4 deletions Snowflake.Data/Client/SnowflakeDbCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -393,15 +393,15 @@ private static Dictionary<string, BindingDTO> convertToBindList(List<SnowflakeDb
if (parameter.SFDataType == SFDataType.None)
{
Tuple<string, string> typeAndVal = SFDataConverter
.csharpTypeValToSfTypeVal(parameter.DbType, val);
.CSharpTypeValToSfTypeVal(parameter.DbType, val);

bindingType = typeAndVal.Item1;
vals.Add(typeAndVal.Item2);
}
else
{
bindingType = parameter.SFDataType.ToString();
vals.Add(SFDataConverter.csharpValToSfVal(parameter.SFDataType, val));
vals.Add(SFDataConverter.CSharpValToSfVal(parameter.SFDataType, val));
}
}
bindingVal = vals;
Expand All @@ -411,14 +411,14 @@ private static Dictionary<string, BindingDTO> convertToBindList(List<SnowflakeDb
if (parameter.SFDataType == SFDataType.None)
{
Tuple<string, string> typeAndVal = SFDataConverter
.csharpTypeValToSfTypeVal(parameter.DbType, parameter.Value);
.CSharpTypeValToSfTypeVal(parameter.DbType, parameter.Value);
bindingType = typeAndVal.Item1;
bindingVal = typeAndVal.Item2;
}
else
{
bindingType = parameter.SFDataType.ToString();
bindingVal = SFDataConverter.csharpValToSfVal(parameter.SFDataType, parameter.Value);
bindingVal = SFDataConverter.CSharpValToSfVal(parameter.SFDataType, parameter.Value);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Snowflake.Data/Core/ArrowResultSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ internal override string GetString(int ordinal)
return ret;
case DateTime ret:
if (type == SFDataType.DATE)
return SFDataConverter.toDateString(ret, sfResultSetMetaData.dateOutputFormat);
return SFDataConverter.ToDateString(ret, sfResultSetMetaData.dateOutputFormat);
break;
}

Expand Down
22 changes: 11 additions & 11 deletions Snowflake.Data/Core/SFBindUploader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,35 +251,35 @@ internal string GetCSVData(string sType, string sValue)
return '"' + sValue.Replace("\"", "\"\"") + '"';
return sValue;
case "DATE":
long msFromEpoch = long.Parse(sValue); // SFDateConverter.csharpValToSfVal provides in [ms] from Epoch
long msFromEpoch = long.Parse(sValue); // SFDateConverter.CSharpValToSfVal provides in [ms] from Epoch
DateTime date = epoch.AddMilliseconds(msFromEpoch);
return date.ToShortDateString();
case "TIME":
long nsSinceMidnight = long.Parse(sValue); // SFDateConverter.csharpValToSfVal provides in [ns] from Midnight
long nsSinceMidnight = long.Parse(sValue); // SFDateConverter.CSharpValToSfVal provides in [ns] from Midnight
DateTime time = epoch.AddTicks(nsSinceMidnight/100);
return time.ToString("HH:mm:ss.fffffff");
case "TIMESTAMP_LTZ":
long ticksFromEpochLtz =
long.TryParse(sValue, out var nssLtz) ?
nssLtz / 100 :
(long)(decimal.Parse(sValue) / 100);
long.TryParse(sValue, out var nsLtz)
? nsLtz / 100
: (long)(decimal.Parse(sValue) / 100);

DateTime ltz = epoch.AddTicks(ticksFromEpochLtz);
return ltz.ToLocalTime().ToString("O"); // ISO 8601 format
case "TIMESTAMP_NTZ":
long ticksFromEpochNtz =
long.TryParse(sValue, out var nsNtz) ?
nsNtz / 100 :
(long)(decimal.Parse(sValue) / 100);
long.TryParse(sValue, out var nsNtz)
? nsNtz / 100
: (long)(decimal.Parse(sValue) / 100);

DateTime ntz = epoch.AddTicks(ticksFromEpochNtz);
return ntz.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
case "TIMESTAMP_TZ":
string[] tstzString = sValue.Split(' ');
long ticksFromEpochTz =
long.TryParse(tstzString[0], out var nsTz) ?
nsTz / 100 :
(long)(decimal.Parse(tstzString[0]) / 100);
long.TryParse(tstzString[0], out var nsTz)
? nsTz / 100
: (long)(decimal.Parse(tstzString[0]) / 100);

int timeZoneOffset = int.Parse(tstzString[1]) - 1440; // SFDateConverter provides in minutes increased by 1440m
DateTime timestamp = epoch.AddTicks(ticksFromEpochTz).AddMinutes(timeZoneOffset);
Expand Down
12 changes: 6 additions & 6 deletions Snowflake.Data/Core/SFDataConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ private static long GetTicksFromSecondAndNanosecond(UTF8Buffer srcVal)

}

internal static Tuple<string, string> csharpTypeValToSfTypeVal(DbType srcType, object srcVal)
internal static Tuple<string, string> CSharpTypeValToSfTypeVal(DbType srcType, object srcVal)
{
SFDataType destType;
string destVal;
Expand Down Expand Up @@ -300,7 +300,7 @@ internal static Tuple<string, string> csharpTypeValToSfTypeVal(DbType srcType, o
default:
throw new SnowflakeDbException(SFError.UNSUPPORTED_DOTNET_TYPE, srcType);
}
destVal = csharpValToSfVal(destType, srcVal);
destVal = CSharpValToSfVal(destType, srcVal);
return Tuple.Create(destType.ToString(), destVal);
}

Expand All @@ -323,10 +323,8 @@ internal static byte[] HexToBytes(string hex)
return bytes;
}

internal static string csharpValToSfVal(SFDataType sfDataType, object srcVal)
internal static string CSharpValToSfVal(SFDataType sfDataType, object srcVal)
{
string TicksToNanoSecondsString(long tickDiff) => tickDiff == 0 ? "0" : $"{tickDiff}00";

string destVal = null;

if (srcVal != DBNull.Value && srcVal != null)
Expand Down Expand Up @@ -431,7 +429,9 @@ internal static string csharpValToSfVal(SFDataType sfDataType, object srcVal)
return destVal;
}

internal static string toDateString(DateTime date, string formatter)
private static string TicksToNanoSecondsString(long tickDiff) => tickDiff == 0 ? "0" : $"{tickDiff}00";

internal static string ToDateString(DateTime date, string formatter)
{
// change formatter from "YYYY-MM-DD" to "yyyy-MM-dd"
formatter = formatter.Replace("Y", "y").Replace("m", "M").Replace("D", "d");
Expand Down
2 changes: 1 addition & 1 deletion Snowflake.Data/Core/SFResultSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ internal override string GetString(int ordinal)
var val = GetValue(ordinal);
if (val == DBNull.Value)
return null;
return SFDataConverter.toDateString((DateTime)val, sfResultSetMetaData.dateOutputFormat);
return SFDataConverter.ToDateString((DateTime)val, sfResultSetMetaData.dateOutputFormat);

default:
return GetObjectInternal(ordinal).SafeToString();
Expand Down

0 comments on commit c8098f0

Please sign in to comment.