1+ using System . Collections . Immutable ;
12using System . Data ;
23using System . Data . Common ;
4+ using System . Globalization ;
35using Ydb . Scheme ;
46using Ydb . Scheme . V1 ;
57using Ydb . Sdk . Services . Table ;
@@ -28,6 +30,7 @@ public static Task<DataTable> GetSchemaAsync(
2830
2931 // Ydb specific Schema Collections
3032 "TABLES" => GetTables ( ydbConnection , restrictions , cancellationToken ) ,
33+ "COLUMNS" => GetColumns ( ydbConnection , restrictions , cancellationToken ) ,
3134 "TABLESWITHSTATS" => GetTablesWithStats ( ydbConnection , restrictions , cancellationToken ) ,
3235
3336 _ => throw new ArgumentOutOfRangeException ( nameof ( collectionName ) , collectionName ,
@@ -40,18 +43,24 @@ private static async Task<DataTable> GetTables(
4043 string ? [ ] restrictions ,
4144 CancellationToken cancellationToken )
4245 {
43- var table = new DataTable ( "Tables" ) ;
44- table . Columns . Add ( "table_name" , typeof ( string ) ) ;
45- table . Columns . Add ( "table_type" , typeof ( string ) ) ;
46+ var table = new DataTable ( "Tables" )
47+ {
48+ Locale = CultureInfo . InvariantCulture ,
49+ Columns =
50+ {
51+ new DataColumn ( "table_name" ) ,
52+ new DataColumn ( "table_type" )
53+ }
54+ } ;
4655
4756 var tableName = restrictions [ 0 ] ;
4857 var tableType = restrictions [ 1 ] ;
4958 var database = ydbConnection . Database ;
5059
5160 if ( tableName == null ) // tableName isn't set
5261 {
53- foreach ( var tupleTable in await ListTables ( ydbConnection . Session . Driver ,
54- WithSuffix ( database ) , database , tableType , cancellationToken ) )
62+ foreach ( var tupleTable in
63+ await ListTables ( ydbConnection , WithSuffix ( database ) , database , tableType , cancellationToken ) )
5564 {
5665 table . Rows . Add ( tupleTable . TableName , tupleTable . TableType ) ;
5766 }
@@ -61,7 +70,6 @@ private static async Task<DataTable> GetTables(
6170 await AppendDescribeTable (
6271 ydbConnection : ydbConnection ,
6372 describeTableSettings : new DescribeTableSettings { CancellationToken = cancellationToken } ,
64- database : database ,
6573 tableName : tableName ,
6674 tableType : tableType ,
6775 ( _ , type ) => { table . Rows . Add ( tableName , type ) ; } ) ;
@@ -75,27 +83,32 @@ private static async Task<DataTable> GetTablesWithStats(
7583 string ? [ ] restrictions ,
7684 CancellationToken cancellationToken )
7785 {
78- var table = new DataTable ( "TablesWithStats" ) ;
79- table . Columns . Add ( "table_name" , typeof ( string ) ) ;
80- table . Columns . Add ( "table_type" , typeof ( string ) ) ;
81- table . Columns . Add ( "rows_estimate" , typeof ( ulong ) ) ;
82- table . Columns . Add ( "creation_time" , typeof ( DateTime ) ) ;
83- table . Columns . Add ( "modification_time" , typeof ( DateTime ) ) ;
86+ var table = new DataTable ( "TablesWithStats" )
87+ {
88+ Locale = CultureInfo . InvariantCulture ,
89+ Columns =
90+ {
91+ new DataColumn ( "table_name" ) ,
92+ new DataColumn ( "table_type" ) ,
93+ new DataColumn ( "rows_estimate" , typeof ( ulong ) ) ,
94+ new DataColumn ( "creation_time" , typeof ( DateTime ) ) ,
95+ new DataColumn ( "modification_time" , typeof ( DateTime ) )
96+ }
97+ } ;
8498
8599 var tableName = restrictions [ 0 ] ;
86100 var tableType = restrictions [ 1 ] ;
87101 var database = ydbConnection . Database ;
88102
89103 if ( tableName == null ) // tableName isn't set
90104 {
91- foreach ( var tupleTable in await ListTables ( ydbConnection . Session . Driver ,
92- WithSuffix ( database ) , database , tableType , cancellationToken ) )
105+ foreach ( var tupleTable in
106+ await ListTables ( ydbConnection , WithSuffix ( database ) , database , tableType , cancellationToken ) )
93107 {
94108 await AppendDescribeTable (
95109 ydbConnection : ydbConnection ,
96110 describeTableSettings : new DescribeTableSettings { CancellationToken = cancellationToken }
97111 . WithTableStats ( ) ,
98- database : database ,
99112 tableName : tupleTable . TableName ,
100113 tableType : tableType ,
101114 ( describeTableResult , type ) =>
@@ -117,7 +130,6 @@ await AppendDescribeTable(
117130 ydbConnection : ydbConnection ,
118131 describeTableSettings : new DescribeTableSettings { CancellationToken = cancellationToken }
119132 . WithTableStats ( ) ,
120- database : database ,
121133 tableName : tableName ,
122134 tableType : tableType ,
123135 ( describeTableResult , type ) =>
@@ -136,18 +148,74 @@ await AppendDescribeTable(
136148 return table ;
137149 }
138150
151+ private static async Task < DataTable > GetColumns (
152+ YdbConnection ydbConnection ,
153+ string ? [ ] restrictions ,
154+ CancellationToken cancellationToken )
155+ {
156+ var table = new DataTable ( "Columns" )
157+ {
158+ Locale = CultureInfo . InvariantCulture ,
159+ Columns =
160+ {
161+ new DataColumn ( "table_name" ) ,
162+ new DataColumn ( "column_name" ) ,
163+ new DataColumn ( "ordinal_position" , typeof ( int ) ) ,
164+ new DataColumn ( "is_nullable" ) ,
165+ new DataColumn ( "data_type" ) ,
166+ new DataColumn ( "family_name" )
167+ }
168+ } ;
169+ var tableNameRestriction = restrictions [ 0 ] ;
170+ var columnName = restrictions [ 1 ] ;
171+
172+ var tableNames = await ListTableNames ( ydbConnection , tableNameRestriction , cancellationToken ) ;
173+ foreach ( var tableName in tableNames )
174+ {
175+ await AppendDescribeTable (
176+ ydbConnection ,
177+ new DescribeTableSettings { CancellationToken = cancellationToken } ,
178+ tableName ,
179+ null ,
180+ ( result , _ ) =>
181+ {
182+ for ( var ordinal = 0 ; ordinal < result . Columns . Count ; ordinal ++ )
183+ {
184+ var column = result . Columns [ ordinal ] ;
185+
186+ if ( ! column . Name . IsPattern ( columnName ) )
187+ {
188+ continue ;
189+ }
190+
191+ var row = table . Rows . Add ( ) ;
192+ var type = column . Type ;
193+
194+ row [ "table_name" ] = tableName ;
195+ row [ "column_name" ] = column . Name ;
196+ row [ "ordinal_position" ] = ordinal ;
197+ row [ "is_nullable" ] = type . TypeCase == Type . TypeOneofCase . OptionalType ? "YES" : "NO" ;
198+ row [ "data_type" ] = type . YqlTableType ( ) ;
199+ row [ "family_name" ] = column . Family ;
200+ }
201+ }
202+ ) ;
203+ }
204+
205+ return table ;
206+ }
207+
139208 private static async Task AppendDescribeTable (
140209 YdbConnection ydbConnection ,
141210 DescribeTableSettings describeTableSettings ,
142- string database ,
143211 string tableName ,
144212 string ? tableType ,
145213 Action < DescribeTableResult , string > appendInTable )
146214 {
147215 try
148216 {
149217 var describeResponse = await ydbConnection . Session
150- . DescribeTable ( WithSuffix ( database ) + tableName , describeTableSettings ) ;
218+ . DescribeTable ( WithSuffix ( ydbConnection . Database ) + tableName , describeTableSettings ) ;
151219
152220 if ( describeResponse . Operation . Status == StatusIds . Types . StatusCode . SchemeError )
153221 {
@@ -174,7 +242,7 @@ private static async Task AppendDescribeTable(
174242 _ => throw new YdbException ( $ "Unexpected entry type for Table: { describeRes . Self . Type } ")
175243 } ;
176244
177- if ( type . IsTableType ( tableType ) )
245+ if ( type . IsPattern ( tableType ) )
178246 {
179247 appendInTable ( describeRes , type ) ;
180248 }
@@ -187,8 +255,26 @@ private static async Task AppendDescribeTable(
187255 }
188256 }
189257
190- private static async Task < List < ( string TableName , string TableType ) > > ListTables (
191- Driver driver ,
258+ private static async Task < IReadOnlyCollection < string > > ListTableNames (
259+ YdbConnection ydbConnection ,
260+ string ? tableName ,
261+ CancellationToken cancellationToken )
262+ {
263+ var database = ydbConnection . Database ;
264+
265+ return tableName != null
266+ ? new List < string > { tableName }
267+ : ( await ListTables (
268+ ydbConnection ,
269+ WithSuffix ( database ) ,
270+ database ,
271+ null ,
272+ cancellationToken
273+ ) ) . Select ( tuple => tuple . TableName ) . ToImmutableList ( ) ;
274+ }
275+
276+ private static async Task < IReadOnlyCollection < ( string TableName , string TableType ) > > ListTables (
277+ YdbConnection ydbConnection ,
192278 string databasePath ,
193279 string path ,
194280 string ? tableType ,
@@ -198,7 +284,7 @@ private static async Task AppendDescribeTable(
198284 {
199285 var fullPath = WithSuffix ( path ) ;
200286 var tables = new List < ( string , string ) > ( ) ;
201- var response = await driver . UnaryCall (
287+ var response = await ydbConnection . Session . Driver . UnaryCall (
202288 SchemeService . ListDirectoryMethod ,
203289 new ListDirectoryRequest { Path = fullPath } ,
204290 new GrpcRequestSettings { CancellationToken = cancellationToken }
@@ -220,22 +306,23 @@ private static async Task AppendDescribeTable(
220306 {
221307 case Entry . Types . Type . Table :
222308 var type = tablePath . IsSystem ( ) ? "SYSTEM_TABLE" : "TABLE" ;
223- if ( type . IsTableType ( tableType ) )
309+ if ( type . IsPattern ( tableType ) )
224310 {
225311 tables . Add ( ( tablePath , type ) ) ;
226312 }
227313
228314 break ;
229315 case Entry . Types . Type . ColumnTable :
230- if ( "COLUMN_TABLE" . IsTableType ( tableType ) )
316+ if ( "COLUMN_TABLE" . IsPattern ( tableType ) )
231317 {
232318 tables . Add ( ( tablePath , "COLUMN_TABLE" ) ) ;
233319 }
234320
235321 break ;
236322 case Entry . Types . Type . Directory :
237323 tables . AddRange (
238- await ListTables ( driver , databasePath , fullPath + entry . Name , tableType , cancellationToken )
324+ await ListTables ( ydbConnection , databasePath , fullPath + entry . Name , tableType ,
325+ cancellationToken )
239326 ) ;
240327 break ;
241328 case Entry . Types . Type . Unspecified :
@@ -333,6 +420,7 @@ private static DataTable GetMetaDataCollections()
333420 // Ydb Specific Schema Collections
334421 table . Rows . Add ( "Tables" , 2 , 1 ) ;
335422 table . Rows . Add ( "TablesWithStats" , 2 , 1 ) ;
423+ table . Rows . Add ( "Columns" , 2 , 2 ) ;
336424
337425 return table ;
338426 }
@@ -350,6 +438,8 @@ private static DataTable GetRestrictions()
350438 table . Rows . Add ( "Tables" , "TableType" , "TABLE_TYPE" , 2 ) ;
351439 table . Rows . Add ( "TablesWithStats" , "Table" , "TABLE_NAME" , 1 ) ;
352440 table . Rows . Add ( "TablesWithStats" , "TableType" , "TABLE_TYPE" , 2 ) ;
441+ table . Rows . Add ( "Columns" , "Table" , "TABLE_NAME" , 1 ) ;
442+ table . Rows . Add ( "Columns" , "Column" , "COLUMN_NAME" , 2 ) ;
353443
354444 return table ;
355445 }
@@ -366,8 +456,15 @@ private static bool IsSystem(this string tablePath)
366456 || tablePath . StartsWith ( ".sys_health_dev/" ) ;
367457 }
368458
369- private static bool IsTableType ( this string tableType , string ? expectedTableType )
459+ private static bool IsPattern ( this string tableType , string ? expectedTableType )
370460 {
371461 return expectedTableType == null || expectedTableType . Equals ( tableType , StringComparison . OrdinalIgnoreCase ) ;
372462 }
463+
464+ internal static string YqlTableType ( this Type type )
465+ {
466+ return type . TypeCase == Type . TypeOneofCase . OptionalType
467+ ? type . OptionalType . Item . TypeId . ToString ( )
468+ : type . TypeId . ToString ( ) ;
469+ }
373470}
0 commit comments