Skip to content

Commit 6530ea2

Browse files
committed
Refactoring
1 parent c1640f0 commit 6530ea2

File tree

8 files changed

+85
-94
lines changed

8 files changed

+85
-94
lines changed

DuckDB.NET.Data/DuckDBAppenderRow.cs

Lines changed: 16 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public void EndRow()
3131

3232
public DuckDBAppenderRow AppendNullValue() => Append<int>(null); //Doesn't matter what type T we pass to Append when passing null.
3333

34-
public DuckDBAppenderRow AppendValue(bool? value) => Append(value);
34+
public DuckDBAppenderRow AppendValue(bool? value) => AppendValue2(value);
3535

3636
#if NET6_0_OR_GREATER
3737

@@ -40,40 +40,11 @@ public void EndRow()
4040
public DuckDBAppenderRow AppendValue(Span<byte> value) => AppendSpan(value);
4141
#endif
4242

43-
public DuckDBAppenderRow AppendValue(string? value)
44-
{
45-
return AppendHelper(value, (writer, data) => writer.AppendString(data!, rowIndex));
46-
}
43+
public DuckDBAppenderRow AppendValue(string? value) => AppendValue2(value);
4744

48-
public DuckDBAppenderRow AppendValue(decimal? value)
49-
{
50-
return AppendHelper(value, (writer, data) =>
51-
{
52-
if (writer is DecimalVectorDataWriter decimalVectorWriter)
53-
{
54-
decimalVectorWriter.AppendValue(data!.Value, rowIndex);
55-
}
56-
else
57-
{
58-
throw new InvalidOperationException("Cannot write decimal to non-decimal column");
59-
}
60-
});
61-
}
45+
public DuckDBAppenderRow AppendValue(decimal? value) => AppendValue2(value);
6246

63-
public DuckDBAppenderRow AppendValue(Guid? value)
64-
{
65-
return AppendHelper(value, (writer, data) =>
66-
{
67-
if (writer is GuidVectorDataWriter guidVectorDataWriter)
68-
{
69-
guidVectorDataWriter.AppendValue(data!.Value, rowIndex);
70-
}
71-
else
72-
{
73-
throw new InvalidOperationException("Cannot write guid to non-uuid column");
74-
}
75-
});
76-
}
47+
public DuckDBAppenderRow AppendValue(Guid? value) => AppendValue2(value);
7748

7849
public DuckDBAppenderRow AppendValue(BigInteger? value, bool unsigned = false)
7950
{
@@ -141,51 +112,37 @@ public DuckDBAppenderRow AppendValue(BigInteger? value, bool unsigned = false)
141112

142113
public DuckDBAppenderRow AppendValue(TimeSpan? value)
143114
{
144-
return AppendHelper(value, (writer, data) =>
145-
{
146-
if (writer is IntervalVectorDataWriter intervalVectorDataWriter)
147-
{
148-
intervalVectorDataWriter.AppendValue(data!.Value, rowIndex);
149-
}
150-
else
151-
{
152-
throw new InvalidOperationException("Cannot write timespan to non-interval column");
153-
}
154-
});
115+
return AppendValue2(value);
155116
}
156117

157118
#endregion
158119

159-
private DuckDBAppenderRow Append<T>(T? value) where T : unmanaged
120+
private DuckDBAppenderRow AppendValue2<T>(T? value)
160121
{
161122
CheckColumnAccess();
162123

163-
if (value == null)
164-
{
165-
vectorWriters[columnIndex].AppendNull(rowIndex);
166-
}
167-
else
168-
{
169-
vectorWriters[columnIndex].AppendValue(value.Value, rowIndex);
170-
}
124+
vectorWriters[columnIndex].AppendValue(value, rowIndex);
171125

172126
columnIndex++;
173127

174128
return this;
175129
}
176130

177-
private DuckDBAppenderRow AppendHelper<T>(T value, Action<VectorDataWriterBase, T> appendAction)
131+
private DuckDBAppenderRow Append<T>(T? value) where T : unmanaged
178132
{
133+
CheckColumnAccess();
134+
179135
if (value == null)
180136
{
181-
return AppendNullValue();
137+
vectorWriters[columnIndex].AppendNull(rowIndex);
138+
}
139+
else
140+
{
141+
vectorWriters[columnIndex].AppendValueInternal(value.Value, rowIndex);
182142
}
183-
184-
CheckColumnAccess();
185-
186-
appendAction(vectorWriters[columnIndex], value);
187143

188144
columnIndex++;
145+
189146
return this;
190147
}
191148

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace DuckDB.NET.Data.Internal.Writer;
66

7-
internal unsafe class DecimalVectorDataWriter(IntPtr vector, void* vectorData, DuckDBLogicalType logicalType) : VectorDataWriterBase(vector, vectorData)
7+
internal sealed unsafe class DecimalVectorDataWriter(IntPtr vector, void* vectorData, DuckDBLogicalType logicalType, DuckDBType columnType) : VectorDataWriterBase(vector, vectorData, columnType)
88
{
99
private readonly byte scale = NativeMethods.LogicalType.DuckDBDecimalScale(logicalType);
1010
private readonly DuckDBType decimalType = NativeMethods.LogicalType.DuckDBDecimalInternalType(logicalType);
@@ -16,13 +16,13 @@ public void AppendValue(decimal value, ulong rowIndex)
1616
switch (decimalType)
1717
{
1818
case DuckDBType.SmallInt:
19-
AppendValue<short>((short)decimal.Multiply(value, new decimal(power)), rowIndex);
19+
AppendValueInternal<short>((short)decimal.Multiply(value, new decimal(power)), rowIndex);
2020
break;
2121
case DuckDBType.Integer:
22-
AppendValue<int>((int)decimal.Multiply(value, new decimal(power)), rowIndex);
22+
AppendValueInternal<int>((int)decimal.Multiply(value, new decimal(power)), rowIndex);
2323
break;
2424
case DuckDBType.BigInt:
25-
AppendValue<long>((long)decimal.Multiply(value, new decimal(power)), rowIndex);
25+
AppendValueInternal<long>((long)decimal.Multiply(value, new decimal(power)), rowIndex);
2626
break;
2727
case DuckDBType.HugeInt:
2828
var integralPart = decimal.Truncate(value);
@@ -32,7 +32,7 @@ public void AppendValue(decimal value, ulong rowIndex)
3232

3333
result += new BigInteger(decimal.Multiply(fractionalPart, (decimal)power));
3434

35-
AppendValue(new DuckDBHugeInt(result), rowIndex);
35+
AppendValueInternal(new DuckDBHugeInt(result), rowIndex);
3636
break;
3737
}
3838
}

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44

55
namespace DuckDB.NET.Data.Internal.Writer;
66

7-
internal unsafe class GuidVectorDataWriter(IntPtr vector, void* vectorData) : VectorDataWriterBase(vector, vectorData)
7+
internal sealed unsafe class GuidVectorDataWriter(IntPtr vector, void* vectorData, DuckDBType columnType) : VectorDataWriterBase(vector, vectorData, columnType)
88
{
9-
public void AppendValue(Guid value, ulong rowIndex)
10-
{
11-
AppendValue(value.ToHugeInt(), rowIndex);
12-
}
13-
}
9+
internal override bool AppendGuid(Guid value, ulong rowIndex) => AppendValueInternal(value.ToHugeInt(), rowIndex);
10+
}

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44

