Skip to content

Commit 9f25a34

Browse files
committed
Merge branch 'develop' into Bind-Complex-Types
2 parents ad8918b + fd5688b commit 9f25a34

File tree

10 files changed

+61
-33
lines changed

10 files changed

+61
-33
lines changed

.github/workflows/NuGet.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ jobs:
1414
github_token: ${{ secrets.GITHUB_TOKEN }}
1515
workflow: ci.yml
1616
workflow_conclusion: success
17-
branch: main
17+
branch: ${{github.ref_name}}
1818
name: nugetPackages-${{github.ref_name}}
1919

2020
- name: Display structure of downloaded files
2121
run: ls -R
2222

2323
- name: Push package to NuGet.org
24-
run: dotnet nuget push "**/*.nupkg" -k ${{ secrets.NUGET }} -s https://api.nuget.org/v3/index.json
24+
run: dotnet nuget push "**/*.nupkg" -k ${{ secrets.NUGET }} -s https://api.nuget.org/v3/index.json

DuckDB.NET.Bindings/Bindings.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ Added support for Varint type.
99

1010
Added support for writing to Enum columns when using managed Appender.
1111

12-
Updated to DuckDB v1.1.1
12+
Updated to DuckDB v1.1.2
1313
</PackageReleaseNotes>
1414
<RootNamespace>DuckDB.NET.Native</RootNamespace>
1515
<RuntimeIdentifiers>win-x64;win-arm64;linux-x64;linux-arm64;osx</RuntimeIdentifiers>
16-
<DuckDbArtifactRoot Condition=" '$(DuckDbArtifactRoot)' == '' ">https://github.com/duckdb/duckdb/releases/download/v1.1.1</DuckDbArtifactRoot>
16+
<DuckDbArtifactRoot Condition=" '$(DuckDbArtifactRoot)' == '' ">https://github.com/duckdb/duckdb/releases/download/v1.1.2</DuckDbArtifactRoot>
1717
<SignAssembly>True</SignAssembly>
1818
<AssemblyOriginatorKeyFile>..\keyPair.snk</AssemblyOriginatorKeyFile>
1919
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

DuckDB.NET.Bindings/DuckDBNativeObjects.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,6 @@ public struct DuckDBTimeTz
141141
public struct DuckDBTimestampStruct
142142
{
143143
public long Micros { get; set; }
144-
145-
public readonly DateTime ToDateTime()
146-
{
147-
var ticks = Micros * 10 + Utils.UnixEpochTicks;
148-
return new DateTime(ticks);
149-
}
150144
}
151145

152146
[StructLayout(LayoutKind.Sequential)]

DuckDB.NET.Bindings/Utils.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ namespace DuckDB.NET.Native;
77

88
public static class Utils
99
{
10-
internal const long UnixEpochTicks = 621355968000000000;
11-
1210
public static bool IsSuccess(this DuckDBState state)
1311
{
1412
return state == DuckDBState.Success;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
3+
namespace DuckDB.NET.Data.Extensions;
4+
5+
//https://stackoverflow.com/a/5359304/239438
6+
internal static class DateTimeExtensions
7+
{
8+
public const int TicksPerMicrosecond = 10;
9+
public const int NanosecondsPerTick = 100;
10+
11+
public static int Nanoseconds(this DateTime self)
12+
{
13+
#if NET8_0_OR_GREATER
14+
return self.Nanosecond;
15+
#else
16+
return (int)(self.Ticks % TimeSpan.TicksPerMillisecond % TicksPerMicrosecond) * NanosecondsPerTick;
17+
#endif
18+
}
19+
}

DuckDB.NET.Data/Internal/Reader/DateTimeVectorDataReader.cs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ internal sealed class DateTimeVectorDataReader : VectorDataReaderBase
1818

1919
private static readonly Type TimeOnlyType = typeof(TimeOnly);
2020
private static readonly Type TimeOnlyNullableType = typeof(TimeOnly?);
21-
2221
#endif
2322

2423
internal unsafe DateTimeVectorDataReader(void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName) : base(dataPointer, validityMaskPointer, columnType, columnName)
@@ -86,24 +85,21 @@ protected override T GetValidValue<T>(ulong offset, Type targetType)
8685
DuckDBType.TimestampTz => ReadTimestamp<T>(offset, targetType),
8786
DuckDBType.TimestampS => ReadTimestamp<T>(offset, targetType, 1000000),
8887
DuckDBType.TimestampMs => ReadTimestamp<T>(offset, targetType, 1000),
89-
DuckDBType.TimestampNs => ReadTimestamp<T>(offset, targetType, 1, 1000),
88+
DuckDBType.TimestampNs => ReadTimestamp<T>(offset, targetType, 1, 1000, true),
9089
_ => base.GetValidValue<T>(offset, targetType)
9190
};
9291
}
9392

