Skip to content

Commit

Permalink
Fix for #569
Browse files Browse the repository at this point in the history
  • Loading branch information
mgravell committed Jul 22, 2016
1 parent ce4d015 commit 344de88
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 13 deletions.
14 changes: 13 additions & 1 deletion Dapper.Tests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3302,7 +3302,19 @@ public void PseudoPositionalParameters_ReusedParameter()
}
}
}


[Fact]
public void Issue569_SO38527197_PseudoPositionalParameters_In()
{
using (var connection = ConnectViaOledb())
{
int[] ids = { 1, 2, 5, 7 };
var list = connection.Query<int>("select * from string_split('1,2,3,4,5',',') where value in ?ids?", new { ids }).AsList();
list.Sort();
string.Join(",", list).IsEqualTo("1,2,5");
}
}

[Fact]
public void PseudoPositionalParameters_ExecSingle()
{
Expand Down
30 changes: 18 additions & 12 deletions Dapper/SqlMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1831,7 +1831,9 @@ internal static int GetListPaddingExtraCount(int count)
return intoBlock == 0 ? 0 : (padFactor - intoBlock);
}

private static string GetInListRegex(string name) => @"([?@:]" + Regex.Escape(name) + @")(?!\w)(\s+(?i)unknown(?-i))?";
private static string GetInListRegex(string name, bool byPosition) => byPosition
? (@"(\?)" + Regex.Escape(name) + @"\?(?!\w)(\s+(?i)unknown(?-i))?")
: (@"([?@:]" + Regex.Escape(name) + @")(?!\w)(\s+(?i)unknown(?-i))?");
/// <summary>
/// Internal use only
/// </summary>
Expand All @@ -1854,6 +1856,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
}
else
{
bool byPosition = ShouldPassByPosition(command.CommandText);
var list = value as IEnumerable;
var count = 0;
bool isString = value is IEnumerable<string>;
Expand All @@ -1862,7 +1865,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj

int splitAt = SqlMapper.Settings.InListStringSplitCount;
bool viaSplit = splitAt >= 0
&& TryStringSplit(ref list, splitAt, namePrefix, command);
&& TryStringSplit(ref list, splitAt, namePrefix, command, byPosition);

if (list != null && !viaSplit)
{
Expand Down Expand Up @@ -1934,7 +1937,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
}
else
{
var regexIncludingUnknown = GetInListRegex(namePrefix);
var regexIncludingUnknown = GetInListRegex(namePrefix, byPosition);
if (count == 0)
{
command.CommandText = Regex.Replace(command.CommandText, regexIncludingUnknown, match =>
Expand Down Expand Up @@ -1974,10 +1977,13 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
}
else
{
var sb = GetStringBuilder().Append('(').Append(variableName).Append(1);

var sb = GetStringBuilder().Append('(').Append(variableName);
if(!byPosition) sb.Append(1);
for (int i = 2; i <= count; i++)
{
sb.Append(',').Append(variableName).Append(i);
sb.Append(',').Append(variableName);
if (!byPosition) sb.Append(i);
}
return sb.Append(')').__ToStringRecycle();
}
Expand All @@ -1987,20 +1993,20 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
}
}

private static bool TryStringSplit(ref IEnumerable list, int splitAt, string namePrefix, IDbCommand command)
private static bool TryStringSplit(ref IEnumerable list, int splitAt, string namePrefix, IDbCommand command, bool byPosition)
{
if (list == null || splitAt < 0) return false;
if (list is IEnumerable<int>) return TryStringSplit<int>(ref list, splitAt, namePrefix, command, "int",
if (list is IEnumerable<int>) return TryStringSplit<int>(ref list, splitAt, namePrefix, command, "int", byPosition,
(sb, i) => sb.Append(i.ToString(CultureInfo.InvariantCulture)));
if (list is IEnumerable<long>) return TryStringSplit<long>(ref list, splitAt, namePrefix, command, "bigint",
if (list is IEnumerable<long>) return TryStringSplit<long>(ref list, splitAt, namePrefix, command, "bigint", byPosition,
(sb, i) => sb.Append(i.ToString(CultureInfo.InvariantCulture)));
if (list is IEnumerable<short>) return TryStringSplit<short>(ref list, splitAt, namePrefix, command, "smallint",
if (list is IEnumerable<short>) return TryStringSplit<short>(ref list, splitAt, namePrefix, command, "smallint", byPosition,
(sb, i) => sb.Append(i.ToString(CultureInfo.InvariantCulture)));
if (list is IEnumerable<byte>) return TryStringSplit<byte>(ref list, splitAt, namePrefix, command, "tinyint",
if (list is IEnumerable<byte>) return TryStringSplit<byte>(ref list, splitAt, namePrefix, command, "tinyint", byPosition,
(sb, i) => sb.Append(i.ToString(CultureInfo.InvariantCulture)));
return false;
}
private static bool TryStringSplit<T>(ref IEnumerable list, int splitAt, string namePrefix, IDbCommand command, string colType,
private static bool TryStringSplit<T>(ref IEnumerable list, int splitAt, string namePrefix, IDbCommand command, string colType, bool byPosition,
Action<StringBuilder, T> append)
{
ICollection<T> typed = list as ICollection<T>;
Expand All @@ -2012,7 +2018,7 @@ private static bool TryStringSplit<T>(ref IEnumerable list, int splitAt, string
if (typed.Count < splitAt) return false;

string varName = null;
var regexIncludingUnknown = GetInListRegex(namePrefix);
var regexIncludingUnknown = GetInListRegex(namePrefix, byPosition);
var sql = Regex.Replace(command.CommandText, regexIncludingUnknown, match =>
{
var variableName = match.Groups[1].Value;
Expand Down

0 comments on commit 344de88

Please sign in to comment.