Skip to content

Commit

Permalink
Merge branch 'develop' into nightly-builds
Browse files Browse the repository at this point in the history
  • Loading branch information
Giorgi committed Nov 29, 2024
2 parents 466c564 + b13117d commit 261886d
Show file tree
Hide file tree
Showing 14 changed files with 279 additions and 93 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/NuGet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
steps:

- name: Download Artifacts
uses: dawidd6/action-download-artifact@v3
uses: dawidd6/action-download-artifact@v6
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: ci.yml
Expand Down
13 changes: 13 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,17 @@
<PackagePath></PackagePath>
</None>
</ItemGroup>

<PropertyGroup Label="CI" Condition="'$(CI)' == ''">
<CI>false</CI>
<!-- GH, CircleCI, GitLab and BitBucket already use CI -->
<CI Condition="'$(TF_BUILD)' == 'true' or
'$(TEAMCITY_VERSION)' != '' or
'$(APPVEYOR)' != '' or
'$(BuildRunner)' == 'MyGet' or
'$(JENKINS_URL)' != '' or
'$(TRAVIS)' == 'true' or
'$(BUDDY)' == 'true' or
'$(CODEBUILD_CI)' == 'true'">true</CI>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion DuckDB.NET.Bindings/Bindings.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Updated to DuckDB v1.1.3
<Link>runtimes\%(RecursiveDir)\%(FileName)%(Extension)</Link>
</None>
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(CI)' == 'true'">
<PackageReference Include="GitVersion.MsBuild" Version="5.11.1" PrivateAssets="all" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
Expand Down
11 changes: 4 additions & 7 deletions DuckDB.NET.Bindings/DuckDBWrapperObjects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,15 @@ public T GetValue<T>()
DuckDBType.Decimal => Cast(decimal.Parse(NativeMethods.Value.DuckDBGetVarchar(this))),
DuckDBType.Uuid => Cast(new Guid(NativeMethods.Value.DuckDBGetVarchar(this))),

//DuckDBType.HugeInt => expr,
//DuckDBType.UnsignedHugeInt => expr,
DuckDBType.HugeInt => Cast(NativeMethods.Value.DuckDBGetHugeInt(this).ToBigInteger()),
DuckDBType.UnsignedHugeInt => Cast(NativeMethods.Value.DuckDBGetUHugeInt(this).ToBigInteger()),

DuckDBType.Varchar => Cast(NativeMethods.Value.DuckDBGetVarchar(this)),

//DuckDBType.Date => expr,
//DuckDBType.Time => expr,
//DuckDBType.TimeTz => expr,
//DuckDBType.Interval => expr,
DuckDBType.Interval => Cast((TimeSpan)NativeMethods.Value.DuckDBGetInterval(this)),
DuckDBType.Timestamp => Cast(NativeMethods.DateTimeHelpers.DuckDBFromTimestamp(NativeMethods.Value.DuckDBGetTimestamp(this)).ToDateTime()),
//DuckDBType.TimestampS => expr,
//DuckDBType.TimestampMs => expr,
Expand All @@ -160,9 +160,6 @@ public T GetValue<T>()
_ => throw new NotImplementedException($"Cannot read value of type {typeof(T).FullName}")
};

