-
-
Notifications
You must be signed in to change notification settings - Fork 56
/
SchemaDescriber.cs
105 lines (93 loc) · 4.08 KB
/
SchemaDescriber.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.Data;
using System.Linq;
using System.Text;
using ClickHouse.Client.ADO;
using ClickHouse.Client.ADO.Adapters;
using ClickHouse.Client.ADO.Readers;
using ClickHouse.Client.Types;
namespace ClickHouse.Client.Utility;
internal static class SchemaDescriber
{
public static DataTable DescribeSchema(this ClickHouseDataReader reader)
{
var table = new DataTable();
table.Columns.Add("ColumnName", typeof(string));
table.Columns.Add("ColumnOrdinal", typeof(int));
table.Columns.Add("ColumnSize", typeof(int));
table.Columns.Add("NumericPrecision", typeof(int));
table.Columns.Add("NumericScale", typeof(int));
table.Columns.Add("IsUnique", typeof(bool));
table.Columns.Add("IsKey", typeof(bool));
table.Columns.Add("DataType", typeof(Type));
table.Columns.Add("AllowDBNull", typeof(bool));
table.Columns.Add("ProviderType", typeof(string));
table.Columns.Add("IsAliased", typeof(bool));
table.Columns.Add("IsExpression", typeof(bool));
table.Columns.Add("IsIdentity", typeof(bool));
table.Columns.Add("IsAutoIncrement", typeof(bool));
table.Columns.Add("IsRowVersion", typeof(bool));
table.Columns.Add("IsHidden", typeof(bool));
table.Columns.Add("IsLong", typeof(bool));
table.Columns.Add("IsReadOnly", typeof(bool));
for (int ordinal = 0; ordinal < reader.FieldCount; ordinal++)
{
var chType = reader.GetClickHouseType(ordinal);
var row = table.NewRow();
row["ColumnName"] = reader.GetName(ordinal);
row["ColumnOrdinal"] = ordinal;
row["DataType"] = chType.FrameworkType;
row["ProviderType"] = chType;
row["IsLong"] = chType is StringType;
row["AllowDBNull"] = chType is NullableType;
row["IsReadOnly"] = true;
row["IsRowVersion"] = false;
row["IsUnique"] = false;
row["IsKey"] = false;
row["IsAutoIncrement"] = false;
if (chType is DecimalType dt)
{
row["ColumnSize"] = dt.Size;
row["NumericPrecision"] = dt.Precision;
row["NumericScale"] = dt.Scale;
}
table.Rows.Add(row);
}
return table;
}
public static DataTable DescribeSchema(this ClickHouseConnection connection, string type, string[] restrictions) => type switch
{
"Columns" => DescribeColumns(connection, restrictions),
_ => throw new NotSupportedException(),
};
private static DataTable DescribeColumns(ClickHouseConnection connection, string[] restrictions)
{
var command = connection.CreateCommand();
var query = new StringBuilder("SELECT database as Database, table as Table, name as Name, type as ProviderType, type as DataType FROM system.columns");
var database = restrictions != null && restrictions.Length > 0 ? restrictions[0] : null;
var table = restrictions != null && restrictions.Length > 1 ? restrictions[1] : null;
if (database != null)
{
query.Append(" WHERE database={database:String}");
command.AddParameter("database", "String", database);
}
if (table != null)
{
query.Append(" AND table={table:String}");
command.AddParameter("table", "String", table);
}
command.CommandText = query.ToString();
using var adapter = new ClickHouseDataAdapter();
adapter.SelectCommand = command;
var result = new DataTable();
adapter.Fill(result);
foreach (var row in result.Rows.Cast<DataRow>())
{
var clickHouseType = TypeConverter.ParseClickHouseType((string)row["ProviderType"], TypeSettings.Default);
row["ProviderType"] = clickHouseType.ToString();
// TODO: this should return actual framework type like other implementations do
row["DataType"] = clickHouseType.FrameworkType.ToString().Replace("System.", string.Empty);
}
return result;
}
}