55
namespace DuckDB.NET.Data.Internal.Writer;
66

7-
internal unsafe class IntervalVectorDataWriter(IntPtr vector, void* vectorData) : VectorDataWriterBase(vector, vectorData)
7+
internal sealed unsafe class IntervalVectorDataWriter(IntPtr vector, void* vectorData, DuckDBType columnType) : VectorDataWriterBase(vector, vectorData, columnType)
88
{
9-
public void AppendValue(TimeSpan value, ulong rowIndex)
10-
{
11-
AppendValue((DuckDBInterval)value, rowIndex);
12-
}
9+
internal override bool AppendTimeSpan(TimeSpan value, ulong rowIndex) => AppendValueInternal((DuckDBInterval)value, rowIndex);
1310
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using DuckDB.NET.Native;
3+
4+
namespace DuckDB.NET.Data.Internal.Writer;
5+
6+
internal sealed unsafe class StringVectorDataWriter(IntPtr vector, void* vectorData, DuckDBType columnType) : VectorDataWriterBase(vector, vectorData, columnType)
7+
{
8+
internal override bool AppendString(string value, ulong rowIndex)
9+
{
10+
using var unmanagedString = value.ToUnmanagedString();
11+
NativeMethods.Vectors.DuckDBVectorAssignStringElement(base.Vector, rowIndex, unmanagedString);
12+
return true;
13+
}
14+
15+
internal override bool AppendBlob(byte* value, int length, ulong rowIndex)
16+
{
17+
NativeMethods.Vectors.DuckDBVectorAssignStringElementLength(Vector, rowIndex, value, length);
18+
return true;
19+
}
20+
}

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

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,52 @@
33

44
namespace DuckDB.NET.Data.Internal.Writer;
55

6-
internal unsafe class VectorDataWriterBase(IntPtr vector, void* vectorData)
6+
internal unsafe class VectorDataWriterBase(IntPtr vector, void* vectorData, DuckDBType columnType)
77
{
88
private unsafe ulong* validity;
9+
internal IntPtr Vector { get; } = vector;
910

1011
public unsafe void AppendNull(ulong rowIndex)
1112
{
1213
if (validity == default)
1314
{
14-
NativeMethods.Vectors.DuckDBVectorEnsureValidityWritable(vector);
15-
validity = NativeMethods.Vectors.DuckDBVectorGetValidity(vector);
15+
NativeMethods.Vectors.DuckDBVectorEnsureValidityWritable(Vector);
16+
validity = NativeMethods.Vectors.DuckDBVectorGetValidity(Vector);
1617
}
1718

1819
NativeMethods.ValidityMask.DuckDBValiditySetRowValidity(validity, rowIndex, false);
1920
}
2021

21-
public unsafe void AppendValue<T>(T value, ulong rowIndex) where T : unmanaged
22+
public unsafe void AppendValue<T>(T value, ulong rowIndex)
2223
{
23-
((T*)vectorData)[rowIndex] = value;
24-
}
24+
if (value == null)
25+
{
26+
AppendNull(rowIndex);
27+
return;
28+
}
2529

26-
public void AppendString(string value, ulong rowIndex)
27-
{
28-
using var unmanagedString = value.ToUnmanagedString();
29-
NativeMethods.Vectors.DuckDBVectorAssignStringElement(vector, rowIndex, unmanagedString);
30+
_ = value switch
31+
{
32+
string val => AppendString(val, rowIndex),
33+
Guid val => AppendGuid(val, rowIndex),
34+
TimeSpan val => AppendTimeSpan(val, rowIndex),
35+
_ => throw new InvalidOperationException($"Cannot write ${typeof(T).Name} to {columnType} column")
36+
};
3037
}
3138

32-
public void AppendBlob(byte* value, int length, ulong rowIndex)
39+
internal virtual bool AppendTimeSpan(TimeSpan value, ulong rowIndex) => throw new InvalidOperationException($"Cannot write timespan to {columnType} column");
40+
41+
internal virtual bool AppendGuid(Guid value, ulong rowIndex) => throw new InvalidOperationException($"Cannot write guid to {columnType} column");
42+
43+
internal virtual bool AppendBlob(byte* value, int length, ulong rowIndex) => throw new InvalidOperationException($"Cannot write blob to {columnType} column");
44+
45+
internal virtual bool AppendString(string value, ulong rowIndex) => throw new InvalidOperationException($"Cannot write string to {columnType} column");
46+
47+
internal virtual bool AppendNumeric<T>(T value, ulong rowIndex) where T : unmanaged => throw new InvalidOperationException($"Cannot write {typeof(T).Name} to {columnType} column");
48+
49+
public unsafe bool AppendValueInternal<T>(T value, ulong rowIndex) where T : unmanaged
3350
{
34-
NativeMethods.Vectors.DuckDBVectorAssignStringElementLength(vector, rowIndex, value, length);
51+
((T*)vectorData)[rowIndex] = value;
52+
return true;
3553
}
3654
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ public static unsafe VectorDataWriterBase CreateWriter(IntPtr vector, void* data
1010
var columnType = NativeMethods.LogicalType.DuckDBGetTypeId(logicalType);
1111
return columnType switch
1212
{
13-
DuckDBType.Uuid => new GuidVectorDataWriter(vector, dataPointer),
14-
DuckDBType.Interval => new IntervalVectorDataWriter(vector, dataPointer),
15-
DuckDBType.Decimal => new DecimalVectorDataWriter(vector, dataPointer, logicalType),
16-
_ => new VectorDataWriterBase(vector, dataPointer)
13+
DuckDBType.Uuid => new GuidVectorDataWriter(vector, dataPointer, columnType),
14+
DuckDBType.Blob => new StringVectorDataWriter(vector, dataPointer, columnType),
15+
DuckDBType.Varchar => new StringVectorDataWriter(vector, dataPointer, columnType),
16+
DuckDBType.Interval => new IntervalVectorDataWriter(vector, dataPointer, columnType),
17+
DuckDBType.Decimal => new DecimalVectorDataWriter(vector, dataPointer, logicalType, columnType),
18+
_ => new VectorDataWriterBase(vector, dataPointer, columnType)
1719
};
1820
}
1921
}

DuckDB.NET.Test/ManagedAppenderTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ public void GuidValues()
198198
Command.CommandText = table;
199199
Command.ExecuteNonQuery();
200200

201-
var guids = Enumerable.Range(0, 20).Select(i => Guid.NewGuid()).ToList();
201+
var guids = Enumerable.Range(0, 20).Select(i => (Guid?)Guid.NewGuid()).ToList();
202+
guids.Add(null);
202203

203204
using (var appender = Connection.CreateAppender("managedAppenderGuids"))
204205
{
@@ -211,8 +212,7 @@ public void GuidValues()
211212
Command.CommandText = "SELECT * FROM managedAppenderGuids";
212213
using (var reader = Command.ExecuteReader())
213214
{
214-
var result = reader.Cast<IDataRecord>().Select(record => record.GetGuid(0)).ToList();
215-
215+
var result = reader.Cast<IDataRecord>().Select(record => record.IsDBNull(0) ? (Guid?)null : record.GetGuid(0)).ToList();
216216
result.Should().BeEquivalentTo(guids);
217217
}
218218
}

0 commit comments

Comments
 (0)