T Cast<TSource>(TSource value)
{
return Unsafe.As<TSource, T>(ref value);
}
T Cast<TSource>(TSource value) => Unsafe.As<TSource, T>(ref value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ public static class TableFunction
[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_bind_set_bind_data")]
public static extern unsafe void DuckDBBindSetBindData(IntPtr info, IntPtr bindData, delegate* unmanaged[Cdecl]<IntPtr, void> destroy);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_bind_set_error")]
public static extern unsafe void DuckDBBindSetError(IntPtr info, SafeUnmanagedMemoryHandle error);

#endregion

#region TableFunction
Expand All @@ -61,6 +64,9 @@ public static class TableFunction
[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_function_get_bind_data")]
public static extern unsafe IntPtr DuckDBFunctionGetBindData(IntPtr info);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_function_set_error")]
public static extern unsafe void DuckDBFunctionSetError(IntPtr info, SafeUnmanagedMemoryHandle error);

#endregion
}
}
12 changes: 6 additions & 6 deletions DuckDB.NET.Bindings/NativeMethods/NativeMethods.Value.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,22 @@ public static class Value
public static extern double DuckDBGetDouble(DuckDBValue value);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_get_date")]
public static extern unsafe DuckDBDate DuckDBGetDate(DuckDBValue value);
public static extern DuckDBDate DuckDBGetDate(DuckDBValue value);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_get_time")]
public static extern unsafe DuckDBTime DuckDBGetTime(DuckDBValue value);
public static extern DuckDBTime DuckDBGetTime(DuckDBValue value);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_get_time_tz")]
public static extern unsafe DuckDBTimeTzStruct DuckDBGetTimeTz(DuckDBValue value);
public static extern DuckDBTimeTzStruct DuckDBGetTimeTz(DuckDBValue value);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_get_timestamp")]
public static extern unsafe DuckDBTimestampStruct DuckDBGetTimestamp(DuckDBValue value);
public static extern DuckDBTimestampStruct DuckDBGetTimestamp(DuckDBValue value);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_get_interval")]
public static extern unsafe DuckDBInterval DuckDBGetInterval(DuckDBValue value);
public static extern DuckDBInterval DuckDBGetInterval(DuckDBValue value);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_get_value_type")]
public static extern unsafe DuckDBLogicalType DuckDBGetValueType(DuckDBValue value);
public static extern DuckDBLogicalType DuckDBGetValueType(DuckDBValue value);

[DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_get_varchar")]
public static extern string DuckDBGetVarchar(DuckDBValue value);
Expand Down
2 changes: 1 addition & 1 deletion DuckDB.NET.Data/Data.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Updated to DuckDB v1.1.3
<Description>$(Description) $(NoNativeText)</Description>
</PropertyGroup>

<ItemGroup>
<ItemGroup Condition="'$(CI)' == 'true'">
<PackageReference Include="GitVersion.MsBuild" Version="5.11.1" PrivateAssets="all" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
Expand Down
14 changes: 4 additions & 10 deletions DuckDB.NET.Data/DuckDBAppender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ public void Close()
writer?.Dispose();
}

dataChunk.Dispose();

var state = NativeMethods.Appender.DuckDBAppenderClose(nativeAppender);
if (!state.IsSuccess())
{
ThrowLastError(nativeAppender);
}

dataChunk.Dispose();
}
finally
{
Expand All @@ -105,14 +105,8 @@ private void InitVectorWriters()
{
var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, index);

if (vectorWriters[index] == null)
{
vectorWriters[index] = VectorDataWriterFactory.CreateWriter(vector, logicalTypes[index]);
}
else
{
vectorWriters[index].InitializerWriter();
}
vectorWriters[index]?.Dispose();
vectorWriters[index] = VectorDataWriterFactory.CreateWriter(vector, logicalTypes[index]);
}
}

Expand Down
123 changes: 71 additions & 52 deletions DuckDB.NET.Data/DuckDBConnection.TableFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,37 +102,48 @@ private unsafe void RegisterTableFunctionInternal(string name, Func<IReadOnlyLis
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
public static unsafe void Bind(IntPtr info)
{
var handle = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBBindGetExtraInfo(info));

if (handle.Target is not TableFunctionInfo functionInfo)
IDuckDBValueReader[] parameters = [];
try
{
throw new InvalidOperationException("User defined table function bind failed. Bind extra info is null");
}
var handle = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBBindGetExtraInfo(info));

var parameters = new IDuckDBValueReader[NativeMethods.TableFunction.DuckDBBindGetParameterCount(info)];
if (handle.Target is not TableFunctionInfo functionInfo)
{
throw new InvalidOperationException("User defined table function bind failed. Bind extra info is null");
}