94-
private T ReadTimestamp<T>(ulong offset, Type targetType, int factor = 1, int divisor = 1)
93+
private T ReadTimestamp<T>(ulong offset, Type targetType, int factor = 1, int divisor = 1, bool keepNanoseconds = false)
9594
{
96-
var timestampStruct = GetFieldData<DuckDBTimestampStruct>(offset);
97-
98-
timestampStruct.Micros = timestampStruct.Micros * factor / divisor;
95+
var (additionalTicks, timestamp) = ReadTimestamp(offset, factor, divisor, keepNanoseconds);
9996

10097
if (targetType == DateTimeType || targetType == DateTimeNullableType)
10198
{
102-
var dateTime = timestampStruct.ToDateTime();
99+
var dateTime = timestamp.ToDateTime().AddTicks(additionalTicks);
103100
return (T)(object)dateTime;
104101
}
105102

106-
var timestamp = NativeMethods.DateTimeHelpers.DuckDBFromTimestamp(timestampStruct);
107103
return (T)(object)timestamp;
108104
}
109105

@@ -118,7 +114,7 @@ internal override object GetValue(ulong offset, Type targetType)
118114
DuckDBType.TimestampTz => GetDateTime(offset, targetType),
119115
DuckDBType.TimestampS => GetDateTime(offset, targetType, 1000000),
120116
DuckDBType.TimestampMs => GetDateTime(offset, targetType, 1000),
121-
DuckDBType.TimestampNs => GetDateTime(offset, targetType, 1, 1000),
117+
DuckDBType.TimestampNs => GetDateTime(offset, targetType, 1, 1000, true),
122118
_ => base.GetValue(offset, targetType)
123119
};
124120
}
@@ -176,18 +172,18 @@ private object GetTime(ulong offset, Type targetType)
176172
return timeOnly;
177173
}
178174

179-
private object GetDateTime(ulong offset, Type targetType, int factor = 1, int divisor = 1)
175+
private object GetDateTime(ulong offset, Type targetType, int factor = 1, int divisor = 1, bool keepNanoseconds = false)
180176
{
181-
var data = GetFieldData<DuckDBTimestampStruct>(offset);
182-
183-
data.Micros = (data.Micros * factor / divisor);
177+
var (additionalTicks, timestamp) = ReadTimestamp(offset, factor, divisor, keepNanoseconds);
184178

185179
if (targetType == typeof(DateTime))
186180
{
187-
return data.ToDateTime();
181+
var dateTime = timestamp.ToDateTime().AddTicks(additionalTicks);
182+
183+
return dateTime;
188184
}
189185

190-
return NativeMethods.DateTimeHelpers.DuckDBFromTimestamp(data);
186+
return timestamp;
191187
}
192188

193189
private object GetDateTimeOffset(ulong offset, Type targetType)
@@ -201,4 +197,20 @@ private object GetDateTimeOffset(ulong offset, Type targetType)
201197

202198
return timeTz;
203199
}
200+
201+
private (int additionalTicks, DuckDBTimestamp timestamp) ReadTimestamp(ulong offset, int factor, int divisor, bool keepNanoseconds)
202+
{
203+
var data = GetFieldData<DuckDBTimestampStruct>(offset);
204+
var additionalTicks = 0;
205+
206+
if (keepNanoseconds)
207+
{
208+
additionalTicks = (int)(data.Micros % 1000 / 100);
209+
}
210+
211+
data.Micros = (data.Micros * factor / divisor);
212+
213+
var timestamp = NativeMethods.DateTimeHelpers.DuckDBFromTimestamp(data);
214+
return (additionalTicks, timestamp);
215+
}
204216
}

DuckDB.NET.Data/Internal/Writer/DateTimeVectorDataWriter.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using DuckDB.NET.Data.Extensions;
23
using DuckDB.NET.Native;
34

