-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathChDb.cs
82 lines (75 loc) · 2.7 KB
/
ChDb.cs
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
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
namespace ChDb;
internal static class NativeMethods
{
private const string __DllName = "libchdb.so";
[DllImport(__DllName, EntryPoint = "query_stable_v2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern nint query_stable_v2(int argc, string[] argv);
[DllImport(__DllName, EntryPoint = "free_result_v2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void free_result_v2(nint result);
}
/// <summary>
/// Entry point for stateless chdb queries.
/// </summary>
public static class ChDb
{
/// <summary>
/// Execute a stateless query and return the result.
/// </summary>
/// <param name="query">SQL query</param>
/// <param name="format">Optional output format from supported by clickhouse. Default is TabSeparated.</param>
/// <returns>Query result</returns>
/// <remarks>
/// Stateless queries are useful for simple queries that do not require a session.
/// Use <see cref="Session"/> if you need to create databases or tables.
/// Set <see cref="Session.DataPath"/> to a non-temporary directory to keep the data between sessions.
/// </remarks>
public static LocalResult? Query(string query, string? format = null)
{
if (query is null)
throw new ArgumentNullException(nameof(query));
var argv = new[] {
"clickhouse",
"--multiquery",
$"--query={query}",
$"--output-format={format ?? "TabSeparated"}"
};
return Execute(argv);
}
private static string? LookUpArg(string[] argv, string key)
{
foreach (var arg in argv)
{
var prefix = $"--{key}=";
if (arg.StartsWith(prefix))
return arg.Substring(prefix.Length);
}
return null;
}
[SuppressUnmanagedCodeSecurity]
[SecurityCritical]
internal static LocalResult? Execute(string[] argv)
{
try
{
var ptr = NativeMethods.query_stable_v2(argv.Length, argv);
var res = LocalResult.FromPtr(ptr);
NativeMethods.free_result_v2(ptr);
// Marshal.FreeHGlobal(ptr);
return res;
}
catch (RuntimeWrappedException e)
{
if (e.WrappedException is string s)
throw new ArgumentException($"Unmanaged string error {s}");
else
throw new ArgumentException($"Unmanaged unknown error {e.WrappedException}");
}
catch (Exception e)
{
throw new Exception("Managed error", e);
}
}
}