Skip to content

Commit

Permalink
Fixed schema description to allow DataTable.Load to work #428 (#429)
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkWanderer authored Jan 14, 2024
1 parent 50d4c4d commit aae58a7
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 74 deletions.
2 changes: 1 addition & 1 deletion ClickHouse.Client.Benchmark/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"ClickHouse.Client.Benchmark": {
"commandName": "Project",
"commandLineArgs": "--filter \"*\" --inProcess --job Default --join"
"commandLineArgs": "--filter \"*\" --inProcess --job Short --join"
}
}
}
12 changes: 12 additions & 0 deletions ClickHouse.Client.Tests/ADO/DataAdapterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using ClickHouse.Client.ADO.Adapters;
using NUnit.Framework;

Expand Down Expand Up @@ -44,6 +45,17 @@ public void DataAdapterShouldFillDataTable()
Assert.AreEqual(2, dataTable.Columns.Count);
}

[Test]
public async Task DataTableShouldLoadResults()
{
using var connection = TestUtilities.GetTestClickHouseConnection();
using var command = connection.CreateCommand();
command.CommandText = "SELECT 1 as SOMEID FROM numbers(10)";
await using var reader = await command.ExecuteReaderAsync();
var table = new DataTable();
table.Load(reader);
}

public static IEnumerable<TestCaseData> SimpleSelectQueries => TestUtilities.GetDataTypeSamples()
.Where(sample => sample.ExampleValue != DBNull.Value)
.Select(sample => new TestCaseData($"SELECT {sample.ExampleExpression} AS col"));
Expand Down
115 changes: 42 additions & 73 deletions ClickHouse.Client/Utility/SchemaDescriber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,85 +11,54 @@ namespace ClickHouse.Client.Utility;

internal static class SchemaDescriber
{
private static readonly string[] Columns =
{
"ColumnName",
"ColumnOrdinal",
"ColumnSize",
"NumericPrecision",
"NumericScale",
"DataType",
"ProviderType",
"IsLong",
"AllowDBNull",
"IsReadOnly",
"IsRowVersion",
"IsUnique",
"IsKey",
"IsAutoIncrement",
"BaseCatalogName",
"BaseSchemaName",
"BaseTableName",
"BaseColumnName",
"AutoIncrementSeed",
"AutoIncrementStep",
"DefaultValue",
"Expression",
"ColumnMapping",
"BaseTableNamespace",
"BaseColumnNamespace",
};

public static DataTable DescribeSchema(this ClickHouseDataReader reader)
{
var result = new DataTable();
foreach (var columnName in Columns)
result.Columns.Add(columnName);
for (int i = 0; i < reader.FieldCount; i++)
result.Rows.Add(reader.DescribeColumn(i));

return result;
}
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));

private static object[] DescribeColumn(this ClickHouseDataReader reader, int ordinal)
{
var chType = reader.GetClickHouseType(ordinal);
for (int ordinal = 0; ordinal < reader.FieldCount; ordinal++)
{
var chType = reader.GetClickHouseType(ordinal);

var result = new object[Columns.Length];
result[0] = reader.GetName(ordinal); // ColumnName
result[1] = ordinal; // ColumnOrdinal
result[2] = null; // ColumnSize
result[3] = null; // NumericPrecision
result[4] = null; // NumericScale
result[5] = chType.FrameworkType; // DataType
result[6] = chType.ToString(); // ProviderType
result[7] = chType is StringType; // IsLong
result[8] = chType is NullableType; // AllowDBNull
result[9] = true; // IsReadOnly
result[10] = false; // IsRowVersion
result[11] = false; // IsUnique
result[12] = false; // IsKey
result[13] = false; // IsAutoIncrement
result[14] = null; // BaseCatalogName
result[15] = null; // BaseSchemaName
result[16] = null; // BaseTableName
result[17] = reader.GetName(ordinal); // BaseColumnName
result[18] = null; // AutoIncrementSeed
result[19] = null; // AutoIncrementStep
result[20] = null; // DefaultValue
result[21] = null; // Expression
result[22] = MappingType.Element; // ColumnMapping
result[23] = null; // BaseTableNamespace
result[24] = null; // BaseColumnNamespace
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)
{
result[2] = dt.Size;
result[3] = dt.Precision;
result[4] = dt.Scale;
if (chType is DecimalType dt)
{
row["ColumnSize"] = dt.Size;
row["NumericPrecision"] = dt.Precision;
row["NumericScale"] = dt.Scale;
}
table.Rows.Add(row);
}

return result;
return table;
}

public static DataTable DescribeSchema(this ClickHouseConnection connection, string type, string[] restrictions) => type switch
Expand Down

0 comments on commit aae58a7

Please sign in to comment.