Skip to content

Commit fb33c73

Browse files
author
Tien Nguyen
committed
Caching the command parameter metadata is only applicable for dbType.String but not for the others.
Adding more test cases raised by issue #196
1 parent 730e8a5 commit fb33c73

File tree

5 files changed

+142
-43
lines changed

5 files changed

+142
-43
lines changed

build/common.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
<Project>
22
<PropertyGroup>
33
<TargetFrameworks>netcoreapp1.0;netcoreapp1.1;netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;net46;netstandard2.0</TargetFrameworks>
4-
<VersionPrefix>0.19.1</VersionPrefix>
4+
<VersionPrefix>0.19.2</VersionPrefix>
55
<AssemblyVersion>0.11.0.0</AssemblyVersion>
66
<FileVersion>$(VersionPrefix)</FileVersion>
77
<Authors>dataaction</Authors>
88
<PackageTags>Sybase ASE Adaptive SAP AseClient DbProvider</PackageTags>
99
<PackageIcon>icon.png</PackageIcon>
1010
<PackageProjectUrl>https://github.com/DataAction/AdoNetCore.AseClient</PackageProjectUrl>
1111
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
12-
<PackageReleaseNotes>Refer to GitHub - https://github.com/DataAction/AdoNetCore.AseClient/releases/tag/0.19.1</PackageReleaseNotes>
12+
<PackageReleaseNotes>Refer to GitHub - https://github.com/DataAction/AdoNetCore.AseClient/releases/tag/0.19.2</PackageReleaseNotes>
1313
<RepositoryUrl>https://github.com/DataAction/AdoNetCore.AseClient</RepositoryUrl>
1414
<RepositoryType>git</RepositoryType>
1515
</PropertyGroup>

src/AdoNetCore.AseClient/Internal/FormatItem.cs

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -64,50 +64,60 @@ public string ParameterName
6464
/// </summary>
6565
public SerializationType SerializationType { get; set; }
6666

