From 344de88979578f26706f51901564e8e8c1b88065 Mon Sep 17 00:00:00 2001 From: Marc Gravell Date: Fri, 22 Jul 2016 14:44:52 +0100 Subject: [PATCH] Fix for #569 --- Dapper.Tests/Tests.cs | 14 +++++++++++++- Dapper/SqlMapper.cs | 30 ++++++++++++++++++------------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/Dapper.Tests/Tests.cs b/Dapper.Tests/Tests.cs index 30b9bc0d1..e90e2e60c 100644 --- a/Dapper.Tests/Tests.cs +++ b/Dapper.Tests/Tests.cs @@ -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("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() { diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 6cbfc56f4..6f7e6c4aa 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -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))?"); /// /// Internal use only /// @@ -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; @@ -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) { @@ -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 => @@ -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(); } @@ -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) return TryStringSplit(ref list, splitAt, namePrefix, command, "int", + if (list is IEnumerable) return TryStringSplit(ref list, splitAt, namePrefix, command, "int", byPosition, (sb, i) => sb.Append(i.ToString(CultureInfo.InvariantCulture))); - if (list is IEnumerable) return TryStringSplit(ref list, splitAt, namePrefix, command, "bigint", + if (list is IEnumerable) return TryStringSplit(ref list, splitAt, namePrefix, command, "bigint", byPosition, (sb, i) => sb.Append(i.ToString(CultureInfo.InvariantCulture))); - if (list is IEnumerable) return TryStringSplit(ref list, splitAt, namePrefix, command, "smallint", + if (list is IEnumerable) return TryStringSplit(ref list, splitAt, namePrefix, command, "smallint", byPosition, (sb, i) => sb.Append(i.ToString(CultureInfo.InvariantCulture))); - if (list is IEnumerable) return TryStringSplit(ref list, splitAt, namePrefix, command, "tinyint", + if (list is IEnumerable) return TryStringSplit(ref list, splitAt, namePrefix, command, "tinyint", byPosition, (sb, i) => sb.Append(i.ToString(CultureInfo.InvariantCulture))); return false; } - private static bool TryStringSplit(ref IEnumerable list, int splitAt, string namePrefix, IDbCommand command, string colType, + private static bool TryStringSplit(ref IEnumerable list, int splitAt, string namePrefix, IDbCommand command, string colType, bool byPosition, Action append) { ICollection typed = list as ICollection; @@ -2012,7 +2018,7 @@ private static bool TryStringSplit(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;