Skip to content

Commit ac0860f

Browse files
SNOW-979288: Add explicit DbType Parameter assignment (#889)
### Description Add explicit DbType Parameter assignment ### Checklist - [ ] Code compiles correctly - [ ] Code is formatted according to [Coding Conventions](../CodingConventions.md) - [ ] Created tests which fail without the change (if possible) - [ ] All tests passing (`dotnet test`) - [ ] Extended the README / documentation, if necessary - [ ] Provide JIRA issue id (if possible) or GitHub issue id in PR name
1 parent 0303514 commit ac0860f

File tree

4 files changed

+203
-1
lines changed

4 files changed

+203
-1
lines changed

Snowflake.Data.Tests/IntegrationTests/SFBindTestIT.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,5 +769,69 @@ public void testPutArrayBind1()
769769
conn.Close();
770770
}
771771
}
772+
773+
[Test]
774+
public void testExplicitDbTypeAssignmentForSimpleValue()
775+
{
776+
777+
using (IDbConnection conn = new SnowflakeDbConnection())
778+
{
779+
conn.ConnectionString = ConnectionString;
780+
conn.Open();
781+
782+
CreateOrReplaceTable(conn, TableName, new[]
783+
{
784+
"cola INTEGER",
785+
});
786+
787+
using (IDbCommand cmd = conn.CreateCommand())
788+
{
789+
string insertCommand = $"insert into {TableName} values (?)";
790+
cmd.CommandText = insertCommand;
791+
792+
var p1 = cmd.CreateParameter();
793+
p1.ParameterName = "1";
794+
p1.Value = 1;
795+
cmd.Parameters.Add(p1);
796+
797+
var count = cmd.ExecuteNonQuery();
798+
Assert.AreEqual(1, count);
799+
}
800+
801+
conn.Close();
802+
}
803+
}
804+
805+
[Test]
806+
public void testExplicitDbTypeAssignmentForArrayValue()
807+
{
808+
809+
using (IDbConnection conn = new SnowflakeDbConnection())
810+
{
811+
conn.ConnectionString = ConnectionString;
812+
conn.Open();
813+
814+
CreateOrReplaceTable(conn, TableName, new[]
815+
{
816+
"cola INTEGER",
817+
});
818+
819+
using (IDbCommand cmd = conn.CreateCommand())
820+
{
821+
string insertCommand = $"insert into {TableName} values (?)";
822+
cmd.CommandText = insertCommand;
823+
824+
var p1 = cmd.CreateParameter();
825+
p1.ParameterName = "1";
826+
p1.Value = new int[] { 1, 2, 3 };
827+
cmd.Parameters.Add(p1);
828+
829+
var count = cmd.ExecuteNonQuery();
830+
Assert.AreEqual(3, count);
831+
}
832+
833+
conn.Close();
834+
}
835+
}
772836
}
773837
}

Snowflake.Data.Tests/UnitTests/SFDbParameterTest.cs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ namespace Snowflake.Data.Tests
77
using NUnit.Framework;
88
using Snowflake.Data.Client;
99
using Snowflake.Data.Core;
10+
using System;
1011
using System.Data;
12+
using System.Text;
1113