67-
public static FormatItem CreateForParameter(AseParameter parameter, DbEnvironment env, CommandType commandType)
67+
public static FormatItem CreateForParameter(AseParameter parameter, DbEnvironment env, AseCommand command)
6868
{
69-
parameter.AseDbType = TypeMap.InferType(parameter);
70-
7169
var dbType = parameter.DbType;
72-
7370
var length = TypeMap.GetFormatLength(dbType, parameter, env.Encoding);
7471

75-
var format = new FormatItem
76-
{
77-
AseDbType = parameter.AseDbType,
78-
ParameterName = parameter.ParameterName,
79-
IsOutput = parameter.IsOutput,
80-
IsNullable = parameter.IsNullable,
81-
Length = length,
82-
DataType = TypeMap.GetTdsDataType(dbType, parameter.SendableValue, length, parameter.ParameterName),
83-
UserType = TypeMap.GetUserType(dbType, parameter.SendableValue, length)
84-
};
72+
parameter.AseDbType = TypeMap.InferType(parameter);
8573

86-
//fixup the FormatItem's BlobType for strings and byte arrays
87-
if (format.DataType == TdsDataType.TDS_BLOB)
74+
var format = command.FormatItem;
75+
var parameterName = parameter.ParameterName ?? command.Parameters.IndexOf(parameter).ToString();
76+
if (!(command.FormatItem != null && command.FormatItem.ParameterName == parameterName &&
77+
command.FormatItem.AseDbType == parameter.AseDbType))
8878
{
89-
switch (parameter.DbType)
79+
format = new FormatItem
9080
{
91-
case DbType.AnsiString:
92-
format.BlobType = BlobType.BLOB_LONGCHAR;
93-
break;
94-
case DbType.String:
95-
format.BlobType = BlobType.BLOB_UNICHAR;
96-
// This is far less than ideal but at the time of addressing this issue whereby if the
97-
// BlobType is a BLOB_UNICHAR then the UserType would need to be 36 when it
98-
// is a stored proc otherwise it would need to be zero (0).
99-
//
100-
// In the future, we'd need to overhaul how TDS_BLOB is structured especially
101-
// around BLOB_UNICHAR and the UserType that it should return in a more consistent way
102-
if (commandType != CommandType.StoredProcedure)
103-
format.UserType = 0;
81+
AseDbType = parameter.AseDbType,
82+
ParameterName = parameter.ParameterName,
83+
IsOutput = parameter.IsOutput,
84+
IsNullable = parameter.IsNullable,
85+
Length = length,
86+
DataType = TypeMap.GetTdsDataType(dbType, parameter.SendableValue, length, parameter.ParameterName),
87+
UserType = TypeMap.GetUserType(dbType, parameter.SendableValue, length)
88+
};
10489

105-
break;
106-
case DbType.Binary:
107-
format.BlobType = BlobType.BLOB_LONGBINARY;
108-
break;
90+
//fixup the FormatItem's BlobType for strings and byte arrays
91+
if (format.DataType == TdsDataType.TDS_BLOB)
92+
{
93+
switch (parameter.DbType)
94+
{
95+
case DbType.AnsiString:
96+
format.BlobType = BlobType.BLOB_LONGCHAR;
97+
break;
98+
case DbType.String:
99+
format.BlobType = BlobType.BLOB_UNICHAR;
100+
// This is far less than ideal but at the time of addressing this issue whereby if the
101+
// BlobType is a BLOB_UNICHAR then the UserType would need to be 36 when it
102+
// is a stored proc otherwise it would need to be zero (0).
103+
//
104+
// In the future, we'd need to overhaul how TDS_BLOB is structured especially
105+
// around BLOB_UNICHAR and the UserType that it should return in a more consistent way
106+
if (command.CommandType != CommandType.StoredProcedure)
107+
format.UserType = 0;
108+
109+
break;
110+
case DbType.Binary:
111+
format.BlobType = BlobType.BLOB_LONGBINARY;
112+
break;
113+
}
109114
}
110115
}
116+
else
117+
{
118+
format.DataType = TypeMap.GetTdsDataType(dbType, parameter.SendableValue, length, parameter.ParameterName);
119+
format.UserType = TypeMap.GetUserType(dbType, parameter.SendableValue, length);
120+
}
111121

112122
//fixup the FormatItem's length,scale,precision for decimals
113123
if (format.IsDecimalType)

src/AdoNetCore.AseClient/Internal/InternalConnection.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -669,11 +669,7 @@ private IToken[] BuildParameterTokens(AseCommand command)
669669

670670
foreach (var parameter in command.Parameters.SendableParameters)
671671
{
672-
var parameterName = parameter.ParameterName ?? command.Parameters.IndexOf(parameter).ToString();
673-
if (!(command.FormatItem != null && command.FormatItem.ParameterName == parameterName && command.FormatItem.AseDbType == parameter.AseDbType))
674-
{
675-
command.FormatItem = FormatItem.CreateForParameter(parameter, _environment, command.CommandType);
676-
}
672+
command.FormatItem = FormatItem.CreateForParameter(parameter, _environment, command);
677673

678674
formatItems.Add(command.FormatItem);
679675
parameterItems.Add(new ParametersToken.Parameter

test/AdoNetCore.AseClient.Tests/Integration/AseCommandTests.cs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,89 @@ public void Command_Reuse_ShouldWork()
178178
}
179179
}
180180

181+
[TestCaseSource(nameof(ReUseCommandTypeData))]
182+
public void Command_Reuse_ShouldWork_For_Null_Value(System.Data.DbType dbType, Type type, object value)
183+
{
184+
using (var connection = GetConnection())
185+
{
186+
connection.Open();
187+
using (var cmd = connection.CreateCommand())
188+
{
189+
var sql = @"SELECT @value";
190+
var p = cmd.CreateParameter();
191+
p.ParameterName = "@value";
192+
p.DbType = dbType;
193+
p.Value = Convert.ChangeType(value, type);
194+
cmd.CommandText = sql;
195+
cmd.Parameters.Add(p);
196+
cmd.ExecuteScalar();
197+
198+
p = cmd.CreateParameter();
199+
p.ParameterName = "@value";
200+
p.DbType = dbType;
201+
p.Value = null;
202+
cmd.Parameters.Clear();
203+
cmd.Parameters.Add(p);
204+
205+
cmd.ExecuteScalar();
206+
}
207+
}
208+
}
209+
210+
211+
[TestCaseSource(nameof(ReUseCommandTypeData))]
212+
public void Command_Reuse_ShouldWork_For_NonNull_Value(System.Data.DbType dbType, Type type, object value)
213+
{
214+
using (var connection = GetConnection())
215+
{
216+
connection.Open();
217+
using (var cmd = connection.CreateCommand())
218+
{
219+
var sql = @"SELECT @value";
220+
var p = cmd.CreateParameter();
221+
p.ParameterName = "@value";
222+
p.DbType = dbType;
223+
p.Value = null;
224+
cmd.CommandText = sql;
225+
cmd.Parameters.Add(p);
226+
cmd.ExecuteScalar();
227+
228+
p = cmd.CreateParameter();
229+
p.ParameterName = "@value";
230+
p.DbType = dbType;
231+
p.Value = Convert.ChangeType(value, type);
232+
cmd.Parameters.Clear();
233+
cmd.Parameters.Add(p);
234+
235+
cmd.ExecuteScalar();
236+
}
237+
}
238+
}
239+
private static IEnumerable<TestCaseData> ReUseCommandTypeData()
240+
{
241+
yield return new TestCaseData(System.Data.DbType.Boolean, typeof(bool), false);
242+
yield return new TestCaseData(System.Data.DbType.Byte, typeof(byte), 12);
243+
yield return new TestCaseData(System.Data.DbType.SByte, typeof(sbyte), 2);
244+
yield return new TestCaseData(System.Data.DbType.Int16, typeof(short), 3);
245+
yield return new TestCaseData(System.Data.DbType.UInt16, typeof(ushort), 4);
246+
yield return new TestCaseData(System.Data.DbType.Int32, typeof(int), 23);
247+
yield return new TestCaseData(System.Data.DbType.UInt32, typeof(uint), 45);
248+
yield return new TestCaseData(System.Data.DbType.Int64, typeof(long), 76434755);
249+
yield return new TestCaseData(System.Data.DbType.UInt64, typeof(ulong), 1223);
250+
yield return new TestCaseData(System.Data.DbType.String, typeof(string), "If it could only be like this always—always summer, always alone, the fruit always ripe");
251+
yield return new TestCaseData(System.Data.DbType.AnsiString, typeof(string), "Doubt thou the stars are fire; Doubt that the sun doth move; Doubt truth to be a liar; But never doubt I love");
252+
yield return new TestCaseData(System.Data.DbType.AnsiStringFixedLength, typeof(string), "For never was a story of more woe than this of Juliet and her Romeo.");
253+
yield return new TestCaseData(System.Data.DbType.Guid, typeof(string), "e2207b47-3fce-4187-808f-e206398a9133");
254+
yield return new TestCaseData(System.Data.DbType.Decimal, typeof(decimal), 342.23);
255+
yield return new TestCaseData(System.Data.DbType.Currency, typeof(decimal), 1233.3);
256+
yield return new TestCaseData(System.Data.DbType.Single, typeof(float), 20.34f);
257+
yield return new TestCaseData(System.Data.DbType.Double, typeof(double), 3423.234d);
258+
yield return new TestCaseData(System.Data.DbType.DateTime, typeof(DateTime), "2019-03-13 03:20:35.23 AM");
259+
yield return new TestCaseData(System.Data.DbType.Date, typeof(DateTime), "2018-07-04 23:20:35.23 PM");
260+
yield return new TestCaseData(System.Data.DbType.Time, typeof(DateTime), "2014-09-10 23:20:35");
261+
262+
}
263+
181264
private static IEnumerable<TestCaseData> GetDataTypeName_ShouldWork_Cases()
182265
{
183266
yield return new TestCaseData("convert(unichar(2), 'À')", "unichar");
@@ -244,5 +327,15 @@ private static IEnumerable<TestCaseData> GetDataTypeName_ShouldWorkUtf8_Cases()
244327
yield return new TestCaseData("convert(nvarchar(2), 'a')", "nvarchar");
245328
yield return new TestCaseData("convert(nvarchar(2), null)", "nvarchar");
246329
}
330+
331+
public T CastObject<T>(object input) {
332+
return (T) input;
333+
}
334+
335+
public T ConvertObject<T>(object input) {
336+
return (T) Convert.ChangeType(input, typeof(T));
337+
}
338+
247339
}
340+
248341
}

test/AdoNetCore.AseClient.Tests/Integration/TextEchoProcedureTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,8 @@ public void Insert_Text_ShouldBeValid()
447447
fragmentCommand.CommandType = CommandType.Text;
448448
fragmentCommand.Transaction = transaction;
449449

450-
//var bytesSegmentSize = 16382;
451-
var bytesSegmentSize = 2048;
450+
var bytesSegmentSize = 16382;
451+
//var bytesSegmentSize = 2048;
452452
var data = Enumerable.Repeat((byte) 0x65, 16384).ToArray();
453453
//var data = Enumerable.Repeat((byte) 0x65, 6380).ToArray();
454454
var totalSegment = GetTotalSegments(data.Length, bytesSegmentSize );

0 commit comments

Comments
 (0)