-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSnowflakeCommand.GroupBy.cs
More file actions
92 lines (80 loc) · 4.03 KB
/
SnowflakeCommand.GroupBy.cs
File metadata and controls
92 lines (80 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//-----------------------------------------------------------------------
// <copyright file="SnowflakeCommand.GroupBy.cs" company="Jonas Schubert">
// Copyright (c) Jonas Schubert. All rights reserved.
// </copyright>
// <author>Jonas Schubert</author>
//-----------------------------------------------------------------------
using TimeSpanXt;
namespace Snowflake.Data.Xt
{
/// <summary>
/// The snowflake command.
/// </summary>
/// <typeparam name="T">The generic type. This is used to parse properties for the query.</typeparam>
public partial class SnowflakeCommand<T>
where T : class
{
/// <summary>
/// Adds a group by clause.
/// https://docs.snowflake.com/en/sql-reference/constructs/group-by .
/// </summary>
/// <typeparam name="TGroupBy">The generic type.</typeparam>
/// <param name="predicate">The group by predicate.</param>
/// <returns>The snowflake command.</returns>
/// <exception cref="InvalidOperationException">Command already has a group by clause.</exception>
public SnowflakeCommand<T> GroupBy<TGroupBy>(Expression<Func<T, TGroupBy>> predicate)
{
if (this.Sql.Contains("GROUP BY", StringComparison.Ordinal))
{
throw new InvalidOperationException("Command already has a group by clause!");
}
var groupByBody = string.Join(", ", new Regex("new <>f__AnonymousType[0-9]{1,}`[0-9]{1,}", RegexOptions.None, 3.Seconds())
.Replace(
predicate.Body
.ToString()
.Replace($"{predicate.Parameters[0].Name}.", string.Empty, StringComparison.Ordinal), string.Empty)
.Replace("(", string.Empty, StringComparison.Ordinal)
.Replace(")", string.Empty, StringComparison.Ordinal)
.Split(',')
.Select(_ => _.Split("=")[0].Trim()));
foreach (var property in this.Properties)
{
var propertyName = property.Value.Name;
var propertyTableAlias = string.IsNullOrWhiteSpace(property.Value.Table)
? this.Table.Alias
: this.Joins.Single(join => string.Equals(join.Table, property.Value.Table, StringComparison.Ordinal)).Alias;
groupByBody = groupByBody.Replace($"{property.Key.Name}", $"{propertyTableAlias}.{propertyName}", StringComparison.Ordinal);
}
this.SqlBuilder.Append(CultureInfo.InvariantCulture, $" GROUP BY {groupByBody.Trim()}");
return this;
}
/// <summary>
/// Adds a group by clause.
/// https://docs.snowflake.com/en/sql-reference/constructs/group-by .
/// </summary>
/// <param name="groupBy">The group by clause.</param>
/// <returns>The snowflake command.</returns>
/// <exception cref="InvalidOperationException">Command already has a group by clause.</exception>
/// <exception cref="ArgumentNullException">Value for group by clause may not be empty.</exception>
/// <exception cref="ArgumentException">Group By may only contain valid properties.</exception>
[Obsolete("Use GroupBy<TGroupBy>(Expression<Func<T, TGroupBy>> predicate) instead.")]
public SnowflakeCommand<T> GroupBy(string groupBy)
{
if (this.Sql.Contains("GROUP BY", StringComparison.Ordinal))
{
throw new InvalidOperationException("Command already has a group by clause!");
}
if (string.IsNullOrWhiteSpace(groupBy))
{
throw new ArgumentNullException(nameof(groupBy), "Value for group by clause may not be empty!");
}
var regexTestValue = groupBy.Replace("GROUP BY", string.Empty, StringComparison.Ordinal).Trim();
if (!this.ValidPropertiesRegex.IsMatch(regexTestValue))
{
throw new ArgumentException($"Group By may only contain valid properties ({string.Join(", ", this.ValidProperties)})! \"{regexTestValue}\" is not allowed!");
}
this.SqlBuilder.Append(CultureInfo.InvariantCulture, $" {(groupBy.Trim().StartsWith("GROUP BY", ignoreCase: true, CultureInfo.InvariantCulture) ? groupBy.Trim() : $"GROUP BY {groupBy.Trim()}")}");
return this;
}
}
}