From d181f451bd14d70a58dd2292f24dc86db9cad0bb Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Wed, 8 Mar 2023 18:32:57 +0200 Subject: [PATCH 1/8] Add dimension label APIs on `ArraySchema`. --- sources/TileDB.CSharp/ArraySchema.cs | 67 ++++++++++++++++++++++++++++ sources/TileDB.CSharp/DataOrder.cs | 23 ++++++++++ 2 files changed, 90 insertions(+) create mode 100644 sources/TileDB.CSharp/DataOrder.cs diff --git a/sources/TileDB.CSharp/ArraySchema.cs b/sources/TileDB.CSharp/ArraySchema.cs index 376d9a60..a08136fc 100644 --- a/sources/TileDB.CSharp/ArraySchema.cs +++ b/sources/TileDB.CSharp/ArraySchema.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using TileDB.CSharp.Marshalling.SafeHandles; using TileDB.Interop; using ArraySchemaHandle = TileDB.CSharp.Marshalling.SafeHandles.ArraySchemaHandle; @@ -69,6 +70,44 @@ public void AddAttributes(params Attribute[] attrs) } } + /// + /// Adds a dimension label to the . + /// + /// The dimension's index. + /// The dimension label's name. + /// The data order of the dimension label. + /// The dimension lable's data type. + public void AddDimensionLabel(uint dimensionIndex, string name, DataOrder labelOrder, DataType labelType) + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_name = new MarshaledString(name); + _ctx.handle_error(Methods.tiledb_array_schema_add_dimension_label(ctxHandle, handle, dimensionIndex, ms_name, (tiledb_data_order_t)labelOrder, (tiledb_datatype_t)labelType)); + } + + /// + /// Adds a dimension label to the , that has a specified tile extent. + /// + /// The dimension's index. + /// The dimension label's name. + /// The data order of the dimension label. + /// The dimension lable's data type. + /// The dimension label's tile extent. + /// and do not match. + public void AddDimensionLabel(uint dimensionIndex, string name, DataOrder labelOrder, DataType labelType, T extent) where T : struct + { + if (RuntimeHelpers.IsReferenceOrContainsReferences() || typeof(T) != EnumUtil.DataTypeToType(labelType)) + { + ThrowHelpers.ThrowTypeMismatch(labelType); + } + + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_name = new MarshaledString(name); + _ctx.handle_error(Methods.tiledb_array_schema_add_dimension_label(ctxHandle, handle, dimensionIndex, ms_name, (tiledb_data_order_t)labelOrder, (tiledb_datatype_t)labelType)); + _ctx.handle_error(Methods.tiledb_array_schema_set_dimension_label_tile_extent(ctxHandle, handle, ms_name, (tiledb_datatype_t)labelType, &extent)); + } + /// /// Sets whether cells with duplicate coordinates are allowed in the . /// @@ -133,6 +172,20 @@ public void SetCellOrder(LayoutType layoutType) _ctx.handle_error(Methods.tiledb_array_schema_set_cell_order(ctxHandle, handle, tiledb_layout)); } + /// + /// Sets the of filters that will be applied in one of the 's dimension labels. + /// + /// The dimension label's name. + /// The dimension label's filter list. + public void SetDimensionLabelFilterList(string name, FilterList filterList) + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_name = new MarshaledString(name); + using var filterListHandle = filterList.Handle.Acquire(); + _ctx.handle_error(Methods.tiledb_array_schema_set_dimension_label_filter_list(ctxHandle, handle, ms_name, filterListHandle)); + } + /// /// Sets the 's tile order. /// @@ -479,6 +532,20 @@ public bool HasAttribute(string name) return has_attr > 0; } + /// + /// Checks if a dimension label with the given name exists in the or not. + /// + /// The name to check. + public bool HasDimensionLabel(string name) + { + int has_attr; + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_name = new MarshaledString(name); + _ctx.handle_error(Methods.tiledb_array_schema_has_dimension_label(ctxHandle, handle, ms_name, &has_attr)); + return has_attr > 0; + } + /// /// Load an from a URI. /// diff --git a/sources/TileDB.CSharp/DataOrder.cs b/sources/TileDB.CSharp/DataOrder.cs new file mode 100644 index 00000000..f1b444f6 --- /dev/null +++ b/sources/TileDB.CSharp/DataOrder.cs @@ -0,0 +1,23 @@ +using TileDB.Interop; + +namespace TileDB.CSharp +{ + /// + /// Specifies the order of data in dimension labels. + /// + public enum DataOrder + { + /// + /// Data are not ordered. + /// + Unordered = tiledb_data_order_t.TILEDB_UNORDERED_DATA, + /// + /// Data are stored in increasing order. + /// + Increasing = tiledb_data_order_t.TILEDB_INCREASING_DATA, + /// + /// Data are stored in decreasing order. + /// + Decreasing = tiledb_data_order_t.TILEDB_DECREASING_DATA + } +} From f1808dbafa2dbee9b7b39cc12dcd2a1752a908e2 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Thu, 9 Mar 2023 13:22:07 +0200 Subject: [PATCH 2/8] Add a `DimensionLabel` type. --- sources/TileDB.CSharp/ArraySchema.cs | 34 +++++ sources/TileDB.CSharp/DimensionLabel.cs | 134 ++++++++++++++++++ .../SafeHandles/DimensionLabelHandle.cs | 27 ++++ 3 files changed, 195 insertions(+) create mode 100644 sources/TileDB.CSharp/DimensionLabel.cs create mode 100644 sources/TileDB.CSharp/Marshalling/SafeHandles/DimensionLabelHandle.cs diff --git a/sources/TileDB.CSharp/ArraySchema.cs b/sources/TileDB.CSharp/ArraySchema.cs index a08136fc..d5f148f9 100644 --- a/sources/TileDB.CSharp/ArraySchema.cs +++ b/sources/TileDB.CSharp/ArraySchema.cs @@ -532,6 +532,40 @@ public bool HasAttribute(string name) return has_attr > 0; } + /// + /// Gets a from the by name. + /// + /// The dimension label's name. + public DimensionLabel DimensionLabel(string name) + { + var handle = new DimensionLabelHandle(); + var successful = false; + tiledb_dimension_label_t* dimension_label_p = null; + try + { + using (var ctxHandle = _ctx.Handle.Acquire()) + using (var schemaHandle = _handle.Acquire()) + using (var ms_name = new MarshaledString(name)) + { + _ctx.handle_error(Methods.tiledb_array_schema_get_dimension_label_from_name(ctxHandle, schemaHandle, ms_name, &dimension_label_p)); + } + successful = true; + } + finally + { + if(successful) + { + handle.InitHandle(dimension_label_p); + } + else + { + handle.SetHandleAsInvalid(); + } + } + + return new DimensionLabel(_ctx, handle); + } + /// /// Checks if a dimension label with the given name exists in the or not. /// diff --git a/sources/TileDB.CSharp/DimensionLabel.cs b/sources/TileDB.CSharp/DimensionLabel.cs new file mode 100644 index 00000000..1ad791eb --- /dev/null +++ b/sources/TileDB.CSharp/DimensionLabel.cs @@ -0,0 +1,134 @@ +using System; +using TileDB.CSharp.Marshalling.SafeHandles; +using TileDB.Interop; + +namespace TileDB.CSharp +{ + /// + /// Represents a TileDB dimension label object. + /// + /// + public sealed unsafe class DimensionLabel : IDisposable + { + private readonly Context _ctx; + + private readonly DimensionLabelHandle _handle; + + internal DimensionLabel(Context ctx, DimensionLabelHandle handle) + { + _ctx = ctx; + _handle = handle; + } + + /// + /// This value indicates a variable-sized dimension label. + /// It may be returned from . + /// + public const uint VariableSized = Constants.VariableSizedImpl; + + /// + /// The 's data type. + /// + public DataType DataType + { + get + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + tiledb_datatype_t result; + _ctx.handle_error(Methods.tiledb_dimension_label_get_label_type(ctxHandle, handle, &result)); + return (DataType)result; + } + } + + /// + /// The order of the 's data. + /// + public DataOrder DataOrder + { + get + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + tiledb_data_order_t result; + _ctx.handle_error(Methods.tiledb_dimension_label_get_label_order(ctxHandle, handle, &result)); + return (DataOrder)result; + } + } + + /// + /// The index of the 's underlying dimension. + /// + public uint DimensionIndex + { + get + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + uint result; + _ctx.handle_error(Methods.tiledb_dimension_label_get_dimension_index(ctxHandle, handle, &result)); + return result; + } + } + + /// + /// Gets the number of values per cell for this . + /// + /// + /// For variable-sized dimension labels the result is . + /// + public uint ValuesPerCell + { + get + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + uint result; + _ctx.handle_error(Methods.tiledb_dimension_label_get_label_cell_val_num(ctxHandle, handle, &result)); + return result; + } + } + + /// + /// Gets the name of the attrbiute the 's data are stored under. + /// + public string GetAttributeName() + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + sbyte* result; + _ctx.handle_error(Methods.tiledb_dimension_label_get_label_attr_name(ctxHandle, handle, &result)); + return MarshaledStringOut.GetStringFromNullTerminated(result); + } + + /// + /// Gets the name of the . + /// + public string GetName() + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + sbyte* result; + _ctx.handle_error(Methods.tiledb_dimension_label_get_name(ctxHandle, handle, &result)); + return MarshaledStringOut.GetStringFromNullTerminated(result); + } + + /// + /// Gets the URI of the 's array. + /// + public string GetUri() + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + sbyte* result; + _ctx.handle_error(Methods.tiledb_dimension_label_get_uri(ctxHandle, handle, &result)); + return MarshaledStringOut.GetStringFromNullTerminated(result); + } + + /// + public void Dispose() + { + throw new NotImplementedException(); + } + } +} diff --git a/sources/TileDB.CSharp/Marshalling/SafeHandles/DimensionLabelHandle.cs b/sources/TileDB.CSharp/Marshalling/SafeHandles/DimensionLabelHandle.cs new file mode 100644 index 00000000..fddeebc3 --- /dev/null +++ b/sources/TileDB.CSharp/Marshalling/SafeHandles/DimensionLabelHandle.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.InteropServices; +using TileDB.Interop; + +namespace TileDB.CSharp.Marshalling.SafeHandles +{ + internal unsafe sealed class DimensionLabelHandle : SafeHandle + { + public DimensionLabelHandle() : base(IntPtr.Zero, true) { } + + public DimensionLabelHandle(IntPtr handle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) { SetHandle(handle); } + + protected override bool ReleaseHandle() + { + fixed (IntPtr* p = &handle) + { + Methods.tiledb_dimension_label_free((tiledb_dimension_label_t**)p); + } + return true; + } + + internal void InitHandle(tiledb_dimension_label_t* h) { SetHandle((IntPtr)h); } + public override bool IsInvalid => handle == IntPtr.Zero; + + public SafeHandleHolder Acquire() => new(this); + } +} From 598f9e83e587ca03c9a389fcacf89beac83656cd Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Fri, 20 Oct 2023 19:01:29 +0300 Subject: [PATCH 3/8] Add `Subarray` APIs that add dimension label ranges. --- sources/TileDB.CSharp/Subarray.cs | 48 ++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/sources/TileDB.CSharp/Subarray.cs b/sources/TileDB.CSharp/Subarray.cs index b0f439e4..ecb40aba 100644 --- a/sources/TileDB.CSharp/Subarray.cs +++ b/sources/TileDB.CSharp/Subarray.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using TileDB.CSharp.Marshalling; @@ -134,6 +134,14 @@ public void SetSubarray(ReadOnlySpan data) where T : struct } } + private void ValidateLabelType(string name) where T : struct + { + ErrorHandling.ThrowIfManagedType(); + using var schema = _array.Schema(); + using var label = schema.DimensionLabel(name); + ErrorHandling.CheckDataType(label.DataType); + } + private void ValidateType(string name) where T : struct { ErrorHandling.ThrowIfManagedType(); @@ -152,6 +160,44 @@ private void ValidateType(uint index) where T : struct ErrorHandling.CheckDataType(dimension.Type()); } + /// + /// Adds a 1D range along a subarray dimension index, in the form (start, end). + /// + /// The dimension's type. + /// The dimension's index. + /// The start of the dimension's range. + /// The end of the dimension's range. + /// is not supported. + public void AddLabelRange(string labelName, T start, T end) where T : struct + { + ValidateLabelType(labelName); + AddLabelRange(labelName, &start, &end, null); + } + + private void AddLabelRange(string labelName, void* start, void* end, void* stride) + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_name = new MarshaledString(labelName); + _ctx.handle_error(Methods.tiledb_subarray_add_label_range(ctxHandle, handle, ms_name, start, end, stride)); + } + + /// + /// Adds a 1D string range along a variable-sized subarray dimension label, in the form (start, end). + /// + /// The dimension label's name. + /// The start of the dimension label's range. + /// The end of the dimension label's range. + public void AddLabelRange(string labelName, string start, string end) + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_name = new MarshaledString(labelName); + using var ms_start = new MarshaledString(start); + using var ms_end = new MarshaledString(end); + _ctx.handle_error(Methods.tiledb_subarray_add_label_range_var(ctxHandle, handle, ms_name, ms_start, (ulong)ms_start.Length, ms_end, (ulong)ms_end.Length)); + } + /// /// Adds a 1D range along a subarray dimension index, in the form (start, end). /// From 3f7dbe15c782c5822a8911708469a1039a246388 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Thu, 9 Mar 2023 13:51:18 +0200 Subject: [PATCH 4/8] Add a notice that dimension label APIs are experimental. --- sources/TileDB.CSharp/ArraySchema.cs | 5 +++++ sources/TileDB.CSharp/DataOrder.cs | 1 + sources/TileDB.CSharp/DimensionLabel.cs | 1 + sources/TileDB.CSharp/Subarray.cs | 2 ++ 4 files changed, 9 insertions(+) diff --git a/sources/TileDB.CSharp/ArraySchema.cs b/sources/TileDB.CSharp/ArraySchema.cs index d5f148f9..a7861918 100644 --- a/sources/TileDB.CSharp/ArraySchema.cs +++ b/sources/TileDB.CSharp/ArraySchema.cs @@ -77,6 +77,7 @@ public void AddAttributes(params Attribute[] attrs) /// The dimension label's name. /// The data order of the dimension label. /// The dimension lable's data type. + /// This API is experimental and subject to breaking changes without advance notice. public void AddDimensionLabel(uint dimensionIndex, string name, DataOrder labelOrder, DataType labelType) { using var ctxHandle = _ctx.Handle.Acquire(); @@ -94,6 +95,7 @@ public void AddDimensionLabel(uint dimensionIndex, string name, DataOrder labelO /// The dimension lable's data type. /// The dimension label's tile extent. /// and do not match. + /// This API is experimental and subject to breaking changes without advance notice. public void AddDimensionLabel(uint dimensionIndex, string name, DataOrder labelOrder, DataType labelType, T extent) where T : struct { if (RuntimeHelpers.IsReferenceOrContainsReferences() || typeof(T) != EnumUtil.DataTypeToType(labelType)) @@ -177,6 +179,7 @@ public void SetCellOrder(LayoutType layoutType) /// /// The dimension label's name. /// The dimension label's filter list. + /// This API is experimental and subject to breaking changes without advance notice. public void SetDimensionLabelFilterList(string name, FilterList filterList) { using var ctxHandle = _ctx.Handle.Acquire(); @@ -536,6 +539,7 @@ public bool HasAttribute(string name) /// Gets a from the by name. /// /// The dimension label's name. + /// This API is experimental and subject to breaking changes without advance notice. public DimensionLabel DimensionLabel(string name) { var handle = new DimensionLabelHandle(); @@ -570,6 +574,7 @@ public DimensionLabel DimensionLabel(string name) /// Checks if a dimension label with the given name exists in the or not. /// /// The name to check. + /// This API is experimental and subject to breaking changes without advance notice. public bool HasDimensionLabel(string name) { int has_attr; diff --git a/sources/TileDB.CSharp/DataOrder.cs b/sources/TileDB.CSharp/DataOrder.cs index f1b444f6..c74c7d20 100644 --- a/sources/TileDB.CSharp/DataOrder.cs +++ b/sources/TileDB.CSharp/DataOrder.cs @@ -5,6 +5,7 @@ namespace TileDB.CSharp /// /// Specifies the order of data in dimension labels. /// + /// This API is experimental and subject to breaking changes without advance notice. public enum DataOrder { /// diff --git a/sources/TileDB.CSharp/DimensionLabel.cs b/sources/TileDB.CSharp/DimensionLabel.cs index 1ad791eb..257bd7a6 100644 --- a/sources/TileDB.CSharp/DimensionLabel.cs +++ b/sources/TileDB.CSharp/DimensionLabel.cs @@ -7,6 +7,7 @@ namespace TileDB.CSharp /// /// Represents a TileDB dimension label object. /// + /// This API is experimental and susceptible to breaking changes without advance notice. /// public sealed unsafe class DimensionLabel : IDisposable { diff --git a/sources/TileDB.CSharp/Subarray.cs b/sources/TileDB.CSharp/Subarray.cs index ecb40aba..e9a1aef6 100644 --- a/sources/TileDB.CSharp/Subarray.cs +++ b/sources/TileDB.CSharp/Subarray.cs @@ -168,6 +168,7 @@ private void ValidateType(uint index) where T : struct /// The start of the dimension's range. /// The end of the dimension's range. /// is not supported. + /// This API is experimental and subject to breaking changes without advance notice. public void AddLabelRange(string labelName, T start, T end) where T : struct { ValidateLabelType(labelName); @@ -188,6 +189,7 @@ private void AddLabelRange(string labelName, void* start, void* end, void* strid /// The dimension label's name. /// The start of the dimension label's range. /// The end of the dimension label's range. + /// This API is experimental and subject to breaking changes without advance notice. public void AddLabelRange(string labelName, string start, string end) { using var ctxHandle = _ctx.Handle.Acquire(); From 41adb65575a47ad92e576d9e3b98824b5b9c7cd9 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Thu, 9 Mar 2023 18:12:25 +0200 Subject: [PATCH 5/8] Add `Subarray` getter APIs for dimension labels. --- sources/TileDB.CSharp/Subarray.cs | 93 ++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/sources/TileDB.CSharp/Subarray.cs b/sources/TileDB.CSharp/Subarray.cs index e9a1aef6..b3640d00 100644 --- a/sources/TileDB.CSharp/Subarray.cs +++ b/sources/TileDB.CSharp/Subarray.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using TileDB.CSharp.Marshalling; @@ -306,6 +306,83 @@ public void AddRange(string dimensionName, string start, string end) _ctx.handle_error(Methods.tiledb_subarray_add_range_var_by_name(ctxHandle, handle, ms_name, ms_start, (ulong)ms_start.Length, ms_end, (ulong)ms_end.Length)); } + /// + /// Gets the name of the dimension label for label ranges set on this dimension of the . + /// + /// The dimension's index. + /// This API is experimental and subject to breaking changes without advance notice. + public string GetLabelName(uint dimensionIndex) + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + sbyte* result; + _ctx.handle_error(Methods.tiledb_subarray_get_label_name(ctxHandle, handle, dimensionIndex, &result)); + return MarshaledStringOut.GetStringFromNullTerminated(result); + } + + /// + /// Gets the range for a given dimension label and range index. + /// + /// The dimension label's type. + /// The dimension label's name. + /// The range's index. + /// The dimension's start and end values. + /// is not supported. + /// This API is experimental and subject to breaking changes without advance notice. + public (T Start, T End) GetLabelRange(string labelName, uint rangeIndex) where T : struct + { + ValidateLabelType(labelName); + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_dimensionName = new MarshaledString(labelName); + void* startPtr, endPtr, stridePtr_unused; + _ctx.handle_error(Methods.tiledb_subarray_get_label_range(ctxHandle, handle, ms_dimensionName, rangeIndex, &startPtr, &endPtr, &stridePtr_unused)); + return (Unsafe.ReadUnaligned(startPtr), Unsafe.ReadUnaligned(endPtr)); + } + + /// + /// Gets the string range for a given dimension label and range index. + /// + /// The dimension label's name. + /// The range's index. + /// The dimension's start and end values. + /// This API is experimental and subject to breaking changes without advance notice. + public (string Start, string End) GetStringLabelRange(string labelName, uint rangeIndex) + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_dimensionName = new MarshaledString(labelName); + ulong start_size; + ulong end_size; + _ctx.handle_error(Methods.tiledb_subarray_get_label_range_var_size(ctxHandle, handle, ms_dimensionName, rangeIndex, &start_size, &end_size)); + + using var startBuffer = new ScratchBuffer(checked((int)start_size), stackalloc byte[128]); + using var endBuffer = new ScratchBuffer(checked((int)end_size), stackalloc byte[128]); + fixed (byte* startPtr = startBuffer, endPtr = endBuffer) + { + _ctx.handle_error(Methods.tiledb_subarray_get_label_range_var(ctxHandle, handle, ms_dimensionName, rangeIndex, startPtr, endPtr)); + } + + var startStr = MarshaledStringOut.GetString(startBuffer.Span); + var endStr = MarshaledStringOut.GetString(endBuffer.Span); + return (startStr, endStr); + } + + /// + /// Gets the number of ranges for a given dimension label name. + /// + /// The dimension label's name. + /// This API is experimental and subject to breaking changes without advance notice. + public ulong GetLabelRangeCount(string labelName) + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + using var ms_dimensionName = new MarshaledString(labelName); + ulong result; + _ctx.handle_error(Methods.tiledb_subarray_get_label_range_num(ctxHandle, handle, ms_dimensionName, &result)); + return result; + } + /// /// Gets the number of ranges for a given dimension index. /// @@ -422,5 +499,19 @@ public ulong GetRangeCount(string dimensionName) var endStr = MarshaledStringOut.GetString(endBuffer.Span); return (startStr, endStr); } + + /// + /// Checks whether the has label ranges set on the requested dimension. + /// + /// The dimension's index. + /// This API is experimental and subject to breaking changes without advance notice. + public bool HasLabelRanges(uint dimensionIndex) + { + using var ctxHandle = _ctx.Handle.Acquire(); + using var handle = _handle.Acquire(); + int result; + _ctx.handle_error(Methods.tiledb_subarray_has_label_ranges(ctxHandle, handle, dimensionIndex, &result)); + return result != 0; + } } } From e2851ac50798528ede9e77eae14c7212b4f6733e Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Mon, 16 Oct 2023 19:41:51 +0300 Subject: [PATCH 6/8] Add a dimension labels example. --- .../ExampleDimensionLabels.cs | 201 ++++++++++++++++++ examples/TileDB.CSharp.Example/Program.cs | 1 + 2 files changed, 202 insertions(+) create mode 100644 examples/TileDB.CSharp.Example/ExampleDimensionLabels.cs diff --git a/examples/TileDB.CSharp.Example/ExampleDimensionLabels.cs b/examples/TileDB.CSharp.Example/ExampleDimensionLabels.cs new file mode 100644 index 00000000..0c5040a3 --- /dev/null +++ b/examples/TileDB.CSharp.Example/ExampleDimensionLabels.cs @@ -0,0 +1,201 @@ +using System; +using System.IO; +using System.Linq; + +namespace TileDB.CSharp.Examples +{ + public static class ExampleDimensionLabels + { + private static readonly string ArrayPath = ExampleUtil.MakeExamplePath("dimension-labels"); + private static readonly Context Ctx = Context.GetDefault(); + + private static void CreateArray() + { + using var xIndex = Dimension.Create(Ctx, "x_index", 0, 5, 6); + using var sample = Dimension.Create(Ctx, "sample", 0, 3, 4); + + using var domain = new Domain(Ctx); + domain.AddDimensions(xIndex, sample); + + using var a = Attribute.Create(Ctx, "a"); + + using var schema = new ArraySchema(Ctx, ArrayType.Dense); + schema.SetCellOrder(LayoutType.RowMajor); + schema.SetTileOrder(LayoutType.RowMajor); + schema.SetDomain(domain); + schema.AddAttribute(a); + schema.AddDimensionLabel(0, "x", DataOrder.Increasing, DataType.Float64); + schema.AddDimensionLabel(0, "y", DataOrder.Increasing, DataType.Float64); + schema.AddDimensionLabel(1, "timestamp", DataOrder.Increasing, DataType.DateTimeSecond); + + Array.Create(Ctx, ArrayPath, schema); + } + + private static void WriteArrayAndLabels() + { + short[] a = Enumerable.Range(1, 24).Select(x => (short)x).ToArray(); + double[] x = { -1.0, -0.6, -0.2, 0.2, 0.6, 1.0 }; + double[] y = { 0.0, 2.0, 4.0, 6.0, 8.0, 10.0 }; + long[] timestamp = { 31943, 32380, 33131, 33228 }; + + using Array array = new Array(Ctx, ArrayPath); + array.Open(QueryType.Write); + + using Query query = new Query(Ctx, array); + query.SetLayout(LayoutType.RowMajor); + query.SetDataBuffer("a", a); + query.SetDataBuffer("x", x); + query.SetDataBuffer("y", y); + query.SetDataBuffer("timestamp", timestamp); + + query.Submit(); + + if (query.Status() != QueryStatus.Completed) + { + throw new Exception("Write query did not complete."); + } + + array.Close(); + } + + private static void ReadArrayAndLabels() + { + Console.WriteLine("Read from main array"); + + using var array = new Array(Ctx, ArrayPath); + array.Open(QueryType.Read); + + using var subarray = new Subarray(array); + subarray.AddRange(0, 1, 2); + subarray.AddRange(1, 0, 2); + + short[] a = new short[6]; + double[] x = new double[2]; + double[] y = new double[2]; + long[] timestamp = new long[3]; + + using var query = new Query(Ctx, array); + query.SetLayout(LayoutType.RowMajor); + query.SetSubarray(subarray); + query.SetDataBuffer("a", a); + query.SetDataBuffer("x", x); + query.SetDataBuffer("y", y); + query.SetDataBuffer("timestamp", timestamp); + + query.Submit(); + + if (query.Status() != QueryStatus.Completed) + { + throw new Exception("Read query did not complete."); + } + + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3; j++) + { + int x_val = i + 1; + int sample_val = j; + Console.WriteLine($"Cell ({x_val}, {sample_val})"); + Console.WriteLine($" * a({x_val}, {sample_val}) = {a[3 * i + j]}"); + Console.WriteLine($" * x({x_val}) = {x[i]}"); + Console.WriteLine($" * y({x_val}) = {y[i]}"); + Console.WriteLine($" * timestamp({sample_val}) = {TimeSpan.FromSeconds(timestamp[j])}"); + } + } + + array.Close(); + } + + private static void ReadTimestampData() + { + Console.WriteLine("Read from dimension label"); + + using var array = new Array(Ctx, ArrayPath); + array.Open(QueryType.Read); + + using var subarray = new Subarray(array); + subarray.AddRange(1, 1, 3); + + long[] timestamp = new long[3]; + + using var query = new Query(Ctx, array); + query.SetLayout(LayoutType.RowMajor); + query.SetSubarray(subarray); + query.SetDataBuffer("timestamp", timestamp); + + query.Submit(); + + if (query.Status() != QueryStatus.Completed) + { + throw new Exception("Read query did not complete."); + } + + for (int i = 0; i < 3; i++) + { + int sample_val = i + 1; + Console.WriteLine($"Cell ({sample_val})"); + Console.WriteLine($" * timestamp({sample_val}) = {TimeSpan.FromSeconds(timestamp[i])}"); + } + + array.Close(); + } + + private static void ReadArrayByLabel() + { + Console.WriteLine("Read array from label ranges"); + + using var array = new Array(Ctx, ArrayPath); + array.Open(QueryType.Read); + + using var subarray = new Subarray(array); + subarray.AddLabelRange("y", 3.0, 8.0); + subarray.AddLabelRange("timestamp", 31943, 32380); + + short[] a = new short[6]; + double[] y = new double[3]; + long[] timestamp = new long[2]; + + using var query = new Query(Ctx, array); + query.SetLayout(LayoutType.RowMajor); + query.SetSubarray(subarray); + query.SetDataBuffer("y", y); + query.SetDataBuffer("timestamp", timestamp); + query.SetDataBuffer("a", a); + + query.Submit(); + + if (query.Status() != QueryStatus.Completed) + { + throw new Exception("Read query did not complete."); + } + + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 2; j++) + { + Console.WriteLine($"Cell ({y[i]}, {TimeSpan.FromSeconds(timestamp[j])})"); + Console.WriteLine($" * a = {a[2 * i + j]}"); + } + } + + array.Close(); + } + + public static void Run() + { + if (Directory.Exists(ArrayPath)) + { + Directory.Delete(ArrayPath, true); + } + + CreateArray(); + WriteArrayAndLabels(); + ReadArrayAndLabels(); + Console.WriteLine(); + ReadTimestampData(); + Console.WriteLine(); + ReadArrayByLabel(); + Console.WriteLine(); + } + } +} diff --git a/examples/TileDB.CSharp.Example/Program.cs b/examples/TileDB.CSharp.Example/Program.cs index 78c993ee..b858b96d 100644 --- a/examples/TileDB.CSharp.Example/Program.cs +++ b/examples/TileDB.CSharp.Example/Program.cs @@ -15,6 +15,7 @@ static void Main(string[] args) ExampleIncompleteQueryVariableSize.Run(); ExampleWritingDenseGlobal.Run(); ExampleWritingSparseGlobal.Run(); + ExampleDimensionLabels.Run(); ExampleFile.RunLocal(); // ExampleFile.RunCloud("tiledb_api_token", "tiledb_namespace", "new_cloud_array_name", "s3://bucket/prefix/"); From 31d0564f5a3ae5079aa2f4243a187a5c5006b11a Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Fri, 10 Mar 2023 17:36:11 +0200 Subject: [PATCH 7/8] Validate dimension label types when setting query buffers. --- sources/TileDB.CSharp/Query.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sources/TileDB.CSharp/Query.cs b/sources/TileDB.CSharp/Query.cs index e0292be8..31b24e43 100644 --- a/sources/TileDB.CSharp/Query.cs +++ b/sources/TileDB.CSharp/Query.cs @@ -986,6 +986,11 @@ private static DataType GetDataType(string name, ArraySchema schema, Domain doma using var dimension = domain.Dimension(name); return dimension.Type(); } + else if (schema.HasDimensionLabel(name)) + { + using var label = schema.DimensionLabel(name); + return label.DataType; + } if (name == "__coords") { From a704a16dc2925b4f17e628135803630e36d4804b Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Fri, 10 Mar 2023 18:14:24 +0200 Subject: [PATCH 8/8] Dispose the dimension label handle. --- sources/TileDB.CSharp/DimensionLabel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/TileDB.CSharp/DimensionLabel.cs b/sources/TileDB.CSharp/DimensionLabel.cs index 257bd7a6..d353a161 100644 --- a/sources/TileDB.CSharp/DimensionLabel.cs +++ b/sources/TileDB.CSharp/DimensionLabel.cs @@ -129,7 +129,7 @@ public string GetUri() /// public void Dispose() { - throw new NotImplementedException(); + _handle.Dispose(); } } }