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

YdbValue.Null -> Optional<?>(Null) #179

Merged
merged 8 commits into from
Sep 5, 2024
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- Fixed bug: parameter type mismatch, when setting optional with null

## v0.6.2
- Fixed bug: adding correct placeholders to all logging calls with parameters

Expand Down
173 changes: 105 additions & 68 deletions src/Ydb.Sdk/src/Ado/YdbParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,38 @@
using System.Data.Common;
using System.Diagnostics.CodeAnalysis;
using Ydb.Sdk.Value;
using static System.String;

namespace Ydb.Sdk.Ado;

public sealed class YdbParameter : DbParameter
{
private string _parameterName = Empty;
private static readonly Dictionary<DbType, YdbValue> YdbNullByDbType = new()
{
{ DbType.String, YdbValue.MakeOptionalUtf8() },
{ DbType.AnsiString, YdbValue.MakeOptionalUtf8() },
{ DbType.AnsiStringFixedLength, YdbValue.MakeOptionalUtf8() },
{ DbType.StringFixedLength, YdbValue.MakeOptionalUtf8() },
{ DbType.Int32, YdbValue.MakeOptionalInt32() },
{ DbType.Int64, YdbValue.MakeOptionalInt64() },
{ DbType.Boolean, YdbValue.MakeOptionalBool() },
{ DbType.UInt32, YdbValue.MakeOptionalUint32() },
{ DbType.UInt64, YdbValue.MakeOptionalUint64() },
{ DbType.SByte, YdbValue.MakeOptionalInt8() },
{ DbType.Int16, YdbValue.MakeOptionalInt16() },
{ DbType.UInt16, YdbValue.MakeOptionalUint16() },
{ DbType.Double, YdbValue.MakeOptionalDouble() },
{ DbType.Single, YdbValue.MakeOptionalFloat() },
{ DbType.Date, YdbValue.MakeOptionalDate() },
{ DbType.DateTime, YdbValue.MakeOptionalDatetime() },
{ DbType.Binary, YdbValue.MakeOptionalString() },
{ DbType.Byte, YdbValue.MakeOptionalUint8() },
{ DbType.DateTime2, YdbValue.MakeOptionalTimestamp() },
{ DbType.DateTimeOffset, YdbValue.MakeOptionalTimestamp() },
{ DbType.Decimal, YdbValue.MakeOptionalDecimal() },
{ DbType.Currency, YdbValue.MakeOptionalDecimal() }
};

private string _parameterName = string.Empty;

public YdbParameter()
{
Expand Down Expand Up @@ -46,7 +71,7 @@ public override string ParameterName
set => _parameterName = value ?? throw new YdbException("ParameterName must not be null!");
}

[AllowNull] [DefaultValue("")] public override string SourceColumn { get; set; } = Empty;
[AllowNull] [DefaultValue("")] public override string SourceColumn { get; set; } = string.Empty;
public override object? Value { get; set; }
public override bool SourceColumnNullMapping { get; set; }
public override int Size { get; set; }
Expand All @@ -55,44 +80,84 @@ internal YdbValue YdbValue
{
get
{
if (Value is YdbValue ydbValue)
return Value switch
{
return ydbValue;
}

return DbType switch
{
DbType.Object when Value is not null => PrepareThenReturnYdbValue(),
DbType.String or DbType.AnsiString or DbType.AnsiStringFixedLength or DbType.StringFixedLength when
Value is string valueString => YdbValue.MakeUtf8(valueString),
DbType.Int32 when Value is int or sbyte or byte or short or ushort =>
YdbValue.MakeInt32(Convert.ToInt32(Value)),
DbType.Int64 when Value is long or sbyte or byte or short or ushort or int or uint =>
YdbValue.MakeInt64(Convert.ToInt64(Value)),
DbType.Boolean when Value is bool boolValue => YdbValue.MakeBool(boolValue),
DbType.UInt32 when Value is uint or byte or ushort => YdbValue.MakeUint32(Convert.ToUInt32(Value)),
DbType.UInt64
when Value is ulong or byte or ushort or uint => YdbValue.MakeUint64(Convert.ToUInt64(Value)),
DbType.SByte when Value is sbyte sbyteValue => YdbValue.MakeInt8(sbyteValue),
DbType.Int16 when Value is short or sbyte or byte => YdbValue.MakeInt16(Convert.ToInt16(Value)),
DbType.UInt16 when Value is ushort or byte => YdbValue.MakeUint16(Convert.ToUInt16(Value)),
DbType.Double when Value is double or float => YdbValue.MakeDouble(Convert.ToDouble(Value)),
DbType.Single when Value is float floatValue => YdbValue.MakeFloat(floatValue),
DbType.Date when Value is DateTime dateTimeValue => YdbValue.MakeDate(dateTimeValue),
DbType.Time or DbType.DateTime
when Value is DateTime dateTimeValue => YdbValue.MakeDatetime(dateTimeValue),
DbType.DateTime2 when Value is DateTime dateTime => YdbValue.MakeTimestamp(dateTime),
DbType.DateTimeOffset when Value is DateTimeOffset dateTimeOffset =>
YdbValue ydbValue => ydbValue,
null or DBNull when YdbNullByDbType.TryGetValue(DbType, out var value) => value,
string valueString when DbType is DbType.String or DbType.AnsiString or DbType.AnsiStringFixedLength
or DbType.StringFixedLength or DbType.Object => YdbValue.MakeUtf8(valueString),
bool boolValue when DbType is DbType.Boolean or DbType.Object => YdbValue.MakeBool(boolValue),
DateTime dateTimeValue => DbType switch
{
DbType.Date => YdbValue.MakeDate(dateTimeValue),
DbType.DateTime => YdbValue.MakeDatetime(dateTimeValue),
DbType.DateTime2 or DbType.Object => YdbValue.MakeTimestamp(dateTimeValue),
_ => ThrowInvalidCast()
},
DateTimeOffset dateTimeOffset when DbType is DbType.DateTimeOffset or DbType.Object =>
YdbValue.MakeTimestamp(dateTimeOffset.UtcDateTime),
DbType.Decimal or DbType.Currency
when Value is decimal decimalValue => YdbValue.MakeDecimal(decimalValue),
DbType.Binary when Value is byte[] bytes => YdbValue.MakeString(bytes),
DbType.Byte when Value is byte valueByte => YdbValue.MakeUint8(valueByte),
DbType.VarNumeric or DbType.Xml or DbType.Guid => throw new YdbException(
$"Ydb don't supported this DbType: {DbType}"),
_ when !Enum.IsDefined(typeof(DbType), DbType) =>
throw new ArgumentOutOfRangeException(nameof(DbType), DbType, null),
_ when Value is null => YdbValue.Null,
float floatValue => DbType switch
{
DbType.Single or DbType.Object => YdbValue.MakeFloat(floatValue),
DbType.Double => YdbValue.MakeDouble(floatValue),
_ => ThrowInvalidCast()
},
double doubleValue when DbType is DbType.Double or DbType.Object => YdbValue.MakeDouble(doubleValue),
int intValue => DbType switch
{
DbType.Int32 or DbType.Object => YdbValue.MakeInt32(intValue),
DbType.Int64 => YdbValue.MakeInt64(intValue),
_ => ThrowInvalidCast()
},
long longValue when DbType is DbType.Int64 or DbType.Object => YdbValue.MakeInt64(longValue),
decimal decimalValue when DbType is DbType.Decimal or DbType.Currency or DbType.Object =>
YdbValue.MakeDecimal(decimalValue),
ulong ulongValue when DbType is DbType.UInt64 or DbType.Object => YdbValue.MakeUint64(ulongValue),
uint uintValue => DbType switch
{
DbType.UInt32 or DbType.Object => YdbValue.MakeUint32(uintValue),
DbType.UInt64 => YdbValue.MakeUint64(uintValue),
DbType.Int64 => YdbValue.MakeInt64(uintValue),
_ => ThrowInvalidCast()
},
byte byteValue => DbType switch
{
DbType.Byte or DbType.Object => YdbValue.MakeUint8(byteValue),
DbType.Int64 => YdbValue.MakeInt64(byteValue),
DbType.Int32 => YdbValue.MakeInt32(byteValue),
DbType.Int16 => YdbValue.MakeInt16(byteValue),
DbType.UInt64 => YdbValue.MakeUint64(byteValue),
DbType.UInt32 => YdbValue.MakeUint32(byteValue),
DbType.UInt16 => YdbValue.MakeUint16(byteValue),
_ => ThrowInvalidCast()
},
sbyte sbyteValue => DbType switch
{
DbType.SByte or DbType.Object => YdbValue.MakeInt8(sbyteValue),
DbType.Int64 => YdbValue.MakeInt64(sbyteValue),
DbType.Int32 => YdbValue.MakeInt32(sbyteValue),
DbType.Int16 => YdbValue.MakeInt16(sbyteValue),
_ => ThrowInvalidCast()
},
ushort ushortValue => DbType switch
{
DbType.UInt16 or DbType.Object => YdbValue.MakeUint16(ushortValue),
DbType.Int64 => YdbValue.MakeInt64(ushortValue),
DbType.Int32 => YdbValue.MakeInt32(ushortValue),
DbType.UInt64 => YdbValue.MakeUint64(ushortValue),
DbType.UInt32 => YdbValue.MakeUint32(ushortValue),
_ => ThrowInvalidCast()
},
short shortValue => DbType switch
{
DbType.Int16 or DbType.Object => YdbValue.MakeInt16(shortValue),
DbType.Int64 => YdbValue.MakeInt64(shortValue),
DbType.Int32 => YdbValue.MakeInt32(shortValue),
_ => ThrowInvalidCast()
},
byte[] bytesValue when DbType is DbType.Binary or DbType.Object => YdbValue.MakeString(bytesValue),
_ when DbType is DbType.VarNumeric or DbType.Xml or DbType.Guid or DbType.Time =>
throw new YdbException($"Ydb don't supported this DbType: {DbType}"),
_ => ThrowInvalidCast()
};
}
Expand All @@ -101,34 +166,6 @@ DbType.Decimal or DbType.Currency
private YdbValue ThrowInvalidCast()
{
throw new InvalidCastException(
$"Writing values of '{Value?.GetType()}' is not supported for parameters having DbType '{DbType}'");
}

private YdbValue PrepareThenReturnYdbValue()
{
DbType = Value switch
{
string => DbType.String,
int => DbType.Int32,
uint => DbType.UInt32,
long => DbType.Int64,
ulong => DbType.UInt64,
bool => DbType.Boolean,
byte => DbType.Byte,
sbyte => DbType.SByte,
float => DbType.Single,
double => DbType.Double,
short => DbType.Int16,
ushort => DbType.UInt16,
decimal => DbType.Decimal,
byte[] => DbType.Binary,
Guid => DbType.Guid,
DateTime => DbType.DateTime,
DateTimeOffset => DbType.DateTimeOffset,
_ => throw new YdbException($"Error converting {Value?.GetType().ToString() ?? "null"} to YdbValue")
};
IsNullable = false;

return YdbValue;
$"Writing value of '{Value?.GetType().ToString() ?? "null"}' is not supported for parameters having DbType '{DbType}'");
}
}
Loading
Loading