Skip to content

Commit b0dc132

Browse files
YdbValue.Null -> Optional<?>(Null) (#179)
1 parent 61b7f11 commit b0dc132

File tree

6 files changed

+295
-157
lines changed

6 files changed

+295
-157
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
- Fixed bug: parameter type mismatch, when setting optional with null
2+
13
## v0.6.2
24
- Fixed bug: adding correct placeholders to all logging calls with parameters
35

src/Ydb.Sdk/src/Ado/YdbParameter.cs

Lines changed: 105 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,38 @@
33
using System.Data.Common;
44
using System.Diagnostics.CodeAnalysis;
55
using Ydb.Sdk.Value;
6-
using static System.String;
76

87
namespace Ydb.Sdk.Ado;
98

109
public sealed class YdbParameter : DbParameter
1110
{
12-
private string _parameterName = Empty;
11+
private static readonly Dictionary<DbType, YdbValue> YdbNullByDbType = new()
12+
{
13+
{ DbType.String, YdbValue.MakeOptionalUtf8() },
14+
{ DbType.AnsiString, YdbValue.MakeOptionalUtf8() },
15+
{ DbType.AnsiStringFixedLength, YdbValue.MakeOptionalUtf8() },
16+
{ DbType.StringFixedLength, YdbValue.MakeOptionalUtf8() },
17+
{ DbType.Int32, YdbValue.MakeOptionalInt32() },
18+
{ DbType.Int64, YdbValue.MakeOptionalInt64() },
19+
{ DbType.Boolean, YdbValue.MakeOptionalBool() },
20+
{ DbType.UInt32, YdbValue.MakeOptionalUint32() },
21+
{ DbType.UInt64, YdbValue.MakeOptionalUint64() },
22+
{ DbType.SByte, YdbValue.MakeOptionalInt8() },
23+
{ DbType.Int16, YdbValue.MakeOptionalInt16() },
24+
{ DbType.UInt16, YdbValue.MakeOptionalUint16() },
25+
{ DbType.Double, YdbValue.MakeOptionalDouble() },
26+
{ DbType.Single, YdbValue.MakeOptionalFloat() },
27+
{ DbType.Date, YdbValue.MakeOptionalDate() },
28+
{ DbType.DateTime, YdbValue.MakeOptionalDatetime() },
29+
{ DbType.Binary, YdbValue.MakeOptionalString() },
30+
{ DbType.Byte, YdbValue.MakeOptionalUint8() },
31+
{ DbType.DateTime2, YdbValue.MakeOptionalTimestamp() },
32+
{ DbType.DateTimeOffset, YdbValue.MakeOptionalTimestamp() },
33+
{ DbType.Decimal, YdbValue.MakeOptionalDecimal() },
34+
{ DbType.Currency, YdbValue.MakeOptionalDecimal() }
35+
};
36+
37+
private string _parameterName = string.Empty;
1338

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

49-
[AllowNull] [DefaultValue("")] public override string SourceColumn { get; set; } = Empty;
74+
[AllowNull] [DefaultValue("")] public override string SourceColumn { get; set; } = string.Empty;
5075
public override object? Value { get; set; }
5176
public override bool SourceColumnNullMapping { get; set; }
5277
public override int Size { get; set; }
@@ -55,44 +80,84 @@ internal YdbValue YdbValue
5580
{
5681
get
5782
{
58-
if (Value is YdbValue ydbValue)
83+
return Value switch
5984
{
60-
return ydbValue;
61-
}
62-
63-
return DbType switch
64-
{
65-
DbType.Object when Value is not null => PrepareThenReturnYdbValue(),
66-
DbType.String or DbType.AnsiString or DbType.AnsiStringFixedLength or DbType.StringFixedLength when
67-
Value is string valueString => YdbValue.MakeUtf8(valueString),
68-
DbType.Int32 when Value is int or sbyte or byte or short or ushort =>
69-
YdbValue.MakeInt32(Convert.ToInt32(Value)),
70-
DbType.Int64 when Value is long or sbyte or byte or short or ushort or int or uint =>
71-
YdbValue.MakeInt64(Convert.ToInt64(Value)),
72-
DbType.Boolean when Value is bool boolValue => YdbValue.MakeBool(boolValue),
73-
DbType.UInt32 when Value is uint or byte or ushort => YdbValue.MakeUint32(Convert.ToUInt32(Value)),
74-
DbType.UInt64
75-
when Value is ulong or byte or ushort or uint => YdbValue.MakeUint64(Convert.ToUInt64(Value)),
76-
DbType.SByte when Value is sbyte sbyteValue => YdbValue.MakeInt8(sbyteValue),
77-
DbType.Int16 when Value is short or sbyte or byte => YdbValue.MakeInt16(Convert.ToInt16(Value)),
78-
DbType.UInt16 when Value is ushort or byte => YdbValue.MakeUint16(Convert.ToUInt16(Value)),
79-
DbType.Double when Value is double or float => YdbValue.MakeDouble(Convert.ToDouble(Value)),
80-
DbType.Single when Value is float floatValue => YdbValue.MakeFloat(floatValue),
81-
DbType.Date when Value is DateTime dateTimeValue => YdbValue.MakeDate(dateTimeValue),
82-
DbType.Time or DbType.DateTime
83-
when Value is DateTime dateTimeValue => YdbValue.MakeDatetime(dateTimeValue),
84-
DbType.DateTime2 when Value is DateTime dateTime => YdbValue.MakeTimestamp(dateTime),
85-
DbType.DateTimeOffset when Value is DateTimeOffset dateTimeOffset =>
85+
YdbValue ydbValue => ydbValue,
86+
null or DBNull when YdbNullByDbType.TryGetValue(DbType, out var value) => value,
87+
string valueString when DbType is DbType.String or DbType.AnsiString or DbType.AnsiStringFixedLength
88+
or DbType.StringFixedLength or DbType.Object => YdbValue.MakeUtf8(valueString),
89+
bool boolValue when DbType is DbType.Boolean or DbType.Object => YdbValue.MakeBool(boolValue),
90+
DateTime dateTimeValue => DbType switch
91+
{
92+
DbType.Date => YdbValue.MakeDate(dateTimeValue),
93+
DbType.DateTime => YdbValue.MakeDatetime(dateTimeValue),
94+
DbType.DateTime2 or DbType.Object => YdbValue.MakeTimestamp(dateTimeValue),
95+
_ => ThrowInvalidCast()
96+
},
97+
DateTimeOffset dateTimeOffset when DbType is DbType.DateTimeOffset or DbType.Object =>
8698
YdbValue.MakeTimestamp(dateTimeOffset.UtcDateTime),
87-
DbType.Decimal or DbType.Currency
88-
when Value is decimal decimalValue => YdbValue.MakeDecimal(decimalValue),
89-
DbType.Binary when Value is byte[] bytes => YdbValue.MakeString(bytes),
90-
DbType.Byte when Value is byte valueByte => YdbValue.MakeUint8(valueByte),
91-
DbType.VarNumeric or DbType.Xml or DbType.Guid => throw new YdbException(
92-
$"Ydb don't supported this DbType: {DbType}"),
93-
_ when !Enum.IsDefined(typeof(DbType), DbType) =>
94-
throw new ArgumentOutOfRangeException(nameof(DbType), DbType, null),
95-
_ when Value is null => YdbValue.Null,
99+
float floatValue => DbType switch
100+
{
101+
DbType.Single or DbType.Object => YdbValue.MakeFloat(floatValue),
102+
DbType.Double => YdbValue.MakeDouble(floatValue),
103+
_ => ThrowInvalidCast()
104+
},
105+
double doubleValue when DbType is DbType.Double or DbType.Object => YdbValue.MakeDouble(doubleValue),
106+
int intValue => DbType switch
107+
{
108+
DbType.Int32 or DbType.Object => YdbValue.MakeInt32(intValue),
109+
DbType.Int64 => YdbValue.MakeInt64(intValue),
110+
_ => ThrowInvalidCast()
111+
},
112+
long longValue when DbType is DbType.Int64 or DbType.Object => YdbValue.MakeInt64(longValue),
113+
decimal decimalValue when DbType is DbType.Decimal or DbType.Currency or DbType.Object =>
114+
YdbValue.MakeDecimal(decimalValue),
115+
ulong ulongValue when DbType is DbType.UInt64 or DbType.Object => YdbValue.MakeUint64(ulongValue),
116+
uint uintValue => DbType switch
117+
{
118+
DbType.UInt32 or DbType.Object => YdbValue.MakeUint32(uintValue),
119+
DbType.UInt64 => YdbValue.MakeUint64(uintValue),
120+
DbType.Int64 => YdbValue.MakeInt64(uintValue),
121+
_ => ThrowInvalidCast()
122+
},
123+
byte byteValue => DbType switch
124+
{
125+
DbType.Byte or DbType.Object => YdbValue.MakeUint8(byteValue),
126+
DbType.Int64 => YdbValue.MakeInt64(byteValue),
127+
DbType.Int32 => YdbValue.MakeInt32(byteValue),
128+
DbType.Int16 => YdbValue.MakeInt16(byteValue),
129+
DbType.UInt64 => YdbValue.MakeUint64(byteValue),
130+
DbType.UInt32 => YdbValue.MakeUint32(byteValue),
131+
DbType.UInt16 => YdbValue.MakeUint16(byteValue),
132+
_ => ThrowInvalidCast()
133+
},
134+
sbyte sbyteValue => DbType switch
135+
{
136+
DbType.SByte or DbType.Object => YdbValue.MakeInt8(sbyteValue),
137+
DbType.Int64 => YdbValue.MakeInt64(sbyteValue),
138+
DbType.Int32 => YdbValue.MakeInt32(sbyteValue),
139+
DbType.Int16 => YdbValue.MakeInt16(sbyteValue),
140+
_ => ThrowInvalidCast()
141+
},
142+
ushort ushortValue => DbType switch
143+
{
144+
DbType.UInt16 or DbType.Object => YdbValue.MakeUint16(ushortValue),
145+
DbType.Int64 => YdbValue.MakeInt64(ushortValue),
146+
DbType.Int32 => YdbValue.MakeInt32(ushortValue),
147+
DbType.UInt64 => YdbValue.MakeUint64(ushortValue),
148+
DbType.UInt32 => YdbValue.MakeUint32(ushortValue),
149+
_ => ThrowInvalidCast()
150+
},
151+
short shortValue => DbType switch
152+
{
153+
DbType.Int16 or DbType.Object => YdbValue.MakeInt16(shortValue),
154+
DbType.Int64 => YdbValue.MakeInt64(shortValue),
155+
DbType.Int32 => YdbValue.MakeInt32(shortValue),
156+
_ => ThrowInvalidCast()
157+
},
158+
byte[] bytesValue when DbType is DbType.Binary or DbType.Object => YdbValue.MakeString(bytesValue),
159+
_ when DbType is DbType.VarNumeric or DbType.Xml or DbType.Guid or DbType.Time =>
160+
throw new YdbException($"Ydb don't supported this DbType: {DbType}"),
96161
_ => ThrowInvalidCast()
97162
};
98163
}
@@ -101,34 +166,6 @@ DbType.Decimal or DbType.Currency
101166
private YdbValue ThrowInvalidCast()
102167
{
103168
throw new InvalidCastException(
104-
$"Writing values of '{Value?.GetType()}' is not supported for parameters having DbType '{DbType}'");
105-
}
106-
107-
private YdbValue PrepareThenReturnYdbValue()
108-
{
109-
DbType = Value switch
110-
{
111-
string => DbType.String,
112-
int => DbType.Int32,
113-
uint => DbType.UInt32,
114-
long => DbType.Int64,
115-
ulong => DbType.UInt64,
116-
bool => DbType.Boolean,
117-
byte => DbType.Byte,
118-
sbyte => DbType.SByte,
119-
float => DbType.Single,
120-
double => DbType.Double,
121-
short => DbType.Int16,
122-
ushort => DbType.UInt16,
123-
decimal => DbType.Decimal,
124-
byte[] => DbType.Binary,
125-
Guid => DbType.Guid,
126-
DateTime => DbType.DateTime,
127-
DateTimeOffset => DbType.DateTimeOffset,
128-
_ => throw new YdbException($"Error converting {Value?.GetType().ToString() ?? "null"} to YdbValue")
129-
};
130-
IsNullable = false;
131-
132-
return YdbValue;
169+
$"Writing value of '{Value?.GetType().ToString() ?? "null"}' is not supported for parameters having DbType '{DbType}'");
133170
}
134171
}

0 commit comments

Comments
 (0)