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

Support AOT read, add AOT test console, support net8.0 #202

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
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
6 changes: 5 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>

<PropertyGroup Label="Common assembly attributes">
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<LangVersion>default</LangVersion>

Expand Down Expand Up @@ -37,6 +37,10 @@
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

</PropertyGroup>

<PropertyGroup Condition="'$(PublishAot)'!=''">
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
<BuildType>ManagedOnly</BuildType>
Expand Down
41 changes: 41 additions & 0 deletions DuckDB.NET.AOT/AOT.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\DuckDB.NET.Bindings\Bindings.csproj" />
<ProjectReference Include="..\DuckDB.NET.Data\Data.csproj" />
</ItemGroup>

<Target Name="CallExecutable" BeforeTargets="GenerateAdditionalSources">
<MSBuild Projects="..\DuckDB.NET.Bindings\Bindings.csproj" Targets="DownloadNativeLibs" Properties="BuildType=Full;" />
</Target>
<ItemGroup>
<None Condition="'$(RuntimeIdentifier)'=='win-x64'" Include="..\DuckDB.NET.Bindings\obj\runtimes\**\*.dll">
<Visible>false</Visible>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<PackagePath>\</PackagePath>
<Link>%(FileName)%(Extension)</Link>
</None>
<None Condition="'$(RuntimeIdentifier)'=='linux-x64'" Include="..\DuckDB.NET.Bindings\obj\runtimes\**\*.so">
<Visible>false</Visible>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<PackagePath>\</PackagePath>
<Link>%(FileName)%(Extension)</Link>
</None>
<None Condition="'$(RuntimeIdentifier)'=='oxs'" Include="..\DuckDB.NET.Bindings\obj\runtimes\**\*.dylib">
<Visible>false</Visible>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<PackagePath>\</PackagePath>
<Link>%(FileName)%(Extension)</Link>
</None>
</ItemGroup>

</Project>
54 changes: 54 additions & 0 deletions DuckDB.NET.AOT/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using DuckDB.NET.Data;

namespace DuckDB.NET.AOT
{
internal class Program
{
static void Main(string[] args)
{
using var conn = new DuckDBConnection(DuckDBConnectionStringBuilder.InMemoryConnectionString);
conn.Open();
using (var comm = conn.CreateCommand())
{
comm.CommandText = "SELECT 1";
comm.ExecuteNonQuery();

comm.CommandText = "SELECT 1";
using (var reader = comm.ExecuteReader())
{
while (reader.Read())
{
_ = reader.GetInt32(0);
}
}

comm.CommandText = "SELECT [1,2,3]";
using (var reader = comm.ExecuteReader())
{
while (reader.Read())
{
Console.Write("[");
foreach (var item in (List<int>)reader[0])
{
Console.Write(item+",");
}
Console.WriteLine("]");
}
}
comm.CommandText = "select {\"a\":1,\"b\":2};";
using (var reader = comm.ExecuteReader())
{
while (reader.Read())
{
Console.Write("{");
foreach (var item in (Dictionary<string,object>)reader[0])
{
Console.Write($"{item.Key}={item.Value}, ");
}
Console.WriteLine("}");
}
}
}
}
}
}
6 changes: 3 additions & 3 deletions DuckDB.NET.Bindings/Bindings.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Description>DuckDB Bindings for C#.</Description>
<PackageReleaseNotes>Update to DuckDB 0.10.3.</PackageReleaseNotes>
<RootNamespace>DuckDB.NET.Native</RootNamespace>
<RuntimeIdentifiers>win-x64;linux-x64;linux-arm64;osx</RuntimeIdentifiers>
<RuntimeIdentifiers>win-x64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
<DuckDbArtifactRoot Condition=" '$(DuckDbArtifactRoot)' == '' ">https://github.com/duckdb/duckdb/releases/download/v0.10.3</DuckDbArtifactRoot>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\keyPair.snk</AssemblyOriginatorKeyFile>
Expand All @@ -15,13 +15,13 @@
<PropertyGroup Condition="'$(BuildType)' == 'ManagedOnly' ">
<Description>$(Description) $(NoNativeText)</Description>
</PropertyGroup>
<!-- Download and include the native libraries into the nuget package-->
<Target Name="DownloadNativeLibs" BeforeTargets="GenerateAdditionalSources" Condition="'$(BuildType)' == 'Full' ">
<MSBuild Projects="DownloadNativeLibs.targets" Properties="Rid=win-x64;LibUrl=$(DuckDbArtifactRoot)/libduckdb-windows-amd64.zip" />
<MSBuild Projects="DownloadNativeLibs.targets" Properties="Rid=linux-x64;LibUrl=$(DuckDbArtifactRoot)/libduckdb-linux-amd64.zip" />
<MSBuild Condition=" '$(SkipLinuxArm)' == '' " Projects="DownloadNativeLibs.targets" Properties="Rid=linux-arm64;LibUrl=$(DuckDbArtifactRoot)/libduckdb-linux-aarch64.zip" />
<MSBuild Projects="DownloadNativeLibs.targets" Properties="Rid=osx;LibUrl=$(DuckDbArtifactRoot)/libduckdb-osx-universal.zip" />
<MSBuild Projects="DownloadNativeLibs.targets" Properties="Rid=osx-x64;LibUrl=$(DuckDbArtifactRoot)/libduckdb-osx-universal.zip" />
</Target>
<Target Name="CleanNativeLibs" BeforeTargets="Clean" Condition="'$(BuildType)' == 'Full' ">
<RemoveDir Directories="obj\runtimes" />
Expand Down
4 changes: 3 additions & 1 deletion DuckDB.NET.Data/DuckDBException.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Data.Common;
using System;
using System.Data.Common;
using System.Runtime.Serialization;
using DuckDB.NET.Native;