1214
[TestFixture]
1315
class SFDbParameterTest
@@ -125,5 +127,93 @@ public void TestDbParameterResetDbType([Values] SFDataType expectedSFDataType)
125127
_parameter.ResetDbType();
126128
Assert.AreEqual(SFDataType.None, _parameter.SFDataType);
127129
}
130+
131+
[Test]
132+
public void TestDbTypeExplicitAssignment([Values] DbType expectedDbType)
133+
{
134+
_parameter = new SnowflakeDbParameter();
135+
136+
switch (expectedDbType)
137+
{
138+
case DbType.SByte:
139+
_parameter.Value = new sbyte();
140+
break;
141+
case DbType.Byte:
142+
_parameter.Value = new byte();
143+
break;
144+
case DbType.Int16:
145+
_parameter.Value = new short();
146+
break;
147+
case DbType.Int32:
148+
_parameter.Value = new int();
149+
break;
150+
case DbType.Int64:
151+
_parameter.Value = new long();
152+
break;
153+
case DbType.UInt16:
154+
_parameter.Value = new ushort();
155+
break;
156+
case DbType.UInt32:
157+
_parameter.Value = new uint();
158+
break;
159+
case DbType.UInt64:
160+
_parameter.Value = new ulong();
161+
break;
162+
case DbType.Decimal:
163+
_parameter.Value = new decimal();
164+
break;
165+
case DbType.Boolean:
166+
_parameter.Value = true;
167+
break;
168+
case DbType.Single:
169+
_parameter.Value = new float();
170+
break;
171+
case DbType.Double:
172+
_parameter.Value = new double();
173+
break;
174+
case DbType.Guid:
175+
_parameter.Value = new Guid();
176+
break;
177+
case DbType.String:
178+
_parameter.Value = "thisIsAString";
179+
break;
180+
case DbType.DateTime:
181+
_parameter.Value = DateTime.Now;
182+
break;
183+
case DbType.DateTimeOffset:
184+
_parameter.Value = DateTimeOffset.Now;
185+
break;
186+
case DbType.Binary:
187+
_parameter.Value = Encoding.UTF8.GetBytes("BinaryData");
188+
break;
189+
case DbType.Object:
190+
_parameter.Value = new object();
191+
break;
192+
default:
193+
// Not supported
194+
expectedDbType = default(DbType);
195+
break;
196+
}
197+
198+
Assert.AreEqual(expectedDbType, _parameter.DbType);
199+
}
200+
201+
[Test]
202+
public void TestDbTypeExplicitAssignmentWithNullValueAndDefaultDbType()
203+
{
204+
_parameter = new SnowflakeDbParameter();
205+
_parameter.Value = null;
206+
Assert.AreEqual(default(DbType), _parameter.DbType);
207+
}
208+
209+
[Test]
210+
public void TestDbTypeExplicitAssignmentWithNullValueAndNonDefaultDbType()
211+
{
212+
var nonDefaultDbType = DbType.String;
213+
_parameter = new SnowflakeDbParameter();
214+
_parameter.Value = null;
215+
_parameter.DbType = nonDefaultDbType;
216+
Assert.AreEqual(nonDefaultDbType, _parameter.DbType);
217+
}
128218
}
129219
}

Snowflake.Data/Client/SnowflakeDbParameter.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public class SnowflakeDbParameter : DbParameter
1515

1616
private SFDataType OriginType;
1717

18+
private DbType _dbType;
19+
1820
public SnowflakeDbParameter()
1921
{
2022
SFDataType = SFDataType.None;
@@ -34,7 +36,28 @@ public SnowflakeDbParameter(int ParameterIndex, SFDataType SFDataType)
3436
this.SFDataType = SFDataType;
3537
}
3638

37-
public override DbType DbType { get; set; }
39+
public override DbType DbType
40+
{
41+
get
42+
{
43+
if (_dbType != default(DbType) || Value == null || Value is DBNull)
44+
{
45+
return _dbType;
46+
}
47+
48+
var type = Value.GetType();
49+
if (type.IsArray && type != typeof(byte[]))
50+
{
51+
return SFDataConverter.TypeToDbTypeMap[type.GetElementType()];
52+
}
53+
else
54+
{
55+
return SFDataConverter.TypeToDbTypeMap[type];
56+
}
57+
}
58+
59+
set => _dbType = value;
60+
}
3861

3962
public override ParameterDirection Direction
4063
{

Snowflake.Data/Core/SFDataConverter.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
using System;
6+
using System.Collections.Generic;
67
using System.Data;
78
using System.Globalization;
89
using System.Text;
@@ -20,6 +21,30 @@ static class SFDataConverter
2021
{
2122
internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
2223

24+
internal static readonly Dictionary<Type, DbType> TypeToDbTypeMap = new Dictionary<Type, DbType>()
25+
{
26+
[typeof(byte)] = DbType.Byte,
27+
[typeof(sbyte)] = DbType.SByte,
28+
[typeof(short)] = DbType.Int16,
29+
[typeof(ushort)] = DbType.UInt16,
30+
[typeof(int)] = DbType.Int32,
31+
[typeof(uint)] = DbType.UInt32,
32+
[typeof(long)] = DbType.Int64,
33+
[typeof(ulong)] = DbType.UInt64,
34+
[typeof(float)] = DbType.Single,
35+
[typeof(double)] = DbType.Double,
36+
[typeof(decimal)] = DbType.Decimal,
37+
[typeof(bool)] = DbType.Boolean,
38+
[typeof(string)] = DbType.String,
39+
[typeof(char)] = DbType.StringFixedLength,
40+
[typeof(Guid)] = DbType.Guid,
41+
[typeof(DateTime)] = DbType.DateTime,
42+
[typeof(DateTimeOffset)] = DbType.DateTimeOffset,
43+
[typeof(TimeSpan)] = DbType.Time,
44+
[typeof(byte[])] = DbType.Binary,
45+
[typeof(object)] = DbType.Object
46+
};
47+
2348
internal static object ConvertToCSharpVal(UTF8Buffer srcVal, SFDataType srcType, Type destType)
2449
{
2550
if (srcVal == null)

0 commit comments

Comments
 (0)