Skip to content

Commit 4d838fc

Browse files
authored
Merge pull request #762 from FastReports/sync_branch_2025.2.7
FastReport.OpenSource 2025.2.7
2 parents b077d5f + e35c3b0 commit 4d838fc

File tree

78 files changed

+2841
-635
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2841
-635
lines changed

Demos/OpenSource/SPA/FastReport.Core.React/ClientApp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"dependencies": {
66
"bootstrap": "^5.1.0",
7-
"http-proxy-middleware": "^0.19.1",
7+
"http-proxy-middleware": "^2.0.7",
88
"jquery": "^3.5.1",
99
"merge": "^2.1.1",
1010
"oidc-client": "^1.11.5",

Extras/Core/FastReport.Data/FastReport.Data.Cassandra/CassandraDataConnection.cs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
using System.Linq;
66
using System.Text;
77
using System.Threading;
8+
using System.Threading.Tasks;
89
using Cassandra;
9-
using Cassandra.Mapping;
1010

1111
namespace FastReport.Data.Cassandra
1212
{
@@ -22,6 +22,11 @@ public override string[] GetTableNames()
2222
return (string[])cluster.Metadata.GetTables(keyspace);
2323
}
2424

25+
public override Task<string[]> GetTableNamesAsync(CancellationToken cancellationToken = default)
26+
{
27+
return Task.FromResult(GetTableNames());
28+
}
29+
2530
/// <inheritdoc/>
2631
public override string QuoteIdentifier(string value, DbConnection connection)
2732
{
@@ -36,6 +41,13 @@ public override void CreateAllTables(bool initSchema)
3641
base.CreateAllTables(initSchema);
3742
}
3843

44+
public override async Task CreateAllTablesAsync(bool initSchema, CancellationToken cancellationToken = default)
45+
{
46+
if (session == null)
47+
await InitConnectionAsync();
48+
await base.CreateAllTablesAsync(initSchema, cancellationToken);
49+
}
50+
3951
/// <inheritdoc/>
4052
public override void CreateTable(TableDataSource source)
4153
{
@@ -45,6 +57,14 @@ public override void CreateTable(TableDataSource source)
4557
base.CreateTable(source);
4658
}
4759

60+
public override async Task CreateTableAsync(TableDataSource source, CancellationToken cancellationToken = default)
61+
{
62+
if (session == null)
63+
await InitConnectionAsync();
64+
65+
await base.CreateTableAsync(source, cancellationToken);
66+
}
67+
4868
/// <inheritdoc/>
4969
public override void FillTableSchema(DataTable table, string selectCommand, CommandParameterCollection parameters)
5070
{
@@ -54,6 +74,12 @@ public override void FillTableSchema(DataTable table, string selectCommand, Comm
5474
}
5575
}
5676

77+
public override Task FillTableSchemaAsync(DataTable table, string selectCommand, CommandParameterCollection parameters, CancellationToken cancellationToken)
78+
{
79+
FillTableSchema(table, selectCommand, parameters);
80+
return Task.CompletedTask;
81+
}
82+
5783
/// <inheritdoc/>
5884
public override void FillTableData(DataTable table, string selectCommand, CommandParameterCollection parameters)
5985
{
@@ -65,17 +91,35 @@ public override void FillTableData(DataTable table, string selectCommand, Comman
6591
}
6692
}
6793

94+
public override Task FillTableDataAsync(DataTable table, string selectCommand, CommandParameterCollection parameters, CancellationToken cancellationToken = default)
95+
{
96+
FillTableData(table, selectCommand, parameters);
97+
return Task.CompletedTask;
98+
}
99+
68100
public CassandraDataConnection()
69101
{
70102
IsSqlBased = false;
71103
}
72104

73105
private void InitConnection()
106+
{
107+
InitConnectionShared();
108+
session = cluster.Connect(keyspace);
109+
}
110+
111+
private async Task InitConnectionAsync()
112+
{
113+
InitConnectionShared();
114+
session = await cluster.ConnectAsync(keyspace);
115+
}
116+
117+
private void InitConnectionShared()
74118
{
75119
CassandraConnectionStringBuilder connStrBuilder = new CassandraConnectionStringBuilder(ConnectionString);
76120
Builder clusterBuilder = Cluster.Builder();
77121

78-
if (connStrBuilder.Username != null && connStrBuilder.Username != ""
122+
if (connStrBuilder.Username != null && connStrBuilder.Username != ""
79123
&& connStrBuilder.Password != "" && connStrBuilder.Password != null)
80124
clusterBuilder.WithCredentials(connStrBuilder.Username, connStrBuilder.Password);
81125

@@ -86,7 +130,6 @@ private void InitConnection()
86130

87131
keyspace = connStrBuilder.DefaultKeyspace;
88132
cluster = clusterBuilder.Build();
89-
session = cluster.Connect(keyspace);
90133
}
91134
}
92135
}