Expand All @@ -10,6 +11,7 @@ internal DuckDBException()
{
}

[Obsolete]
internal DuckDBException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
Expand Down
18 changes: 18 additions & 0 deletions DuckDB.NET.Data/Internal/Reader/CreatorCache.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;

namespace DuckDB.NET.Data.Internal.Reader;

internal static class CreatorCache
{
private static readonly ConcurrentDictionary<Type, Func<object>> creators=new ConcurrentDictionary<Type, Func<object>>();

public static Func<object> GetCreator(Type type)
{
return creators.GetOrAdd(type, static t =>
{
return Expression.Lambda<Func<object>>(Expression.Convert(Expression.New(t), typeof(object))).Compile();
});
}
}
18 changes: 13 additions & 5 deletions DuckDB.NET.Data/Internal/Reader/ListVectorDataReader.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System;
using DuckDB.NET.Data.Extensions;
using DuckDB.NET.Native;
using System;
using System.Collections;
using System.Collections.Generic;
using DuckDB.NET.Data.Extensions;
using DuckDB.NET.Native;
#if NET8_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif

namespace DuckDB.NET.Data.Internal.Reader;

Expand All @@ -23,12 +26,17 @@ internal unsafe ListVectorDataReader(IntPtr vector, void* dataPointer, ulong* va
arraySize = IsList ? 0 : (ulong)NativeMethods.LogicalType.DuckDBArrayVectorGetSize(logicalType);
listDataReader = VectorDataReaderFactory.CreateReader(childVector, childType, columnName);
}

#if NET8_0_OR_GREATER
[return:DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
#endif
protected override Type GetColumnType()
{
return typeof(List<>).MakeGenericType(listDataReader.ClrType);
}

#if NET8_0_OR_GREATER
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
#endif
protected override Type GetColumnProviderSpecificType()
{
return typeof(List<>).MakeGenericType(listDataReader.ProviderSpecificClrType);
Expand Down Expand Up @@ -57,7 +65,7 @@ private unsafe object GetList(Type returnType, ulong listOffset, ulong length)

var allowNulls = listType.AllowsNullValue(out var _, out var nullableType);

var list = Activator.CreateInstance(returnType) as IList
var list = CreatorCache.GetCreator(returnType)() as IList
?? throw new ArgumentException($"The type '{returnType.Name}' specified in parameter {nameof(returnType)} cannot be instantiated as an IList.");

//Special case for specific types to avoid boxing
Expand Down
46 changes: 30 additions & 16 deletions DuckDB.NET.Data/Internal/Reader/StructVectorDataReader.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using DuckDB.NET.Data.Extensions;
using DuckDB.NET.Native;
Expand Down Expand Up @@ -37,23 +38,13 @@ internal override object GetValue(ulong offset, Type targetType)

return base.GetValue(offset, targetType);
}

private object GetStruct(ulong offset, Type returnType)
internal static TypeDetails GetTypeDetails(
#if NET8_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
#endif
Type returnType)
{
var result = Activator.CreateInstance(returnType);

if (result is Dictionary<string, object?> dictionary)
{
foreach (var reader in structDataReaders)
{
var value = reader.Value.IsValid(offset) ? reader.Value.GetValue(offset) : null;
dictionary.Add(reader.Key, value);
}

return result;
}

var typeDetails = TypeCache.GetOrAdd(returnType, type =>
return TypeCache.GetOrAdd(returnType, type =>
{
var propertyInfos = returnType.GetProperties();
var details = new TypeDetails();
Expand All @@ -80,6 +71,29 @@ private object GetStruct(ulong offset, Type returnType)

return details;
});
}
private object GetStruct(ulong offset,
#if NET8_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
#endif
Type returnType)
{
if (returnType.IsEquivalentTo(typeof(Dictionary<string, object?>)))
{
var dictionary = new Dictionary<string, object?>();

foreach (var reader in structDataReaders)
{
var value = reader.Value.IsValid(offset) ? reader.Value.GetValue(offset) : null;
dictionary.Add(reader.Key, value);
}

return dictionary;
}

var typeDetails = GetTypeDetails(returnType);

var result = CreatorCache.GetCreator(returnType)();

foreach (var property in typeDetails.Properties)
{
Expand Down
6 changes: 6 additions & 0 deletions DuckDB.NET.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Data", "DuckDB.NET.Data\Dat
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "DuckDB.NET.Test\Test.csproj", "{56C63520-26F9-4230-9AD1-04457E5EBF57}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOT", "DuckDB.NET.AOT\AOT.csproj", "{29DB9656-5E17-4F49-944C-EDC5FF8F9312}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -33,6 +35,10 @@ Global
{56C63520-26F9-4230-9AD1-04457E5EBF57}.Debug|Any CPU.Build.0 = Debug|Any CPU
{56C63520-26F9-4230-9AD1-04457E5EBF57}.Release|Any CPU.ActiveCfg = Release|Any CPU
{56C63520-26F9-4230-9AD1-04457E5EBF57}.Release|Any CPU.Build.0 = Release|Any CPU
{29DB9656-5E17-4F49-944C-EDC5FF8F9312}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29DB9656-5E17-4F49-944C-EDC5FF8F9312}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29DB9656-5E17-4F49-944C-EDC5FF8F9312}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29DB9656-5E17-4F49-944C-EDC5FF8F9312}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Loading