Skip to content

Commit a989949

Browse files
committed
feat: implement comprehensive data type support for RPC parameters
1 parent e690ef0 commit a989949

4 files changed

Lines changed: 86 additions & 5 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
<Authors>vkuttyp</Authors>
88
<PackageLicenseExpression>MIT</PackageLicenseExpression>
99
<RepositoryUrl>https://github.com/vkuttyp/CosmoSQLClient-Dotnet</RepositoryUrl>
10-
<Version>1.9.6</Version>
10+
<Version>1.9.7</Version>
1111
</PropertyGroup>
1212
</Project>

src/CosmoSQLClient.Core/SqlValue.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ public sealed record Date(DateTime Value) : SqlValue;
4141
private static SqlValue FromBoxed(object v) => v switch
4242
{
4343
bool b => From(b),
44-
sbyte b => From(b),
45-
short s => From(s),
44+
byte b => From((int)b),
45+
sbyte b => From((int)b),
46+
ushort s => From((int)s),
47+
short s => From((int)s),
4648
int i => From(i),
4749
long l => From(l),
4850
float f => From(f),

src/CosmoSQLClient.MsSql/MsSqlConnection.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,8 @@ private static string BuildParamDeclarations(IReadOnlyList<SqlParameter> paramet
500500
private static string SqlValueToTypeName(SqlValue v) => v switch {
501501
SqlValue.Bool => "BIT", SqlValue.Int32 => "INT", SqlValue.Int64 => "BIGINT",
502502
SqlValue.Float => "REAL", SqlValue.Double => "FLOAT", SqlValue.Decimal => "DECIMAL(38,10)",
503-
SqlValue.Date => "DATETIME", SqlValue.Uuid => "UNIQUEIDENTIFIER", _ => "NVARCHAR(MAX)"
503+
SqlValue.Date => "DATETIME", SqlValue.Uuid => "UNIQUEIDENTIFIER", SqlValue.Bytes => "VARBINARY(MAX)",
504+
_ => "NVARCHAR(MAX)"
504505
};
505506

506507
private static void WriteAllHeaders(BinaryWriter bw, long tx) {
@@ -561,9 +562,15 @@ private static void WriteNamedParam(BinaryWriter bw, string name, SqlValue value
561562
break;
562563
case SqlValue.Uuid v:
563564
bw.Write((byte)0x24); // UNIQUEIDENTIFIER
564-
bw.Write((byte)0x10); // length
565+
bw.Write((byte)0x10); // Max length
566+
bw.Write((byte)0x10); // Actual data length
565567
bw.Write(v.Value.ToByteArray());
566568
break;
569+
case SqlValue.Bytes v:
570+
bw.Write((byte)0xA5); // VARBINARY
571+
bw.Write((ushort)0xFFFF); // Max length (PLP)
572+
WritePlpBytes(bw, v.Value);
573+
break;
567574
default:
568575
WriteNvarcharMaxTypeAndValue(bw, value.AsString());
569576
break;
@@ -579,4 +586,11 @@ private static void WriteNvarcharMaxTypeAndValue(BinaryWriter bw, string? s) {
579586
bw.Write((ulong)b.Length); bw.Write((uint)b.Length); bw.Write(b); bw.Write((uint)0);
580587
}
581588
}
589+
590+
private static void WritePlpBytes(BinaryWriter bw, byte[]? b) {
591+
if (b == null) bw.Write(ulong.MaxValue);
592+
else {
593+
bw.Write((ulong)b.Length); bw.Write((uint)b.Length); bw.Write(b); bw.Write((uint)0);
594+
}
595+
}
582596
}

tests/CosmoSQLClient.MsSql.Tests/AdoNetTests.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,71 @@ public async Task StandardAdoNet_DateTimeParameter_ShouldWork()
147147
Assert.Equal(now, (DateTime)result!);
148148
}
149149

150+
[Fact]
151+
public async Task StandardAdoNet_AllDataTypes_ShouldWork()
152+
{
153+
if (ShouldSkip) return;
154+
155+
using var conn = new MsSqlConnection(ConnectionString);
156+
await conn.OpenAsync();
157+
158+
using var cmd = conn.CreateCommand();
159+
cmd.CommandText = @"
160+
SELECT
161+
@p_bool AS v_bool,
162+
@p_byte AS v_byte,
163+
@p_short AS v_short,
164+
@p_int AS v_int,
165+
@p_long AS v_long,
166+
@p_float AS v_float,
167+
@p_double AS v_double,
168+
@p_decimal AS v_decimal,
169+
@p_string AS v_string,
170+
@p_guid AS v_guid,
171+
@p_date AS v_date,
172+
@p_bin AS v_bin,
173+
@p_null AS v_null";
174+
175+
var guid = Guid.NewGuid();
176+
var date = new DateTime(2023, 12, 25, 10, 30, 0);
177+
var bin = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF };
178+
179+
cmd.Parameters.AddWithValue("p_bool", true);
180+
cmd.Parameters.AddWithValue("p_byte", (byte)255);
181+
cmd.Parameters.AddWithValue("p_short", (short)32767);
182+
cmd.Parameters.AddWithValue("p_int", 123456789);
183+
cmd.Parameters.AddWithValue("p_long", 9876543210L);
184+
cmd.Parameters.AddWithValue("p_float", 1.23f);
185+
cmd.Parameters.AddWithValue("p_double", 4.5678);
186+
cmd.Parameters.AddWithValue("p_decimal", 12345.6789m);
187+
cmd.Parameters.AddWithValue("p_string", "Hello Comprehensive Test");
188+
cmd.Parameters.AddWithValue("p_guid", guid);
189+
cmd.Parameters.AddWithValue("p_date", date);
190+
cmd.Parameters.AddWithValue("p_bin", bin);
191+
cmd.Parameters.AddWithValue("p_null", DBNull.Value);
192+
193+
using var reader = await cmd.ExecuteReaderAsync();
194+
Assert.True(await reader.ReadAsync());
195+
196+
Assert.True(reader.GetBoolean(0));
197+
Assert.Equal(255, reader.GetInt32(1));
198+
Assert.Equal((short)32767, reader.GetInt16(2));
199+
Assert.Equal(123456789, reader.GetInt32(3));
200+
Assert.Equal(9876543210L, reader.GetInt64(4));
201+
Assert.Equal(1.23f, reader.GetFloat(5));
202+
Assert.Equal(4.5678, reader.GetDouble(6));
203+
Assert.Equal(12345.6789m, reader.GetDecimal(7));
204+
Assert.Equal("Hello Comprehensive Test", reader.GetString(8));
205+
Assert.Equal(guid, reader.GetGuid(9));
206+
Assert.Equal(date, reader.GetDateTime(10));
207+
208+
var actualBin = new byte[4];
209+
reader.GetBytes(11, 0, actualBin, 0, 4);
210+
Assert.Equal(bin, actualBin);
211+
212+
Assert.True(await reader.IsDBNullAsync(12));
213+
}
214+
150215
[Fact]
151216
public async Task StandardAdoNet_Transactions_ShouldWork()
152217
{

0 commit comments

Comments
 (0)