for (var i = 0; i < parameters.Length; i++)
{
var value = NativeMethods.TableFunction.DuckDBBindGetParameter(info, (ulong)i);
parameters[i] = value;
}
parameters = new IDuckDBValueReader[NativeMethods.TableFunction.DuckDBBindGetParameterCount(info)];

for (var i = 0; i < parameters.Length; i++)
{
var value = NativeMethods.TableFunction.DuckDBBindGetParameter(info, (ulong)i);
parameters[i] = value;
}

var tableFunctionData = functionInfo.Bind(parameters);

var tableFunctionData = functionInfo.Bind(parameters);
foreach (var columnInfo in tableFunctionData.Columns)
{
using var logicalType = DuckDBTypeMap.GetLogicalType(columnInfo.Type);
NativeMethods.TableFunction.DuckDBBindAddResultColumn(info, columnInfo.Name.ToUnmanagedString(), logicalType);
}

var bindData = new TableFunctionBindData(tableFunctionData.Columns, tableFunctionData.Data.GetEnumerator());

foreach (var parameter in parameters)
NativeMethods.TableFunction.DuckDBBindSetBindData(info, bindData.ToHandle(), &DestroyExtraInfo);
}
catch (Exception ex)
{
((DuckDBValue)parameter).Dispose();
using var errorMessage = ex.Message.ToUnmanagedString();
NativeMethods.TableFunction.DuckDBBindSetError(info, errorMessage);
}

foreach (var columnInfo in tableFunctionData.Columns)
finally
{
using var logicalType = DuckDBTypeMap.GetLogicalType(columnInfo.Type);
NativeMethods.TableFunction.DuckDBBindAddResultColumn(info, columnInfo.Name.ToUnmanagedString(), logicalType);
foreach (var parameter in parameters)
{
(parameter as IDisposable)?.Dispose();
}
}

var bindData = new TableFunctionBindData(tableFunctionData.Columns, tableFunctionData.Data.GetEnumerator());

NativeMethods.TableFunction.DuckDBBindSetBindData(info, bindData.ToHandle(), &DestroyExtraInfo);
}

[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
Expand All @@ -141,46 +152,54 @@ public static void Init(IntPtr info) { }
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
public static void TableFunction(IntPtr info, IntPtr chunk)
{
var bindData = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetBindData(info));
var extraInfo = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetExtraInfo(info));

if (bindData.Target is not TableFunctionBindData tableFunctionBindData)
try
{
throw new InvalidOperationException("User defined table function failed. Function bind data is null");
}

if (extraInfo.Target is not TableFunctionInfo tableFunctionInfo)
{
throw new InvalidOperationException("User defined table function failed. Function extra info is null");
}

var dataChunk = new DuckDBDataChunk(chunk);
var bindData = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetBindData(info));
var extraInfo = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetExtraInfo(info));

var writers = new VectorDataWriterBase[tableFunctionBindData.Columns.Count];
for (var columnIndex = 0; columnIndex < tableFunctionBindData.Columns.Count; columnIndex++)
{
var column = tableFunctionBindData.Columns[columnIndex];
var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, columnIndex);
if (bindData.Target is not TableFunctionBindData tableFunctionBindData)
{
throw new InvalidOperationException("User defined table function failed. Function bind data is null");
}

using var logicalType = DuckDBTypeMap.GetLogicalType(column.Type);
writers[columnIndex] = VectorDataWriterFactory.CreateWriter(vector, logicalType);
}
if (extraInfo.Target is not TableFunctionInfo tableFunctionInfo)
{
throw new InvalidOperationException("User defined table function failed. Function extra info is null");
}

ulong size = 0;
var dataChunk = new DuckDBDataChunk(chunk);

for (; size < DuckDBGlobalData.VectorSize; size++)
{
if (tableFunctionBindData.DataEnumerator.MoveNext())
var writers = new VectorDataWriterBase[tableFunctionBindData.Columns.Count];
for (var columnIndex = 0; columnIndex < tableFunctionBindData.Columns.Count; columnIndex++)
{
tableFunctionInfo.Mapper(tableFunctionBindData.DataEnumerator.Current, writers, size);
var column = tableFunctionBindData.Columns[columnIndex];
var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, columnIndex);

using var logicalType = DuckDBTypeMap.GetLogicalType(column.Type);
writers[columnIndex] = VectorDataWriterFactory.CreateWriter(vector, logicalType);
}
else

