Skip to content

Commit 4aac41a

Browse files
authored
Enables "snowflake" connection (#1689)
* snowflake tests #1687 * actually add the tests!
1 parent c62611a commit 4aac41a

File tree

4 files changed

+99
-2
lines changed

4 files changed

+99
-2
lines changed

Dapper/SqlMapper.Settings.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ public static void SetDefaults()
9393
/// operation if there are this many elements or more. Note that this feature requires SQL Server 2016 / compatibility level 130 (or above).
9494
/// </summary>
9595
public static int InListStringSplitCount { get; set; } = -1;
96+
97+
/// <summary>
98+
/// If set, pseudo-positional parameters (i.e. ?foo?) are passed using auto-generated incremental names, i.e. "1", "2", "3"
99+
/// instead of the original name; for most scenarios, this is ignored since the name is redundant, but "snowflake" requires this.
100+
/// </summary>
101+
public static bool UseIncrementalPseudoPositionalParameterNames { get; set; }
96102
}
97103
}
98104
}

Dapper/SqlMapper.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,8 @@ private static void PassByPosition(IDbCommand cmd)
17781778
}
17791779
HashSet<string> consumed = new HashSet<string>(StringComparer.Ordinal);
17801780
bool firstMatch = true;
1781+
int index = 0; // use this to spoof names; in most pseudo-positional cases, the name is ignored, however:
1782+
// for "snowflake", the name needs to be incremental i.e. "1", "2", "3"
17811783
cmd.CommandText = pseudoPositional.Replace(cmd.CommandText, match =>
17821784
{
17831785
string key = match.Groups[1].Value;
@@ -1793,6 +1795,10 @@ private static void PassByPosition(IDbCommand cmd)
17931795
cmd.Parameters.Clear(); // only clear if we are pretty positive that we've found this pattern successfully
17941796
}
17951797
// if found, return the anonymous token "?"
1798+
if (Settings.UseIncrementalPseudoPositionalParameterNames)
1799+
{
1800+
param.ParameterName = (++index).ToString();
1801+
}
17961802
cmd.Parameters.Add(param);
17971803
parameters.Remove(key);
17981804
consumed.Add(key);

tests/Dapper.Tests/Dapper.Tests.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
2121
<PackageReference Include="MySqlConnector" Version="1.1.0" />
2222
<PackageReference Include="Npgsql" Version="5.0.0" />
23+
<PackageReference Include="Snowflake.Data" Version="2.0.3" />
2324
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
2425
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
25-
26-
2726
</ItemGroup>
2827

2928
<ItemGroup Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472'">
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#if !NET462 // platform not supported exception
2+
using System;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using Snowflake.Data.Client;
6+
using Xunit;
7+
using Xunit.Abstractions;
8+
9+
namespace Dapper.Tests
10+
{
11+
public class SnowflakeTests
12+
{
13+
static readonly string s_ConnectionString;
14+
static SnowflakeTests()
15+
{
16+
SqlMapper.Settings.UseIncrementalPseudoPositionalParameterNames = true;
17+
18+
try
19+
{ // this *probably* won't exist (TODO: can we get a test account?)
20+
s_ConnectionString = File.ReadAllText(@"c:\Code\SnowflakeConnectionString.txt").Trim();
21+
} catch { }
22+
}
23+
24+
public SnowflakeTests(ITestOutputHelper output)
25+
=> Output = output;
26+
27+
private ITestOutputHelper Output { get; }
28+
29+
30+
private static SnowflakeDbConnection GetConnection()
31+
{
32+
if (string.IsNullOrWhiteSpace(s_ConnectionString))
33+
Skip.Inconclusive("no snowflake connection-string");
34+
35+
return new SnowflakeDbConnection
36+
{
37+
ConnectionString = s_ConnectionString
38+
};
39+
}
40+
41+
[Fact]
42+
public void Connect()
43+
{
44+
using var connection = GetConnection();
45+
connection.Open();
46+
}
47+
48+
49+
[Fact]
50+
public void BasicQuery()
51+
{
52+
53+
using var connection = GetConnection();
54+
var nations = connection.Query<Nation>(@"SELECT * FROM NATION").AsList();
55+
Assert.NotEmpty(nations);
56+
Output.WriteLine($"nations: {nations.Count}");
57+
foreach (var nation in nations)
58+
{
59+
Output.WriteLine($"{nation.N_NATIONKEY}: {nation.N_NAME} (region: {nation.N_REGIONKEY}), {nation.N_COMMENT}");
60+
}
61+
}
62+
63+
[Fact]
64+
public void ParameterizedQuery()
65+
{
66+
using var connection = GetConnection();
67+
const int region = 1;
68+
var nations = connection.Query<Nation>(@"SELECT * FROM NATION WHERE N_REGIONKEY=?region?", new { region }).AsList();
69+
Assert.NotEmpty(nations);
70+
Output.WriteLine($"nations: {nations.Count}");
71+
foreach (var nation in nations)
72+
{
73+
Output.WriteLine($"{nation.N_NATIONKEY}: {nation.N_NAME} (region: {nation.N_REGIONKEY}), {nation.N_COMMENT}");
74+
}
75+
}
76+
77+
public class Nation
78+
{
79+
public int N_NATIONKEY { get; set; }
80+
public string N_NAME{ get; set; }
81+
public int N_REGIONKEY { get; set; }
82+
public string N_COMMENT { get; set; }
83+
}
84+
}
85+
}
86+
#endif

0 commit comments

Comments
 (0)