Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit d65432e

Browse files
committed
Ensure string param size is set on all params
1 parent 0dbc363 commit d65432e

File tree

3 files changed

+124
-38
lines changed

3 files changed

+124
-38
lines changed

src/ServiceStack.OrmLite/Expressions/SqlExpression.cs

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Collections.ObjectModel;
45
using System.Data;
56
using System.Linq;
67
using System.Reflection;
78
using System.Text;
8-
using System.Collections.ObjectModel;
99
using System.Linq.Expressions;
1010
using System.Runtime.CompilerServices;
1111
using System.Text.RegularExpressions;
12+
using ServiceStack.OrmLite.Converters;
1213
using ServiceStack.OrmLite.Dapper;
1314
using ServiceStack.Text;
1415

@@ -2799,25 +2800,7 @@ public IDbDataParameter CreateParam(string name,
27992800
p.SourceVersion = sourceVersion;
28002801
}
28012802

2802-
if (p.DbType == DbType.String)
2803-
{
2804-
p.Size = DialectProvider.GetStringConverter().StringLength;
2805-
if (value is string strValue && strValue.Length > p.Size)
2806-
p.Size = strValue.Length;
2807-
}
2808-
2809-
if (value != null)
2810-
{
2811-
DialectProvider.InitDbParam(p, value.GetType());
2812-
p.Value = DialectProvider.GetParamValue(value, value.GetType());
2813-
}
2814-
else
2815-
{
2816-
p.Value = DBNull.Value;
2817-
}
2818-
2819-
if (dbType != null)
2820-
p.DbType = dbType.Value;
2803+
DialectProvider.ConfigureParam(p, value, dbType);
28212804

28222805
return p;
28232806
}
@@ -2983,35 +2966,45 @@ public static IDbDataParameter CreateParam(this IOrmLiteDialectProvider dialectP
29832966
byte? scale = null,
29842967
int? size = null)
29852968
{
2986-
var to = dialectProvider.CreateParam();
2969+
var p = dialectProvider.CreateParam();
2970+
2971+
p.ParameterName = dialectProvider.GetParam(name);
2972+
2973+
dialectProvider.ConfigureParam(p, value, dbType);
29872974

2988-
to.ParameterName = dialectProvider.GetParam(name);
2975+
if (precision != null)
2976+
p.Precision = precision.Value;
2977+
if (scale != null)
2978+
p.Scale = scale.Value;
2979+
if (size != null)
2980+
p.Size = size.Value;
29892981

2990-
var valueType = fieldType ?? (value?.GetType() ?? typeof(string));
2982+
return p;
2983+
}
29912984

2985+
internal static void ConfigureParam(this IOrmLiteDialectProvider dialectProvider, IDbDataParameter p, object value, DbType? dbType)
2986+
{
29922987
if (value != null)
29932988
{
2994-
dialectProvider.InitDbParam(to, valueType);
2995-
to.Value = dialectProvider.GetParamValue(value, valueType);
2989+
dialectProvider.InitDbParam(p, value.GetType());
2990+
p.Value = dialectProvider.GetParamValue(value, value.GetType());
29962991
}
29972992
else
29982993
{
2999-
to.Value = DBNull.Value;
2994+
p.Value = DBNull.Value;
30002995
}
30012996

3002-
if (precision != null)
3003-
to.Precision = precision.Value;
3004-
if (scale != null)
3005-
to.Scale = scale.Value;
3006-
if (size != null)
3007-
to.Size = size.Value;
3008-
3009-
dialectProvider.InitDbParam(to, valueType);
2997+
// Can't check DbType in PostgreSQL before p.Value is assinged
2998+
if (p.Value is string strValue && strValue.Length > p.Size)
2999+
{
3000+
var stringConverter = dialectProvider.GetStringConverter();
3001+
p.Size = strValue.Length > stringConverter.StringLength
3002+
? strValue.Length
3003+
: stringConverter.StringLength;
3004+
}
30103005

30113006
if (dbType != null)
3012-
to.DbType = dbType.Value;
3013-
3014-
return to;
3007+
p.DbType = dbType.Value;
30153008
}
30163009

30173010
public static IDbDataParameter AddQueryParam(this IOrmLiteDialectProvider dialectProvider,
@@ -3040,6 +3033,7 @@ public static IDbDataParameter AddParam(this IOrmLiteDialectProvider dialectProv
30403033
dbCmd.Parameters.Add(parameter);
30413034
return parameter;
30423035
}
3036+
30433037
}
30443038
}
30453039