ulong size = 0;

for (; size < DuckDBGlobalData.VectorSize; size++)
{
break;
if (tableFunctionBindData.DataEnumerator.MoveNext())
{
tableFunctionInfo.Mapper(tableFunctionBindData.DataEnumerator.Current, writers, size);
}
else
{
break;
}
}
}

NativeMethods.DataChunks.DuckDBDataChunkSetSize(dataChunk, size);
NativeMethods.DataChunks.DuckDBDataChunkSetSize(dataChunk, size);
}
catch (Exception ex)
{
using var errorMessage = ex.Message.ToUnmanagedString();
NativeMethods.TableFunction.DuckDBFunctionSetError(info, errorMessage);
}
}
#endif
}
28 changes: 19 additions & 9 deletions DuckDB.NET.Data/DuckDBDataReader.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System;
using DuckDB.NET.Data.Internal.Reader;
using DuckDB.NET.Native;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using DuckDB.NET.Data.Internal.Reader;
using DuckDB.NET.Native;

namespace DuckDB.NET.Data;

Expand All @@ -29,6 +29,7 @@ public class DuckDBDataReader : DbDataReader

private readonly IEnumerator<DuckDBResult> resultEnumerator;
private VectorDataReaderBase[] vectorReaders = [];
private Dictionary<string, int> columnMapping = [];

internal DuckDBDataReader(DuckDBCommand command, IEnumerable<DuckDBResult> queryResults, CommandBehavior behavior)
{
Expand All @@ -48,6 +49,7 @@ private bool InitNextReader()
currentChunkIndex = 0;
currentResult = resultEnumerator.Current;

columnMapping = [];
fieldCount = (int)NativeMethods.Query.DuckDBColumnCount(ref currentResult);
streamingResult = NativeMethods.Types.DuckDBResultIsStreaming(currentResult) > 0;

Expand Down Expand Up @@ -80,7 +82,7 @@ private bool InitChunkData()
{
vectorReaders = new VectorDataReaderBase[fieldCount];
}

for (int index = 0; index < fieldCount; index++)
{
var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(currentChunk, index);
Expand All @@ -91,6 +93,17 @@ private bool InitChunkData()
NativeMethods.Query.DuckDBColumnName(ref currentResult, index).ToManagedString(false));
}

if (columnMapping.Count == 0)
{
for (var i = 0; i < vectorReaders.Length; i++)
{
if (!columnMapping.ContainsKey(vectorReaders[i].ColumnName))
{
columnMapping.Add(vectorReaders[i].ColumnName, i);
}
}
}

return currentChunkRowCount > 0;
}
}
Expand Down Expand Up @@ -182,12 +195,9 @@ public override string GetName(int ordinal)

public override int GetOrdinal(string name)
{
for (var i = 0; i < fieldCount; i++)
if (columnMapping.TryGetValue(name, out var index))
{
if (GetName(i) == name)
{
return i;
}
return index;
}

throw new DuckDBException($"Column with name {name} was not found.");
Expand Down
2 changes: 1 addition & 1 deletion DuckDB.NET.Data/Internal/DuckDBTypeMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ internal static class DuckDBTypeMap
{ typeof(DateOnly), DuckDBType.Date},
{ typeof(TimeOnly), DuckDBType.Time},
#endif
{ typeof(DateTimeOffset), DuckDBType.TimeTz},
{ typeof(DateTimeOffset), DuckDBType.TimestampTz},
{ typeof(BigInteger), DuckDBType.HugeInt},
{ typeof(string), DuckDBType.Varchar},
{ typeof(decimal), DuckDBType.Decimal},
Expand Down
Loading

0 comments on commit 261886d

Please sign in to comment.