Extras/Core/FastReport.Data/FastReport.Data.ClickHouse/ClickHouseDataConnection.cs

Lines changed: 97 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Linq;
1313
using System.Net;
1414
using System.Text;
15+
using System.Threading;
1516
using System.Threading.Tasks;
1617

1718
namespace FastReport.ClickHouse
@@ -40,6 +41,28 @@ private void GetDBObjectNames(string name, List<string> list)
4041
}
4142
}
4243

44+
private async Task GetDBObjectNamesAsync(string name, List<string> list, CancellationToken cancellationToken)
45+
{
46+
DataTable schema = null;
47+
DbConnection connection = GetConnection();
48+
try
49+
{
50+
await OpenConnectionAsync(connection, cancellationToken);
51+
if (name == "Tables")
52+
schema = DescribeTables(connection, connection.Database);
53+
else
54+
schema = await connection.GetSchemaAsync(name, new string[] { connection.Database }, cancellationToken);
55+
}
56+
finally
57+
{
58+
await DisposeConnectionAsync(connection);
59+
}
60+
foreach (DataRow row in schema.Rows)
61+
{
62+
list.Add(row["name"].ToString());
63+
}
64+
}
65+
4366
private static DataTable DescribeTables(DbConnection connection, string database)
4467
{
4568
var command = connection.CreateCommand();
@@ -70,6 +93,13 @@ public override string[] GetTableNames()
7093
return list.ToArray();
7194
}
7295

