MCPcopy Create free account
hub / github.com/aptabase/aptabase / ClickHouseQueryClient

Class ClickHouseQueryClient

src/Features/Stats/ClickHouseQueryClient.cs:8–65  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

6namespace Aptabase.Features.Stats;
7
8public class ClickHouseQueryClient : IQueryClient
9{
10 private readonly ClickHouseConnection _conn;
11 private readonly EnvSettings _env;
12
13 public ClickHouseQueryClient(ClickHouseConnection conn, EnvSettings env)
14 {
15 _env = env ?? throw new ArgumentNullException(nameof(env));
16 _conn = conn ?? throw new ArgumentNullException(nameof(conn));
17 }
18
19 public async Task<IEnumerable<T>> NamedQueryAsync<T>(string name, object args, CancellationToken cancellationToken)
20 {
21 var dict = args.GetType().GetProperties().ToDictionary(p => p.Name, p => FormatArg(p.GetValue(args, null)));
22 var template = await ReadNamedQuery(name);
23 var query = await template.RenderAsync(dict);
24 return await _conn.QueryAsync<T>(query, cancellationToken);
25 }
26
27 public async Task<T> NamedQuerySingleAsync<T>(string name, object args, CancellationToken cancellationToken) where T : new()
28 {
29 var rows = await NamedQueryAsync<T>(name, args, cancellationToken);
30 return rows.FirstOrDefault() ?? new T();
31 }
32
33 public async Task<Stream> StreamResponseAsync(string query, CancellationToken cancellationToken)
34 {
35 using var command = _conn.CreateCommand();
36 command.CommandText = query;
37 var result = await command.ExecuteRawResultAsync(cancellationToken);
38 return await result.ReadAsStreamAsync();
39 }
40
41 private readonly ConcurrentDictionary<string, Template> _namedQueries = new();
42 private async Task<Template> ReadNamedQuery(string name)
43 {
44 if (_namedQueries.ContainsKey(name))
45 return _namedQueries[name];
46
47 var pathToQuery = Path.Combine(_env.EtcDirectoryPath, "clickhouse", "queries", $"{name}.liquid");
48 var content = await File.ReadAllTextAsync(pathToQuery);
49 var template = Template.ParseLiquid(content);
50
51 _namedQueries[name] = template;
52 return template;
53 }
54
55 private string? FormatArg(object? value)
56 {
57 return value switch
58 {
59 string[] s => string.Join("','", s.Select(EscapeForClickHouse)),
60 string str => EscapeForClickHouse(str),
61 DateTime d => d.ToString("yyyy-MM-dd HH:mm:ss"),
62 null => null,
63 _ => $"{value}",
64 };
65 }

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected