Skip to content

Commit

Permalink
Add more overloads to set query data buffers without type validation. (
Browse files Browse the repository at this point in the history
…#295)

* Throw if the buffer is empty in the most advanced overload of `Query.UnsafeSetDataBuffer`.

All buffer setters are documented to throw, but this one does not.

* Add APIs to set query data buffers to a raw byte buffer.

The existing APIs were memory-unsafe.

* Test the new method and that `UnsafeSetDataBuffer` throws on an empty buffer.

* Test that `UnsafeSetDataReadOnlyBuffer` throws when given an empty buffer.
  • Loading branch information
teo-tsirpanis authored Oct 18, 2023
1 parent e645f63 commit 1ef668b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
47 changes: 45 additions & 2 deletions sources/TileDB.CSharp/Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,24 @@ public void UnsafeSetDataBuffer(string name, void* data, ulong byteSize)
ThrowHelpers.ThrowBufferCannotBeEmpty(nameof(byteSize));
}

UnsafeSetDataBuffer(name, new MemoryHandle(data), byteSize);
UnsafeSetDataBuffer(name, new MemoryHandle(data), byteSize, 0);
}

/// <summary>
/// Sets the data buffer for an attribute or dimension to a
/// byte buffer without performing type validation.
/// </summary>
/// <param name="name">The name of the attribute or the dimension.</param>
/// <param name="data">A <see cref="Memory{T}"/> of bytes pointing to the buffer.</param>
/// <exception cref="ArgumentException"><paramref name="data"/> is empty.</exception>
public void UnsafeSetDataBuffer(string name, Memory<byte> data)
{
if (data.IsEmpty)
{
ThrowHelpers.ThrowBufferCannotBeEmpty(nameof(data));
}

UnsafeSetDataBuffer(name, data.Pin(), (ulong)data.Length, 0);
}

/// <summary>
Expand All @@ -390,8 +407,15 @@ public void UnsafeSetDataBuffer(string name, void* data, ulong byteSize)
/// <item>This method call throws an exception.</item>
/// </list></para>
/// </remarks>
public void UnsafeSetDataBuffer(string name, MemoryHandle memoryHandle, ulong byteSize) =>
public void UnsafeSetDataBuffer(string name, MemoryHandle memoryHandle, ulong byteSize)
{
if (byteSize == 0)
{
ThrowHelpers.ThrowBufferCannotBeEmpty(nameof(byteSize));
}

UnsafeSetDataBuffer(name, memoryHandle, byteSize, 0);
}

private void UnsafeSetDataBuffer(string name, MemoryHandle memoryHandle, ulong byteSize, int elementSize)
{
Expand All @@ -416,6 +440,25 @@ private void UnsafeSetDataBuffer(string name, MemoryHandle memoryHandle, ulong b
}
}

/// <summary>
/// Sets the data buffer for an attribute or dimension to a
/// read-only byte buffer without performing type validation.
/// Not supported for <see cref="QueryType.Read"/> queries.
/// </summary>
/// <param name="name">The name of the attribute or the dimension.</param>
/// <param name="data">A <see cref="ReadOnlyMemory{T}"/> of bytes pointing to the buffer.</param>
/// <exception cref="ArgumentException"><paramref name="data"/> is empty.</exception>
/// <exception cref="NotSupportedException">The query's type is <see cref="QueryType.Read"/></exception>
public void UnsafeSetDataReadOnlyBuffer(string name, ReadOnlyMemory<byte> data)
{
if (QueryType() == CSharp.QueryType.Read)
{
ThrowHelpers.ThrowOperationNotAllowedOnReadQueries();
}

UnsafeSetDataBuffer(name, MemoryMarshal.AsMemory(data));
}

private void SetDataBufferCore(string name, void* data, ulong* size)
{
using var ctxHandle = _ctx.Handle.Acquire();
Expand Down
4 changes: 3 additions & 1 deletion tests/TileDB.CSharp.Test/QueryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ public unsafe void TestNullableAttributeArrayQuery()

query_write.SetDataBuffer("a1", a1_data_ptr, (ulong)a1_data.Length);
query_write.SetValidityBuffer("a1", a1_validity);
Assert.ThrowsException<ArgumentException>(() => query_write.UnsafeSetDataReadOnlyBuffer("a1", ReadOnlyMemory<byte>.Empty));

query_write.UnsafeSetDataBuffer("a2", (void*)a2_data_ptr, (ulong)a2_data.Length * sizeof(int));
query_write.SetOffsetsBuffer("a2", a2_off_ptr, (ulong)a2_off.Length);
Expand Down Expand Up @@ -509,7 +510,8 @@ public unsafe void TestNullableAttributeArrayQuery()
query_read.SetOffsetsBuffer("a2", a2_off_read);
query_read.SetValidityBuffer("a2", a2_validity_read);

query_read.UnsafeSetDataBuffer("a3", a3_data_read.AsMemory().Pin(), (ulong)a3_data_read.Length * sizeof(byte));
query_read.UnsafeSetDataBuffer("a3", a3_data_read.AsMemory());
Assert.ThrowsException<ArgumentException>(() => query_read.UnsafeSetDataBuffer("a3", default(MemoryHandle), 0));
query_read.SetOffsetsBuffer("a3", a3_off_read);
query_read.SetValidityBuffer("a3", a3_validity_read);

Expand Down

0 comments on commit 1ef668b

Please sign in to comment.