1212using System . Linq ;
1313using System . Net ;
1414using System . Text ;
15+ using System . Threading ;
1516using System . Threading . Tasks ;
1617
1718namespace 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