96+
public override async Task<string[]> GetTableNamesAsync(CancellationToken cancellationToken = default)
97+
{
98+
List<string> list = new List<string>();
99+
await GetDBObjectNamesAsync("Tables", list, cancellationToken);
100+
return list.ToArray();
101+
}
102+
73103
public override DbDataAdapter GetAdapter(string selectCommand, DbConnection connection, CommandParameterCollection parameters)
74104
{
75105
ClickHouseDataAdapter clickHouseDataAdapter = new ClickHouseDataAdapter();
@@ -94,7 +124,7 @@ private string PrepareSelectCommand(string selectCommand, string tableName, DbCo
94124
return selectCommand;
95125
}
96126

97-
private IEnumerable<DataColumn> GetColumns(ClickHouseDataReader reader)
127+
private static IEnumerable<DataColumn> GetColumns(ClickHouseDataReader reader)
98128
{
99129
for (int i = 0; i < reader.FieldCount; i++)
100130
{
@@ -112,29 +142,7 @@ public override void FillTableSchema(DataTable table, string selectCommand, Comm
112142
{
113143
OpenConnection(clickHouseConnection);
114144

115-
selectCommand = PrepareSelectCommand(selectCommand, table.TableName, clickHouseConnection);
116-
/*To reduce size of traffic and size of answer from ClickHouse server.
117-
Because FillSchema doesn't work in this ADO.NET library.
118-
LIMIT 0 gets an empty set, but we still have list of desired columns
119-
Probably can be a better way.
120-
*/
121-
selectCommand += " LIMIT 0";
122-
ClickHouseCommand clickHouseCommand = clickHouseConnection.CreateCommand();
123-
124-
foreach (CommandParameter p in parameters)
125-
{
126-
selectCommand = selectCommand.Replace($"@{p.Name}", $"{{{p.Name}:{(ClickHouseTypeCode)p.DataType}}}");
127-
if (p.Value is Variant value)
128-
{
129-
if (value.Type == typeof(string))
130-
clickHouseCommand.AddParameter(p.Name, ((ClickHouseTypeCode)p.DataType).ToString(), VariantToClrType(value, (ClickHouseTypeCode)p.DataType));
131-
else
132-
clickHouseCommand.AddParameter(p.Name, ((ClickHouseTypeCode)p.DataType).ToString(), value.ToType(value.Type));
133-
}
134-
else
135-
clickHouseCommand.AddParameter(p.Name, ((ClickHouseTypeCode)p.DataType).ToString(), p.Value);
136-
}
137-
clickHouseCommand.CommandText = selectCommand;
145+
var clickHouseCommand = FillTableSchemaShared(table, selectCommand, parameters, clickHouseConnection);
138146
using (ClickHouseDataReader reader = clickHouseCommand.ExecuteReader() as ClickHouseDataReader)
139147
{
140148
var clms = GetColumns(reader);
@@ -147,7 +155,57 @@ Probably can be a better way.
147155
}
148156
}
149157

150-
private object VariantToClrType(Variant value, ClickHouseTypeCode type)
158+
public override async Task FillTableSchemaAsync(DataTable table, string selectCommand, CommandParameterCollection parameters,
159+
CancellationToken cancellationToken = default)
160+
{
161+
ClickHouseConnection clickHouseConnection = GetConnection() as ClickHouseConnection;
162+
163+
try
164+
{
165+
await OpenConnectionAsync(clickHouseConnection, cancellationToken);
166+
167+
var clickHouseCommand = FillTableSchemaShared(table, selectCommand, parameters, clickHouseConnection);
168+
using (ClickHouseDataReader reader = await clickHouseCommand.ExecuteReaderAsync(cancellationToken) as ClickHouseDataReader)
169+
{
170+
var clms = GetColumns(reader);
171+
table.Columns.AddRange(clms.ToArray());
172+
}
173+
}
174+
finally
175+
{
176+
await DisposeConnectionAsync(clickHouseConnection);
177+
}
178+
}
179+
180+
private ClickHouseCommand FillTableSchemaShared(DataTable table, string selectCommand, CommandParameterCollection parameters, ClickHouseConnection clickHouseConnection)
181+
{
182+
selectCommand = PrepareSelectCommand(selectCommand, table.TableName, clickHouseConnection);
183+
/*To reduce size of traffic and size of answer from ClickHouse server.
184+
Because FillSchema doesn't work in this ADO.NET library.
185+
LIMIT 0 gets an empty set, but we still have list of desired columns
186+
Probably can be a better way.
187+
*/
188+
selectCommand += " LIMIT 0";
189+
ClickHouseCommand clickHouseCommand = clickHouseConnection.CreateCommand();
190+
191+
foreach (CommandParameter p in parameters)
192+
{
193+
selectCommand = selectCommand.Replace($"@{p.Name}", $"{{{p.Name}:{(ClickHouseTypeCode)p.DataType}}}");
194+
if (p.Value is Variant value)
195+
{
196+
if (value.Type == typeof(string))
197+
clickHouseCommand.AddParameter(p.Name, ((ClickHouseTypeCode)p.DataType).ToString(), VariantToClrType(value, (ClickHouseTypeCode)p.DataType));
198+
else
199+
clickHouseCommand.AddParameter(p.Name, ((ClickHouseTypeCode)p.DataType).ToString(), value.ToType(value.Type));
200+
}
201+
else
202+
clickHouseCommand.AddParameter(p.Name, ((ClickHouseTypeCode)p.DataType).ToString(), p.Value);
203+
}
204+
clickHouseCommand.CommandText = selectCommand;
205+
return clickHouseCommand;
206+
}
207+
208+
private static object VariantToClrType(Variant value, ClickHouseTypeCode type)
151209
{
152210
if (value.ToString() == "" && type != ClickHouseTypeCode.Nothing)
153211
return null;
@@ -157,88 +215,74 @@ private object VariantToClrType(Variant value, ClickHouseTypeCode type)
157215
case ClickHouseTypeCode.Enum8:
158216
case ClickHouseTypeCode.Int8:
159217
{
160-
sbyte val = 0;
161-
sbyte.TryParse(value.ToString(), out val);
218+
sbyte.TryParse(value.ToString(), out var val);
162219
return val;
163220
}
164221
case ClickHouseTypeCode.Enum16:
165222
case ClickHouseTypeCode.Int16:
166223
{
167-
short val = 0;
168-
short.TryParse(value.ToString(), out val);
224+
short.TryParse(value.ToString(), out var val);
169225
return val;
170226
}
171227
case ClickHouseTypeCode.Int32:
172228
{
173-
int val = 0;
174-
int.TryParse(value.ToString(), out val);
229+
int.TryParse(value.ToString(), out var val);
175230
return val;
176231
}
177232
case ClickHouseTypeCode.Int64:
178233
{
179-
long val = 0;
180-
long.TryParse(value.ToString(), out val);
234+
long.TryParse(value.ToString(), out var val);
181235
return val;
182236
}
183237
case ClickHouseTypeCode.UInt8:
184238
{
185-
byte val = 0;
186-
byte.TryParse(value.ToString(), out val);
239+
byte.TryParse(value.ToString(), out var val);
187240
return val;
188241
}
189242
case ClickHouseTypeCode.UInt16:
190243
{
191-
ushort val = 0;
192-
ushort.TryParse(value.ToString(), out val);
244+
ushort.TryParse(value.ToString(), out var val);
193245
return val;
194246
}
195247
case ClickHouseTypeCode.UInt32:
196248
{
197-
uint val = 0;
198-
uint.TryParse(value.ToString(), out val);
249+
uint.TryParse(value.ToString(), out var val);
199250
return val;
200251
}
201252
case ClickHouseTypeCode.UInt64:
202253
{
203-
ulong val = 0;
204-
ulong.TryParse(value.ToString(), out val);
254+
ulong.TryParse(value.ToString(), out var val);
205255
return val;
206256
}
207257
case ClickHouseTypeCode.Date:
208258
{
209-
DateTime val = DateTime.Now;
210-
DateTime.TryParse(value.ToString(), out val);
259+
DateTime.TryParse(value.ToString(), out var val);
211260
return val;
212261
}
213262
case ClickHouseTypeCode.DateTime:
214263
case ClickHouseTypeCode.DateTime64:
215264
{
216-
DateTimeOffset val = DateTimeOffset.Now;
217-
DateTimeOffset.TryParse(value.ToString(), out val);
265+
DateTimeOffset.TryParse(value.ToString(), out var val);
218266
return val;
219267
}
220268
case ClickHouseTypeCode.Decimal:
221269
{
222-
decimal val = 0;
223-
decimal.TryParse(value.ToString(), out val);
270+
decimal.TryParse(value.ToString(), out var val);
224271
return val;
225272
}
226273
case ClickHouseTypeCode.Float32:
227274
{
228-
float val = 0;
229-
float.TryParse(value.ToString(), out val);
275+
float.TryParse(value.ToString(), out var val);
230276
return val;
231277
}
232278
case ClickHouseTypeCode.Float64:
233279
{
234-
double val = 0;
235-
double.TryParse(value.ToString(), out val);
280+
double.TryParse(value.ToString(), out var val);
236281
return val;
237282
}
238283
case ClickHouseTypeCode.UUID:
239284
{
240-
Guid val = Guid.Empty;
241-
Guid.TryParse(value.ToString(), out val);
285+
Guid.TryParse(value.ToString(), out var val);
242286
return val;
243287
}
244288
case ClickHouseTypeCode.IPv6:

0 commit comments

Comments
 (0)