public QueryResponse <Into> ResponseFilter <From, Into>(QueryResponse <Into> response, SqlExpression <From> sqlExpression, IQueryDb dto) { response.Meta = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); var commands = dto.Include.ParseCommands(); var ctx = new QueryDbFilterContext { Db = Db, Commands = commands, Dto = dto, SqlExpression = sqlExpression, Response = response, }; if (IncludeTotal) { var totalCountRequested = commands.Any(x => "COUNT".EqualsIgnoreCase(x.Name) && (x.Args.Count == 0 || (x.Args.Count == 1 && x.Args[0] == "*"))); if (!totalCountRequested) { commands.Add(new Command { Name = "COUNT", Args = { "*" } }); } foreach (var responseFilter in ResponseFilters) { responseFilter(ctx); } string total; response.Total = response.Meta.TryGetValue("COUNT(*)", out total) ? total.ToInt() : (int)Db.Count(sqlExpression); //fallback if it's not populated (i.e. if stripped by custom ResponseFilter) //reduce payload on wire if (!totalCountRequested) { response.Meta.Remove("COUNT(*)"); if (response.Meta.Count == 0) { response.Meta = null; } } } else { foreach (var responseFilter in ResponseFilters) { responseFilter(ctx); } } return(response); }
public QueryResponse <Into> ResponseFilter <From, Into>(QueryResponse <Into> response, SqlExpression <From> expr, IQueryDb dto) { response.Meta = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); var commands = dto.Include.ParseCommands(); var ctx = new QueryDbFilterContext { Db = Db, Commands = commands, Dto = dto, SqlExpression = expr, Response = response, }; var totalCommand = commands.FirstOrDefault(x => x.Name.EqualsIgnoreCase("Total")); if (totalCommand != null) { totalCommand.Name = "COUNT"; } var totalRequested = commands.Any(x => x.Name.EqualsIgnoreCase("COUNT") && (x.Args.Count == 0 || x.Args.Count == 1 && x.Args[0].EqualsOrdinal("*"))); if (IncludeTotal || totalRequested) { if (!totalRequested) { commands.Add(new Command { Name = "COUNT", Args = { "*".AsMemory() } }); } foreach (var responseFilter in ResponseFilters) { responseFilter(ctx); } response.Total = response.Meta.TryGetValue("COUNT(*)", out var total) ? total.ToInt() : (int)Db.Count(expr); //fallback if it's not populated (i.e. if stripped by custom ResponseFilter) //reduce payload on wire if (totalCommand != null || !totalRequested) { response.Meta.Remove("COUNT(*)"); if (response.Meta.Count == 0) { response.Meta = null; } } } else { foreach (var responseFilter in ResponseFilters) { responseFilter(ctx); } } return(response); }
public void IncludeAggregates(QueryDbFilterContext ctx) { var commands = ctx.Commands; if (commands.Count == 0) { return; } var q = ctx.SqlExpression.GetUntypedSqlExpression() .Clone() .ClearLimits() .OrderBy(); var aggregateCommands = new List <Command>(); foreach (var cmd in commands) { if (!SqlAggregateFunctions.Contains(cmd.Name)) { continue; } aggregateCommands.Add(cmd); if (cmd.Args.Count == 0) { cmd.Args.Add("*".AsMemory()); } cmd.Original = cmd.AsMemory(); var hasAlias = !cmd.Suffix.IsNullOrWhiteSpace(); for (var i = 0; i < cmd.Args.Count; i++) { var arg = cmd.Args[i]; string modifier = ""; if (arg.StartsWith("DISTINCT ", StringComparison.OrdinalIgnoreCase)) { arg.SplitOnFirst(' ', out var first, out var last); modifier = first + " "; arg = last; } var fieldRef = q.FirstMatchingField(arg.ToString()); if (fieldRef != null) { //To return predictable aliases, if it's primary table don't fully qualify name var fieldName = fieldRef.Item2.FieldName; var needsRewrite = !fieldName.EqualsIgnoreCase(q.DialectProvider.NamingStrategy.GetColumnName(fieldName)); if (fieldRef.Item1 != q.ModelDef || fieldRef.Item2.Alias != null || needsRewrite || hasAlias) { cmd.Args[i] = (modifier + q.DialectProvider.GetQuotedColumnName(fieldRef.Item1, fieldRef.Item2)).AsMemory(); } } else { double d; if (!arg.EqualsOrdinal("*") && !double.TryParse(arg.ToString(), out d)) { cmd.Args[i] = "{0}".SqlFmt(arg).AsMemory(); } } } if (hasAlias) { var alias = cmd.Suffix.TrimStart().ToString(); if (alias.StartsWith("as ", StringComparison.OrdinalIgnoreCase)) { alias = alias.Substring("as ".Length); } cmd.Suffix = (" " + alias.SafeVarName()).AsMemory(); } else { cmd.Suffix = (" " + q.DialectProvider.GetQuotedName(cmd.Original.ToString())).AsMemory(); } } var selectSql = string.Join(", ", aggregateCommands.Map(x => x.ToString())); q.UnsafeSelect(selectSql); var rows = ctx.Db.Select <Dictionary <string, object> >(q); var row = rows.FirstOrDefault(); foreach (var key in row.Keys) { ctx.Response.Meta[key] = row[key]?.ToString(); } ctx.Commands.RemoveAll(aggregateCommands.Contains); }
public void IncludeAggregates(QueryDbFilterContext ctx) { var commands = ctx.Commands; if (commands.Count == 0) { return; } var q = ctx.SqlExpression.GetUntypedSqlExpression() .Clone() .ClearLimits() .OrderBy(); var aggregateCommands = new List <Command>(); foreach (var cmd in commands) { if (!SqlAggregateFunctions.Contains(cmd.Name)) { continue; } aggregateCommands.Add(cmd); if (cmd.Args.Count == 0) { cmd.Args.Add("*"); } var hasAlias = !string.IsNullOrWhiteSpace(cmd.Suffix); for (var i = 0; i < cmd.Args.Count; i++) { var arg = cmd.Args[i]; string modifier = ""; if (arg.StartsWithIgnoreCase("DISTINCT ")) { var argParts = arg.SplitOnFirst(' '); modifier = argParts[0] + " "; arg = argParts[1]; } var fieldRef = q.FirstMatchingField(arg); if (fieldRef != null) { //To return predictable aliases, if it's primary table don't fully qualify name if (fieldRef.Item1 != q.ModelDef || hasAlias) { cmd.Args[i] = modifier + q.DialectProvider.GetQuotedColumnName(fieldRef.Item1, fieldRef.Item2); } } else { double d; if (arg != "*" && !double.TryParse(arg, out d)) { cmd.Args[i] = "{0}".SqlFmt(arg); } } } if (hasAlias) { var alias = cmd.Suffix.TrimStart(); if (alias.StartsWithIgnoreCase("as ")) { alias = alias.Substring("as ".Length); } cmd.Suffix = " " + alias.SafeVarName(); } else { cmd.Suffix = " " + q.DialectProvider.GetQuotedName(cmd.ToString()); } } var selectSql = string.Join(", ", aggregateCommands.Map(x => x.ToString())); q.UnsafeSelect(selectSql); var rows = ctx.Db.Select <Dictionary <string, object> >(q); var row = rows.FirstOrDefault(); foreach (var key in row.Keys) { ctx.Response.Meta[key] = row[key].ToString(); } ctx.Commands.RemoveAll(aggregateCommands.Contains); }