diff --git a/docs/obsoletions.md b/docs/obsoletions.md
index 8893f3a2..78b9bc31 100644
--- a/docs/obsoletions.md
+++ b/docs/obsoletions.md
@@ -7,7 +7,7 @@ Following [the deprecation policy of TileDB Embedded][core-deprecation], obsolet
|Diagnostic codes|Deprecated in version|Removed in version|
|----------------|---------------------|------------------|
|[`TILEDB0001`](#TILEDB0001) …[`TILEDB0011`](#TILEDB0011)|5.3.0|5.5.0|
-|[`TILEDB0012`](#TILEDB0012) …[`TILEDB0012`](#TILEDB0012)|5.7.0|5.9.0|
+|[`TILEDB0012`](#TILEDB0012) …[`TILEDB0013`](#TILEDB0013)|5.7.0|5.9.0|
## `TILEDB0001` - Enum value names that start with `TILEDB_` were replaced with C#-friendly names.
@@ -320,3 +320,17 @@ The obsoleted APIs fall into the following categories:
- Types with the name `tiledb_***_t` were made public again only to support the APIs of the safe handles above. They have little other use on their own. You should use APIs in the `TileDB.CSharp` namespace instead.
[core-deprecation]: https://github.com/TileDB-Inc/TileDB/blob/dev/doc/policy/api_changes.md
+
+## `TILEDB0013` - The `EnumUtils.TypeToDataType` and `EnumUtils.DataTypeToType` methods are obsolete and will be removed in a future version.
+
+
+
+The `EnumUtils.TypeToDataType` and `EnumUtils.DataTypeToType` methods convert between TileDB data types and .NET types. Given that there is no one-to-one correspondence between these two and for legacy reasons, these methods sometimes return wrong results and were obsoleted.
+
+### Version introduced
+
+5.7.0
+
+### Recommended action
+
+If you are performing queries on arrays of unknown schema, you can use the `Query.UnsafeSetDataBuffer` and `Query.UnsafeSetWriteDataBuffer` methods to set a data buffer to a query without type validation.
diff --git a/sources/TileDB.CSharp/Array.cs b/sources/TileDB.CSharp/Array.cs
index 7c04c1a4..9d8315c4 100644
--- a/sources/TileDB.CSharp/Array.cs
+++ b/sources/TileDB.CSharp/Array.cs
@@ -501,15 +501,11 @@ static void GetDomain(Array array, string dimName, uint i, NonEmptyDomain non
/// is not the dimension's type.
public (T Start, T End, bool IsEmpty) NonEmptyDomain(uint index) where T : struct
{
- var datatype = EnumUtil.TypeToDataType(typeof(T));
using (var schema = Schema())
using (var domain = schema.Domain())
using (var dimension = domain.Dimension(index))
{
- if (datatype != dimension.Type())
- {
- throw new ArgumentException("Array.NonEmptyDomain, not valid datatype!");
- }
+ ErrorHandling.CheckDataType(dimension.Type());
}
SequentialPair data;
@@ -531,15 +527,11 @@ static void GetDomain(Array array, string dimName, uint i, NonEmptyDomain non
/// is not the dimension's type.
public (T Start, T End, bool IsEmpty) NonEmptyDomain(string name) where T : struct
{
- var datatype = EnumUtil.TypeToDataType(typeof(T));
using (var schema = Schema())
using (var domain = schema.Domain())
using (var dimension = domain.Dimension(name))
{
- if (datatype != dimension.Type())
- {
- throw new ArgumentException("Array.NonEmptyDomain, not valid datatype!");
- }
+ ErrorHandling.CheckDataType(dimension.Type());
}
using var ms_name = new MarshaledString(name);
diff --git a/sources/TileDB.CSharp/ArrayMetadata.cs b/sources/TileDB.CSharp/ArrayMetadata.cs
index 0e7b1ef3..92583854 100644
--- a/sources/TileDB.CSharp/ArrayMetadata.cs
+++ b/sources/TileDB.CSharp/ArrayMetadata.cs
@@ -300,7 +300,7 @@ IEnumerator IEnumerable.GetEnumerator()
private void put_metadata(string key, T[] value, tiledb_datatype_t tiledb_datatype) where T : struct
{
- ErrorHandling.ThrowIfManagedType();
+ ErrorHandling.CheckDataType((DataType)tiledb_datatype);
if (string.IsNullOrEmpty(key) || value.Length == 0)
{
throw new ArgumentException("ArrayMetadata.put_metadata, null or empty key-value!");
diff --git a/sources/TileDB.CSharp/Attribute.cs b/sources/TileDB.CSharp/Attribute.cs
index 98f478f6..a1bd479c 100644
--- a/sources/TileDB.CSharp/Attribute.cs
+++ b/sources/TileDB.CSharp/Attribute.cs
@@ -195,7 +195,7 @@ public ulong CellSize()
/// An array of values that will be used as the fill value.
private void SetFillValue(T[] data) where T : struct
{
- ErrorHandling.ThrowIfManagedType();
+ ErrorHandling.CheckDataType(Type());
if (data.Length == 0)
{
throw new ArgumentException("Attribute.SetFillValue, data is empty!");
diff --git a/sources/TileDB.CSharp/Dimension.cs b/sources/TileDB.CSharp/Dimension.cs
index 009ffa6d..4ff733c4 100644
--- a/sources/TileDB.CSharp/Dimension.cs
+++ b/sources/TileDB.CSharp/Dimension.cs
@@ -146,7 +146,7 @@ public DataType Type()
///
public (T Start, T End) GetDomain() where T : struct
{
- ErrorHandling.ThrowIfManagedType();
+ ErrorHandling.CheckDataType(Type());
void* value_p;
using var ctxHandle = _ctx.Handle.Acquire();
@@ -163,7 +163,7 @@ public DataType Type()
///
public T TileExtent() where T : struct
{
- ErrorHandling.ThrowIfManagedType();
+ ErrorHandling.CheckDataType(Type());
using var ctxHandle = _ctx.Handle.Acquire();
using var handle = _handle.Acquire();
void* value_p;
diff --git a/sources/TileDB.CSharp/Enums.cs b/sources/TileDB.CSharp/Enums.cs
index 1d365eb2..98747f74 100644
--- a/sources/TileDB.CSharp/Enums.cs
+++ b/sources/TileDB.CSharp/Enums.cs
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
+using System.Text;
using TileDB.Interop;
namespace TileDB.CSharp
@@ -185,115 +186,217 @@ public enum DataType : uint
///
/// A signed 32-bit integer.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
Int32 = tiledb_datatype_t.TILEDB_INT32,
///
/// A signed 64-bit integer.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
Int64 = tiledb_datatype_t.TILEDB_INT64,
///
/// A 32-bit floating-point number.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
Float32 = tiledb_datatype_t.TILEDB_FLOAT32,
///
/// A 64-bit floating-point number.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
Float64 = tiledb_datatype_t.TILEDB_FLOAT64,
///
/// A signed 8-bit integer.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
Int8 = tiledb_datatype_t.TILEDB_INT8,
///
/// An unsigned 8-bit integer.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
UInt8 = tiledb_datatype_t.TILEDB_UINT8,
///
/// A signed 16-bit integer.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
Int16 = tiledb_datatype_t.TILEDB_INT16,
///
/// An unsigned 16-bit integer.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
UInt16 = tiledb_datatype_t.TILEDB_UINT16,
///
/// An unsigned 32-bit integer.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
UInt32 = tiledb_datatype_t.TILEDB_UINT32,
///
/// An unsigned 64-bit integer.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
UInt64 = tiledb_datatype_t.TILEDB_UINT64,
///
/// An ASCII string.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
StringAscii = tiledb_datatype_t.TILEDB_STRING_ASCII,
///
/// A UTF-8 string.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
StringUtf8 = tiledb_datatype_t.TILEDB_STRING_UTF8,
///
/// A UTF-16 string.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with or .
+ ///
StringUtf16 = tiledb_datatype_t.TILEDB_STRING_UTF16,
///
/// A UTF-32 string.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
StringUtf32 = tiledb_datatype_t.TILEDB_STRING_UTF32,
///
/// A date and time, counted as the signed 64-bit number of
/// years since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeYear = tiledb_datatype_t.TILEDB_DATETIME_YEAR,
///
/// A date and time, counted as the signed 64-bit number of
/// months since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeMonth = tiledb_datatype_t.TILEDB_DATETIME_MONTH,
///
/// A date and time, counted as the signed 64-bit number of
/// weeks since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeWeek = tiledb_datatype_t.TILEDB_DATETIME_WEEK,
///
/// A date and time, counted as the signed 64-bit number of
/// days since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeDay = tiledb_datatype_t.TILEDB_DATETIME_DAY,
///
/// A date and time, counted as the signed 64-bit number of
/// hours since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeHour = tiledb_datatype_t.TILEDB_DATETIME_HR,
///
/// A date and time, counted as the signed 64-bit number of
/// minutes since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeMinute = tiledb_datatype_t.TILEDB_DATETIME_MIN,
///
/// A date and time, counted as the signed 64-bit number of
/// seconds since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeSecond = tiledb_datatype_t.TILEDB_DATETIME_SEC,
///
/// A date and time, counted as the signed 64-bit number of
/// milliseconds since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeMillisecond = tiledb_datatype_t.TILEDB_DATETIME_MS,
///
/// A date and time, counted as the signed 64-bit number of
/// microseconds since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeMicrosecond = tiledb_datatype_t.TILEDB_DATETIME_US,
///
/// A date and time, counted as the signed 64-bit number of
/// nanoseconds since the Unix epoch (January 1 1970 at midnight).
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
DateTimeNanosecond = tiledb_datatype_t.TILEDB_DATETIME_NS,
///
/// A date and time, counted as the signed 64-bit number of
/// picoseconds since the Unix epoch (January 1 1970 at midnight).
///
///
+ ///
/// One second consists of one trillion picoseconds.
+ ///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
///
DateTimePicosecond = tiledb_datatype_t.TILEDB_DATETIME_PS,
///
@@ -301,7 +404,13 @@ public enum DataType : uint
/// femtoseconds since the Unix epoch (January 1 1970 at midnight).
///
///
+ ///
/// One second consists of one quadrillion femtoseconds.
+ ///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
///
DateTimeFemtosecond = tiledb_datatype_t.TILEDB_DATETIME_FS,
///
@@ -309,32 +418,62 @@ public enum DataType : uint
/// attoseconds since the Unix epoch (January 1 1970 at midnight).
///
///
+ ///
/// One second consists of one quintillion attoseconds.
+ ///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
///
DateTimeAttosecond = tiledb_datatype_t.TILEDB_DATETIME_AS,
///
/// A time of day counted in hours.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
TimeHour = tiledb_datatype_t.TILEDB_TIME_HR,
///
/// A time of day counted in minutes.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
TimeMinute = tiledb_datatype_t.TILEDB_TIME_MIN,
///
/// A time of day counted in seconds.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
TimeSecond = tiledb_datatype_t.TILEDB_TIME_SEC,
///
/// A time of day counted in milliseconds.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
TimeMillisecond = tiledb_datatype_t.TILEDB_TIME_MS,
///
/// A time of day counted in microseconds.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
TimeMicrosecond = tiledb_datatype_t.TILEDB_TIME_US,
///
/// A time of day counted in nanoseconds.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
TimeNanosecond = tiledb_datatype_t.TILEDB_TIME_NS,
///
/// A time of day counted in picoseconds.
@@ -349,12 +488,20 @@ public enum DataType : uint
///
TimeAttosecond = tiledb_datatype_t.TILEDB_TIME_AS,
///
- /// A binary blob.
+ /// Binary data.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with .
+ ///
Blob = tiledb_datatype_t.TILEDB_BLOB,
///
/// A boolean value.
///
+ ///
+ /// On generic methods operating to objects of this datatype,
+ /// this datatype can be used with or .
+ ///
Boolean = tiledb_datatype_t.TILEDB_BOOL
}
@@ -968,6 +1115,7 @@ public static VfsMode VfsModeFromStr(string str)
///
/// The type to convert.
/// is unsupported.
+ [Obsolete(Obsoletions.DataTypeTypeConversionsMessage, DiagnosticId = Obsoletions.DataTypeTypeConversionsDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public static DataType TypeToDataType(Type t)
{
if (t == typeof(int))
@@ -1025,6 +1173,7 @@ public static DataType TypeToDataType(Type t)
}
}
+ [Obsolete(Obsoletions.DataTypeTypeConversionsMessage, DiagnosticId = Obsoletions.DataTypeTypeConversionsDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public static Type DataTypeToType(DataType datatype)
{
switch (datatype)
@@ -1087,6 +1236,71 @@ public static Type DataTypeToType(DataType datatype)
}
}
+ // Same with DataTypeToType, but returns the correct corresponding numeric type for strings.
+ internal static Type DataTypeToNumericType(DataType datatype)
+ {
+ switch (datatype)
+ {
+ case DataType.DateTimeAttosecond:
+ case DataType.DateTimeDay:
+ case DataType.DateTimeFemtosecond:
+ case DataType.DateTimeHour:
+ case DataType.DateTimeMinute:
+ case DataType.DateTimeMonth:
+ case DataType.DateTimeMillisecond:
+ case DataType.DateTimeNanosecond:
+ case DataType.DateTimePicosecond:
+ case DataType.DateTimeSecond:
+ case DataType.DateTimeMicrosecond:
+ case DataType.DateTimeWeek:
+ case DataType.DateTimeYear:
+ return typeof(long);
+ case DataType.Float32:
+ return typeof(float);
+ case DataType.Float64:
+ return typeof(double);
+ case DataType.Int16:
+ return typeof(short);
+ case DataType.Int32:
+ return typeof(int);
+ case DataType.Int64:
+ return typeof(long);
+ case DataType.Int8:
+ return typeof(sbyte);
+ case DataType.StringAscii:
+ case DataType.StringUtf8:
+ return typeof(byte);
+ case DataType.StringUtf16:
+ return typeof(ushort);
+ case DataType.StringUtf32:
+ return typeof(uint);
+ case DataType.TimeAttosecond:
+ case DataType.TimeFemtosecond:
+ case DataType.TimeHour:
+ case DataType.TimeMinute:
+ case DataType.TimeMillisecond:
+ case DataType.TimeNanosecond:
+ case DataType.TimePicosecond:
+ case DataType.TimeSecond:
+ case DataType.TimeMicrosecond:
+ return typeof(long);
+ case DataType.UInt16:
+ return typeof(ushort);
+ case DataType.UInt32:
+ return typeof(uint);
+ case DataType.UInt64:
+ return typeof(ulong);
+ case DataType.UInt8:
+ return typeof(byte);
+ case DataType.Blob:
+ return typeof(byte);
+ case DataType.Boolean:
+ return typeof(byte);
+ default:
+ return typeof(byte);
+ }
+ }
+
public static bool IsStringType(DataType datatype)
{
return datatype == DataType.StringAscii
diff --git a/sources/TileDB.CSharp/ErrorHandling.cs b/sources/TileDB.CSharp/ErrorHandling.cs
index 3d2c3bd8..c7e0f87e 100644
--- a/sources/TileDB.CSharp/ErrorHandling.cs
+++ b/sources/TileDB.CSharp/ErrorHandling.cs
@@ -2,6 +2,7 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
+using System.Text;
using TileDB.Interop;
namespace TileDB.CSharp
@@ -55,5 +56,39 @@ public static void ThrowIfManagedType()
ThrowHelpers.ThrowManagedType();
}
}
+
+ ///
+ /// Returns whether values of type can be stored or
+ /// retrieved from a TileDB buffer of type .
+ ///
+ private static unsafe bool AreTypesCompatible(DataType dataType)
+ {
+ if (EnumUtil.DataTypeToNumericType(dataType) == typeof(T))
+ {
+ return true;
+ }
+ if (typeof(T) == typeof(bool) && dataType == DataType.Boolean)
+ {
+ return true;
+ }
+ if (typeof(T) == typeof(char) && dataType == DataType.StringUtf16)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Throws if values of type cannot be stored or
+ /// retrieved from a TileDB buffer of type .
+ ///
+ public static void CheckDataType(DataType dataType)
+ {
+ ThrowIfManagedType();
+ if (!AreTypesCompatible(dataType))
+ {
+ ThrowHelpers.ThrowTypeMismatch(dataType);
+ }
+ }
}
}
diff --git a/sources/TileDB.CSharp/FragmentInfo.cs b/sources/TileDB.CSharp/FragmentInfo.cs
index 5db26a0d..aba0faf0 100644
--- a/sources/TileDB.CSharp/FragmentInfo.cs
+++ b/sources/TileDB.CSharp/FragmentInfo.cs
@@ -409,18 +409,18 @@ public ulong GetMinimumBoundedRectangleCount(uint fragmentIndex)
public (T Start, T End) GetMinimumBoundedRectangle(uint fragmentIndex, uint minimumBoundedRectangleIndex, uint dimensionIndex)
{
DataType dataType = GetDimensionType(fragmentIndex, dimensionIndex);
- ValidateDomainType(dataType);
if (RuntimeHelpers.IsReferenceOrContainsReferences())
{
- if (typeof(T) == typeof(string))
+ if (typeof(T) == typeof(string) && EnumUtil.IsStringType(dataType))
{
(string startStr, string endStr) =
GetStringMinimumBoundedRectangle(fragmentIndex, minimumBoundedRectangleIndex, dimensionIndex, dataType);
return ((T)(object)startStr, (T)(object)endStr);
}
- ThrowHelpers.ThrowTypeNotSupported();
+ ThrowHelpers.ThrowTypeMismatch(dataType);
return default;
}
+ ValidateDomainType(dataType);
using var ctxHandle = _ctx.Handle.Acquire();
using var handle = _handle.Acquire();
@@ -448,18 +448,18 @@ public ulong GetMinimumBoundedRectangleCount(uint fragmentIndex)
public (T Start, T End) GetMinimumBoundedRectangle(uint fragmentIndex, uint minimumBoundedRectangleIndex, string dimensionName)
{
DataType dataType = GetDimensionType(fragmentIndex, dimensionName);
- ValidateDomainType(dataType);
if (RuntimeHelpers.IsReferenceOrContainsReferences())
{
- if (typeof(T) == typeof(string))
+ if (typeof(T) == typeof(string) && EnumUtil.IsStringType(dataType))
{
(string startStr, string endStr) =
GetStringMinimumBoundedRectangle(fragmentIndex, minimumBoundedRectangleIndex, dimensionName, dataType);
return ((T)(object)startStr, (T)(object)endStr);
}
- ThrowHelpers.ThrowTypeNotSupported();
+ ThrowHelpers.ThrowTypeMismatch(dataType);
return default;
}
+ ValidateDomainType(dataType);
using var ctxHandle = _ctx.Handle.Acquire();
using var handle = _handle.Acquire();
@@ -534,17 +534,17 @@ public ulong GetMinimumBoundedRectangleCount(uint fragmentIndex)
public (T Start, T End) GetNonEmptyDomain(uint fragmentIndex, uint dimensionIndex)
{
DataType dataType = GetDimensionType(fragmentIndex, dimensionIndex);
- ValidateDomainType(dataType);
if (RuntimeHelpers.IsReferenceOrContainsReferences())
{
- if (typeof(T) == typeof(string))
+ if (typeof(T) == typeof(string) && EnumUtil.IsStringType(dataType))
{
(string startStr, string endStr) = GetStringNonEmptyDomain(fragmentIndex, dimensionIndex, dataType);
return ((T)(object)startStr, (T)(object)endStr);
}
- ThrowHelpers.ThrowTypeNotSupported();
+ ThrowHelpers.ThrowTypeMismatch(dataType);
return default;
}
+ ValidateDomainType(dataType);
using var ctxHandle = _ctx.Handle.Acquire();
using var handle = _handle.Acquire();
@@ -572,17 +572,17 @@ public ulong GetMinimumBoundedRectangleCount(uint fragmentIndex)
public (T Start, T End) GetNonEmptyDomain(uint fragmentIndex, string dimensionName)
{
DataType dataType = GetDimensionType(fragmentIndex, dimensionName);
- ValidateDomainType(dataType);
if (RuntimeHelpers.IsReferenceOrContainsReferences())
{
- if (typeof(T) == typeof(string))
+ if (typeof(T) == typeof(string) && EnumUtil.IsStringType(dataType))
{
(string startStr, string endStr) = GetStringNonEmptyDomain(fragmentIndex, dimensionName, dataType);
return ((T)(object)startStr, (T)(object)endStr);
}
- ThrowHelpers.ThrowTypeNotSupported();
+ ThrowHelpers.ThrowTypeMismatch(dataType);
return default;
}
+ ValidateDomainType(dataType);
using var ctxHandle = _ctx.Handle.Acquire();
using var handle = _handle.Acquire();
@@ -653,10 +653,7 @@ private static void ValidateDomainType(DataType dataType)
{
ThrowHelpers.ThrowStringTypeMismatch(dataType);
}
- if (dataType != EnumUtil.TypeToDataType(typeof(T)))
- {
- ThrowHelpers.ThrowTypeMismatch(dataType);
- }
+ ErrorHandling.CheckDataType(dataType);
}
private DataType GetDimensionType(uint fragmentIndex, uint dimensionIndex)
diff --git a/sources/TileDB.CSharp/GroupMetadata.cs b/sources/TileDB.CSharp/GroupMetadata.cs
index 3c7a5253..c7af584a 100644
--- a/sources/TileDB.CSharp/GroupMetadata.cs
+++ b/sources/TileDB.CSharp/GroupMetadata.cs
@@ -330,7 +330,7 @@ IEnumerator IEnumerable.GetEnumerator()
#region Private methods
private void put_metadata(string key, T[] value, tiledb_datatype_t tiledb_datatype) where T : struct
{
- ErrorHandling.ThrowIfManagedType();
+ ErrorHandling.CheckDataType((DataType)tiledb_datatype);
if (string.IsNullOrEmpty(key) || value.Length == 0)
{
throw new ArgumentException("ArrayMetadata.put_metadata, null or empty key-value!");
diff --git a/sources/TileDB.CSharp/Interop/SpanExtensions.cs b/sources/TileDB.CSharp/Interop/SpanExtensions.cs
index 99a4ae4b..07041740 100644
--- a/sources/TileDB.CSharp/Interop/SpanExtensions.cs
+++ b/sources/TileDB.CSharp/Interop/SpanExtensions.cs
@@ -8,7 +8,7 @@
namespace TileDB.Interop
{
- [Obsolete(Obsoletions.TileDBInteropMessage, DiagnosticId = Obsoletions.TileDBInteropDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
+ [Obsolete(Obsoletions.TileDBInterop2Message, DiagnosticId = Obsoletions.TileDBInterop2DiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static unsafe class SpanExtensions
{
diff --git a/sources/TileDB.CSharp/Marshalling/MarshaledStringOut.cs b/sources/TileDB.CSharp/Marshalling/MarshaledStringOut.cs
index 4850c2b7..22bdff72 100644
--- a/sources/TileDB.CSharp/Marshalling/MarshaledStringOut.cs
+++ b/sources/TileDB.CSharp/Marshalling/MarshaledStringOut.cs
@@ -5,7 +5,7 @@
namespace TileDB.Interop
{
- [Obsolete(Obsoletions.TileDBInteropMessage, DiagnosticId = Obsoletions.TileDBInteropDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
+ [Obsolete(Obsoletions.TileDBInterop2Message, DiagnosticId = Obsoletions.TileDBInterop2DiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[EditorBrowsable(EditorBrowsableState.Never)]
public unsafe class LibC
{
diff --git a/sources/TileDB.CSharp/Obsoletions.cs b/sources/TileDB.CSharp/Obsoletions.cs
index 33850a81..8b4f69ec 100644
--- a/sources/TileDB.CSharp/Obsoletions.cs
+++ b/sources/TileDB.CSharp/Obsoletions.cs
@@ -41,5 +41,8 @@ internal static class Obsoletions
public const string TileDBInterop2Message = "Members of the TileDB.Interop namespace should not be used by user code and will become internal in a future version.";
public const string TileDBInterop2DiagId = "TILEDB0012";
+
+ public const string DataTypeTypeConversionsMessage = "The EnumUtils.TypeToDataType and EnumUtils.DataTypeToType methods are obsolete and will be removed in a future version.";
+ public const string DataTypeTypeConversionsDiagId = "TILEDB0013";
}
}
diff --git a/sources/TileDB.CSharp/Query.cs b/sources/TileDB.CSharp/Query.cs
index 800d3ce0..bb7e9928 100644
--- a/sources/TileDB.CSharp/Query.cs
+++ b/sources/TileDB.CSharp/Query.cs
@@ -285,7 +285,7 @@ public void SetDataBuffer(string name, Memory data) where T : struct
using (var schema = _array.Schema())
using (var domain = schema.Domain())
{
- CheckDataType(GetDataType(name, schema, domain));
+ ErrorHandling.CheckDataType(GetDataType(name, schema, domain));
}
if (data.IsEmpty)
@@ -321,7 +321,7 @@ public void SetDataBuffer(string name, T* data, ulong size) where T : struct
using (var schema = _array.Schema())
using (var domain = schema.Domain())
{
- CheckDataType(GetDataType(name, schema, domain));
+ ErrorHandling.CheckDataType(GetDataType(name, schema, domain));
}
UnsafeSetDataBuffer(name, new MemoryHandle(data), size * (ulong)sizeof(T), sizeof(T));
@@ -931,18 +931,6 @@ public Tuple FragmentTimestampRange(ulong idx)
return new Tuple(t1, t2);
}
- private void CheckDataType(DataType dataType)
- {
- if (EnumUtil.TypeToDataType(typeof(T)) != dataType)
- {
- if (!(dataType== DataType.StringAscii && (typeof(T)==typeof(byte) || typeof(T) == typeof(sbyte) || typeof(T) == typeof(string)))
- && !(dataType == DataType.Boolean && typeof(T) == typeof(byte)))
- {
- throw new ArgumentException("T " + typeof(T).Name + " doesnot match " + dataType.ToString());
- }
- }
- }
-
private static DataType GetDataType(string name, ArraySchema schema, Domain domain)
{
if (schema.HasAttribute(name))
diff --git a/sources/TileDB.CSharp/Subarray.cs b/sources/TileDB.CSharp/Subarray.cs
index 958fbc56..b0f439e4 100644
--- a/sources/TileDB.CSharp/Subarray.cs
+++ b/sources/TileDB.CSharp/Subarray.cs
@@ -118,13 +118,9 @@ public void SetSubarray(params T[] data) where T : struct
public void SetSubarray(ReadOnlySpan data) where T : struct
{
ErrorHandling.ThrowIfManagedType();
- var dataType = EnumUtil.TypeToDataType(typeof(T));
(var domainType, var nDim) = GetDomainInfo();
- if (dataType != domainType)
- {
- ThrowHelpers.ThrowTypeMismatch(dataType);
- }
+ ErrorHandling.CheckDataType(domainType);
if (data.Length != nDim * 2)
{
ThrowHelpers.ThrowSubarrayLengthMismatch(nameof(data));
@@ -141,27 +137,19 @@ public void SetSubarray(ReadOnlySpan data) where T : struct
private void ValidateType(string name) where T : struct
{
ErrorHandling.ThrowIfManagedType();
- var dataType = EnumUtil.TypeToDataType(typeof(T));
using var schema = _array.Schema();
using var domain = schema.Domain();
using var dimension = domain.Dimension(name);
- if (dimension.Type() != dataType)
- {
- ThrowHelpers.ThrowTypeMismatch(dataType);
- }
+ ErrorHandling.CheckDataType(dimension.Type());
}
private void ValidateType(uint index) where T : struct
{
ErrorHandling.ThrowIfManagedType();
- var dataType = EnumUtil.TypeToDataType(typeof(T));
using var schema = _array.Schema();
using var domain = schema.Domain();
using var dimension = domain.Dimension(index);
- if (dimension.Type() != dataType)
- {
- ThrowHelpers.ThrowTypeMismatch(dataType);
- }
+ ErrorHandling.CheckDataType(dimension.Type());
}
///
diff --git a/sources/TileDB.CSharp/ThrowHelpers.cs b/sources/TileDB.CSharp/ThrowHelpers.cs
index bdfe9e96..13a14ad4 100644
--- a/sources/TileDB.CSharp/ThrowHelpers.cs
+++ b/sources/TileDB.CSharp/ThrowHelpers.cs
@@ -17,11 +17,11 @@ public static void ThrowTypeNotSupported() =>
// We don't have to specify the type in the type argument, it can be seen from the stacktrace.
[DoesNotReturn]
public static void ThrowTypeMismatch(DataType type) =>
- throw new InvalidOperationException($"Type is not compatible with data type {type}.");
+ throw new ArgumentException($"Type is not compatible with data type {type}.");
[DoesNotReturn]
public static void ThrowStringTypeMismatch(DataType type) =>
- throw new InvalidOperationException($"Cannot encode data type {type} into strings.");
+ throw new ArgumentException($"Cannot encode data type {type} into strings.");
[DoesNotReturn]
public static void ThrowTooBigSize(ulong size, [CallerArgumentExpression(nameof(size))] string? paramName = null) =>
diff --git a/sources/TileDB.CSharp/TileDB.CSharp.csproj b/sources/TileDB.CSharp/TileDB.CSharp.csproj
index 01330c29..ddc8d445 100644
--- a/sources/TileDB.CSharp/TileDB.CSharp.csproj
+++ b/sources/TileDB.CSharp/TileDB.CSharp.csproj
@@ -12,7 +12,7 @@
true
true
5.6.0
- $(NoWarn);TILEDB0012
+ $(NoWarn);TILEDB0012;TILEDB0013
diff --git a/tests/TileDB.CSharp.Test/FragmentInfoTest.cs b/tests/TileDB.CSharp.Test/FragmentInfoTest.cs
index 5c1ac9b3..a3787bfb 100644
--- a/tests/TileDB.CSharp.Test/FragmentInfoTest.cs
+++ b/tests/TileDB.CSharp.Test/FragmentInfoTest.cs
@@ -172,11 +172,11 @@ public void TestMinimumBoundedRectanglesString()
Assert.AreEqual(("a", "bb"), info.GetMinimumBoundedRectangle(0, 0, 0));
Assert.AreEqual(("c", "ddd"), info.GetMinimumBoundedRectangle(0, 1, "d"));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 1, "d"));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 1, "d"));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 1, "d"));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 1, "d"));
Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 1, "d"));
}
@@ -199,11 +199,11 @@ public void TestMinimumBoundedRectangles()
Assert.AreEqual((1, 2), info.GetMinimumBoundedRectangle(0, 0, 0));
Assert.AreEqual((7, 8), info.GetMinimumBoundedRectangle(1, 1, "d1"));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
}
@@ -226,11 +226,11 @@ public void TestMinimumBoundedRectanglesInt32()
Assert.AreEqual((1, 2), info.GetMinimumBoundedRectangle(0, 0, 0));
Assert.AreEqual((7, 8), info.GetMinimumBoundedRectangle(1, 1, "d1"));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(0, 0, 0));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
- Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
+ Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
Assert.ThrowsException(() => info.GetMinimumBoundedRectangle(1, 1, "d1"));
}
@@ -268,8 +268,8 @@ public void TestNonEmptyDomain()
(int Start, int End, _) => (Start, End)
};
Assert.AreEqual(expectedNonEmptyDomain, actualNonEmptyDomain);
- Assert.ThrowsException(() => info.GetNonEmptyDomain(i, dim));
- Assert.ThrowsException(() => info.GetNonEmptyDomain(i, dim));
+ Assert.ThrowsException(() => info.GetNonEmptyDomain(i, dim));
+ Assert.ThrowsException(() => info.GetNonEmptyDomain(i, dim));
Assert.ThrowsException(() => info.GetNonEmptyDomain(i, dim));
string name = d.Name();
@@ -279,8 +279,8 @@ public void TestNonEmptyDomain()
(int Start, int End, _) => (Start, End)
};
Assert.AreEqual(expectedNonEmptyDomain, actualNonEmptyDomain);
- Assert.ThrowsException(() => info.GetNonEmptyDomain(i, name));
- Assert.ThrowsException(() => info.GetNonEmptyDomain(i, name));
+ Assert.ThrowsException(() => info.GetNonEmptyDomain(i, name));
+ Assert.ThrowsException(() => info.GetNonEmptyDomain(i, name));
Assert.ThrowsException(() => info.GetNonEmptyDomain(i, name));
}
}
diff --git a/tests/TileDB.CSharp.Test/QueryTest.cs b/tests/TileDB.CSharp.Test/QueryTest.cs
index 92b2a6cf..288676aa 100644
--- a/tests/TileDB.CSharp.Test/QueryTest.cs
+++ b/tests/TileDB.CSharp.Test/QueryTest.cs
@@ -50,13 +50,13 @@ public void TestGlobalQuery(LayoutType layoutType, ArrayType arrayType)
{
using var subarray = new Subarray(array);
subarray.AddRange("rows", 1, 4);
- Assert.ThrowsException(() => subarray.AddRange("rows", 1, 4));
+ Assert.ThrowsException(() => subarray.AddRange("rows", 1, 4));
Assert.AreEqual((1, 4), subarray.GetRange("rows", 0));
- Assert.ThrowsException(() => subarray.GetRange("rows", 0));
+ Assert.ThrowsException(() => subarray.GetRange("rows", 0));
subarray.AddRange(1, 1, 2); // cols
- Assert.ThrowsException(() => subarray.AddRange(1, 1, 2));
+ Assert.ThrowsException(() => subarray.AddRange(1, 1, 2));
Assert.AreEqual((1, 2), subarray.GetRange(1, 0));
- Assert.ThrowsException(() => subarray.GetRange(1, 0));
+ Assert.ThrowsException(() => subarray.GetRange(1, 0));
queryWrite.SetSubarray(subarray);
queryWrite.SetDataReadOnlyBuffer("a1", new[] { 1, 2, 3, 4, 5, 6, 7, 8 }.AsMemory());
}
@@ -181,8 +181,8 @@ public void TestDenseQuery()
using (var subarray = new Subarray(array))
{
subarray.SetSubarray(0, 1);
- Assert.ThrowsException(() => subarray.SetSubarray(0, 1));
- Assert.ThrowsException(() => subarray.SetSubarray(0));
+ Assert.ThrowsException(() => subarray.SetSubarray(0, 1));
+ Assert.ThrowsException(() => subarray.SetSubarray(0));
query.SetSubarray(subarray);
}