src/ServiceStack.OrmLite/OrmLiteDialectProviderBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ public virtual void SetParameterValue<T>(FieldDefinition fieldDef, IDataParamete
969969
var value = GetValueOrDbNull<T>(fieldDef, obj);
970970
p.Value = value;
971971

972-
if (value is string s && p is IDbDataParameter dataParam && dataParam.Size > 0 && s?.Length > dataParam.Size)
972+
if (p.Value is string s && p is IDbDataParameter dataParam && dataParam.Size > 0 && s.Length > dataParam.Size)
973973
{
974974
// db param Size set in StringConverter
975975
dataParam.Size = s.Length;

tests/ServiceStack.OrmLite.Tests/_TypeDescriptorMetadataTests.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Data;
3+
using System.Text;
34
using NUnit.Framework;
45
using ServiceStack.DataAnnotations;
56
using ServiceStack.Text;
@@ -139,6 +140,97 @@ public void Can_Create_Table_with_MaxText_column_Unicode()
139140
}
140141
}
141142
}
143+
144+
[Test]
145+
public void Does_save_cache_data_when_data_exceeds_StringConverter_max_size()
146+
{
147+
IDbDataParameter GetParam(IDbCommand cmd, string name)
148+
{
149+
for (var i = 0; i < cmd.Parameters.Count; i++)
150+
{
151+
if (cmd.Parameters[i] is IDbDataParameter p
152+
&& p.ParameterName.Substring(1).EqualsIgnoreCase(name))
153+
{
154+
return p;
155+
}
156+
}
157+
return null;
158+
}
159+
160+
using (var db = OpenDbConnection())
161+
{
162+
var stringConverter = db.GetDialectProvider().GetStringConverter();
163+
var hold = stringConverter.StringLength;
164+
stringConverter.StringLength = 255;
165+
166+
try
167+
{
168+
db.DropAndCreateTable<CacheEntry>();
169+
}
170+
catch (Exception)
171+
{
172+
db.DropAndCreateTable<CacheEntry>();
173+
}
174+
175+
var sb = new StringBuilder();
176+
30.Times(i => sb.Append("0123456789"));
177+
Assert.That(sb.Length, Is.EqualTo(300));
178+
179+
var id = "key";
180+
181+
var original = new CacheEntry {
182+
Id = id,
183+
Data = sb.ToString(),
184+
CreatedDate = DateTime.Now,
185+
ModifiedDate = DateTime.Now,
186+
};
187+
db.Insert(original, cmd => {
188+
var idParam = GetParam(cmd, nameof(CacheEntry.Id));
189+
var dataParam = GetParam(cmd, nameof(CacheEntry.Data));
190+
191+
//MySql auto sets param size based on value
192+
Assert.That(idParam.Size, Is.EqualTo(stringConverter.StringLength)
193+
.Or.EqualTo(Math.Min((idParam.Value as string).Length, stringConverter.StringLength))
194+
);
195+
Assert.That(dataParam.Size, Is.EqualTo(300)
196+
.Or.EqualTo(Math.Min((dataParam.Value as string).Length, stringConverter.StringLength))
197+
);
198+
});
199+
200+
var key = db.SingleById<CacheEntry>(id);
201+
Assert.That(key.Data, Is.EqualTo(original.Data));
202+
203+
var updatedData = key.Data + "0123456789";
204+
205+
var exists = db.UpdateOnly(new CacheEntry
206+
{
207+
Id = id,
208+
Data = updatedData,
209+
ModifiedDate = DateTime.UtcNow,
210+
},
211+
onlyFields: q => new { q.Data, q.ModifiedDate },
212+
@where: q => q.Id == id,
213+
cmd => {
214+
var idParam = cmd.Parameters[0] as IDbDataParameter;
215+
var dataParam = cmd.Parameters[1] as IDbDataParameter;
216+
217+
//MySql auto sets param size based on value
218+
Assert.That(idParam.Size, Is.EqualTo(stringConverter.StringLength)
219+
.Or.EqualTo(Math.Min((idParam.Value as string).Length, stringConverter.StringLength))
220+
);
221+
Assert.That(dataParam.Size, Is.EqualTo(310)
222+
.Or.EqualTo(Math.Min((dataParam.Value as string).Length, stringConverter.StringLength))
223+
);
224+
}) == 1;
225+
226+
Assert.That(exists);
227+
228+
key = db.SingleById<CacheEntry>(id);
229+
Assert.That(key.Data, Is.EqualTo(updatedData));
230+
231+
stringConverter.StringLength = hold;
232+
}
233+
}
142234
}
143235

144236

0 commit comments

Comments
 (0)