45
namespace DuckDB.NET.Data.Internal.Writer;
@@ -17,6 +18,8 @@ internal override bool AppendDateTime(DateTime value, ulong rowIndex)
1718
if (ColumnType == DuckDBType.TimestampNs)
1819
{
1920
timestamp.Micros *= 1000;
21+
22+
timestamp.Micros += value.Nanoseconds();
2023
}
2124

2225
if (ColumnType == DuckDBType.TimestampMs)

DuckDB.NET.Test/DuckDBDataReaderTestAllTypes.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public void ReadTimeStampNS()
237237
VerifyDataStruct("timestamp_ns", 17, new List<DateTime>
238238
{
239239
new DateTime(1677, 09, 22),
240-
new DateTime (2262, 04, 11, 23,47,16).AddTicks(854775 * 10)
240+
new DateTime (2262, 04, 11, 23,47,16).AddTicks(8547758)
241241
}, typeof(DuckDBTimestamp));
242242
}
243243

@@ -633,7 +633,7 @@ public void ReadStructOfFixedArray()
633633
reader.GetFieldValue<StructOfArrayTest>(columnIndex).Should().BeEquivalentTo(new StructOfArrayTest()
634634
{
635635
A = new() { null, 2, 3 },
636-
B = new() { "a", null, "c"}
636+
B = new() { "a", null, "c" }
637637
});
638638

639639
reader.Read();

DuckDB.NET.Test/DuckDBManagedAppenderTests.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,27 +247,28 @@ public void TemporalValues()
247247
Command.CommandText = "CREATE TABLE managedAppenderTemporal(a Date, b TimeStamp, c TIMESTAMP_NS, d TIMESTAMP_MS, e TIMESTAMP_S, f TIMESTAMPTZ, g TIMETZ, h Time);";
248248
Command.ExecuteNonQuery();
249249

250-
var dates = Enumerable.Range(0, 20).Select(i => new DateTime(1900, 1, 1).AddDays(Random.Shared.Next(1, 50000)).AddSeconds(Random.Shared.Next(3600 * 2, 3600 * 24))).ToList();
250+
var dates = Enumerable.Range(0, 20).Select(i => new DateTime(1900, 1, 1).AddDays(Random.Shared.Next(1, 50000))
251+
.AddSeconds(Random.Shared.Next(3600 * 2, 3600 * 24))).ToList();
251252

252253
using (var appender = Connection.CreateAppender("managedAppenderTemporal"))
253254
{
254255
foreach (var value in dates)
255256
{
256257
appender.CreateRow()
257258
.AppendValue((DateOnly?)DateOnly.FromDateTime(value))
258-
.AppendValue(value).AppendValue(value)
259+
.AppendValue(value).AppendValue(value.AddTicks(1))
259260
.AppendValue(value).AppendValue(value).AppendValue(value)
260261
.AppendValue(value.ToDateTimeOffset(TimeSpan.FromHours(1)))
261262
.AppendValue((TimeOnly?)TimeOnly.FromDateTime(value))
262263
.EndRow();
263264
}
264265
}
265266

266-
var result = Connection.Query<(DateOnly, DateTime, DateTime, DateTime, DateTime, DateTime, DateTimeOffset, TimeOnly)>("SELECT a, b, c, d, e, f, g, h FROM managedAppenderTemporal").ToList();
267+
var result = Connection.Query<(DateOnly, DateTime, DateTime nanos, DateTime, DateTime, DateTime, DateTimeOffset, TimeOnly)>("SELECT a, b, c, d, e, f, g, h FROM managedAppenderTemporal").ToList();
267268

268269
result.Select(tuple => tuple.Item1).Should().BeEquivalentTo(dates.Select(DateOnly.FromDateTime));
269270
result.Select(tuple => tuple.Item2).Should().BeEquivalentTo(dates);
270-
result.Select(tuple => tuple.Item3).Should().BeEquivalentTo(dates);
271+
result.Select(tuple => tuple.nanos).Should().BeEquivalentTo(dates.Select(time => time.AddTicks(1)));
271272
result.Select(tuple => tuple.Item4).Should().BeEquivalentTo(dates);
272273
result.Select(tuple => tuple.Item5).Should().BeEquivalentTo(dates);
273274
result.Select(tuple => tuple.Item6).Should().BeEquivalentTo(dates);

GitVersion.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ branches:
66
ignore:
77
sha: []
88
merge-message-formats: {}
9+
next-version: 1.1.2

0 commit comments

Comments
 (0)