public QueryResponse <Into> ResponseFilter <From, Into>(QueryResponse <Into> response, SqlExpression <From> sqlExpression, IQuery model) { response.Meta = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); var commands = model.Include.ParseCommands(); 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 = { "*" } }); } var ctx = new QueryFilterContext { Db = Db, Commands = commands, Request = model, SqlExpression = sqlExpression, Response = response, }; 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; } } return(response); }
public void IncludeAggregates(QueryFilterContext 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); }