|
1 |
| -using System; |
| 1 | +using System; |
2 | 2 | using System.Collections;
|
3 | 3 | using System.Collections.Generic;
|
4 | 4 | using System.Data;
|
5 | 5 | using System.Data.Common;
|
| 6 | +using System.Globalization; |
6 | 7 | using System.Threading;
|
7 | 8 | using System.Threading.Tasks;
|
8 | 9 | using MySql.Data.MySqlClient.Results;
|
@@ -202,7 +203,15 @@ public override long GetChars(int ordinal, long dataOffset, char[] buffer, int b
|
202 | 203 | public override int VisibleFieldCount => FieldCount;
|
203 | 204 |
|
204 | 205 | #if !NETSTANDARD1_3
|
205 |
| - public override DataTable GetSchemaTable() => throw new NotSupportedException(); |
| 206 | + public override DataTable GetSchemaTable() |
| 207 | + { |
| 208 | + if (m_schemaTable == null) |
| 209 | + { |
| 210 | + m_schemaTable = BuildSchemaTable(); |
| 211 | + } |
| 212 | + |
| 213 | + return m_schemaTable; |
| 214 | + } |
206 | 215 |
|
207 | 216 | public override void Close()
|
208 | 217 | {
|
@@ -270,6 +279,104 @@ internal async Task ReadFirstResultSetAsync(IOBehavior ioBehavior)
|
270 | 279 | m_resultSetBuffered = m_resultSet;
|
271 | 280 | }
|
272 | 281 |
|
| 282 | +#if !NETSTANDARD1_3 |
| 283 | + internal DataTable BuildSchemaTable() |
| 284 | + { |
| 285 | + var colDefinitions = GetResultSet().ColumnDefinitions; |
| 286 | + DataTable schemaTable = new DataTable("SchemaTable"); |
| 287 | + schemaTable.Locale = CultureInfo.InvariantCulture; |
| 288 | + schemaTable.MinimumCapacity = colDefinitions.Length; |
| 289 | + |
| 290 | + var columnName = new DataColumn(SchemaTableColumn.ColumnName, typeof(string)); |
| 291 | + var ordinal = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(int)); |
| 292 | + var size = new DataColumn(SchemaTableColumn.ColumnSize, typeof(int)); |
| 293 | + var precision = new DataColumn(SchemaTableColumn.NumericPrecision, typeof(int)); |
| 294 | + var scale = new DataColumn(SchemaTableColumn.NumericScale, typeof(int)); |
| 295 | + var dataType = new DataColumn(SchemaTableColumn.DataType, typeof(System.Type)); |
| 296 | + var providerType = new DataColumn(SchemaTableColumn.ProviderType, typeof(int)); |
| 297 | + var isLong = new DataColumn(SchemaTableColumn.IsLong, typeof(bool)); |
| 298 | + var allowDBNull = new DataColumn(SchemaTableColumn.AllowDBNull, typeof(bool)); |
| 299 | + var isReadOnly = new DataColumn(SchemaTableOptionalColumn.IsReadOnly, typeof(bool)); |
| 300 | + var isRowVersion = new DataColumn(SchemaTableOptionalColumn.IsRowVersion, typeof(bool)); |
| 301 | + var isUnique = new DataColumn(SchemaTableColumn.IsUnique, typeof(bool)); |
| 302 | + var isKey = new DataColumn(SchemaTableColumn.IsKey, typeof(bool)); |
| 303 | + var isAutoIncrement = new DataColumn(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool)); |
| 304 | + var isHidden = new DataColumn(SchemaTableOptionalColumn.IsHidden, typeof(bool)); |
| 305 | + var baseCatalogName = new DataColumn(SchemaTableOptionalColumn.BaseCatalogName, typeof(string)); |
| 306 | + var baseSchemaName = new DataColumn(SchemaTableColumn.BaseSchemaName, typeof(string)); |
| 307 | + var baseTableName = new DataColumn(SchemaTableColumn.BaseTableName, typeof(string)); |
| 308 | + var baseColumnName = new DataColumn(SchemaTableColumn.BaseColumnName, typeof(string)); |
| 309 | + var isAliased = new DataColumn(SchemaTableColumn.IsAliased, typeof(bool)); |
| 310 | + var isExpression = new DataColumn(SchemaTableColumn.IsExpression, typeof(bool)); |
| 311 | + var isIdentity = new DataColumn("IsIdentity", typeof(bool)); |
| 312 | + ordinal.DefaultValue = 0; |
| 313 | + precision.DefaultValue = 0; |
| 314 | + scale.DefaultValue = 0; |
| 315 | + isLong.DefaultValue = false; |
| 316 | + |
| 317 | + // must maintain order for backward compatibility |
| 318 | + var columns = schemaTable.Columns; |
| 319 | + columns.Add(columnName); |
| 320 | + columns.Add(ordinal); |
| 321 | + columns.Add(size); |
| 322 | + columns.Add(precision); |
| 323 | + columns.Add(scale); |
| 324 | + columns.Add(isUnique); |
| 325 | + columns.Add(isKey); |
| 326 | + columns.Add(baseCatalogName); |
| 327 | + columns.Add(baseColumnName); |
| 328 | + columns.Add(baseSchemaName); |
| 329 | + columns.Add(baseTableName); |
| 330 | + columns.Add(dataType); |
| 331 | + columns.Add(allowDBNull); |
| 332 | + columns.Add(providerType); |
| 333 | + columns.Add(isAliased); |
| 334 | + columns.Add(isExpression); |
| 335 | + columns.Add(isIdentity); |
| 336 | + columns.Add(isAutoIncrement); |
| 337 | + columns.Add(isRowVersion); |
| 338 | + columns.Add(isHidden); |
| 339 | + columns.Add(isLong); |
| 340 | + columns.Add(isReadOnly); |
| 341 | + |
| 342 | + for (var i = 0; i < colDefinitions.Length; ++i) |
| 343 | + { |
| 344 | + var col = colDefinitions[i]; |
| 345 | + var schemaRow = schemaTable.NewRow(); |
| 346 | + schemaRow[columnName] = col.Name; |
| 347 | + schemaRow[ordinal] = i + 1; // https://bugs.mysql.com/bug.php?id=61477 |
| 348 | + schemaRow[dataType] = GetFieldType(i); |
| 349 | + schemaRow[size] = (Type)schemaRow[dataType] == typeof(string) || (Type)schemaRow[dataType] == typeof(Guid) ? |
| 350 | + col.ColumnLength / SerializationUtility.GetBytesPerCharacter(col.CharacterSet) : |
| 351 | + col.ColumnLength; |
| 352 | + schemaRow[providerType] = col.ColumnType; |
| 353 | + schemaRow[isLong] = col.ColumnLength > 255 && ((col.ColumnFlags & ColumnFlags.Blob) != 0 || col.ColumnType.IsBlob()); |
| 354 | + schemaRow[isKey] = (col.ColumnFlags & ColumnFlags.PrimaryKey) != 0; |
| 355 | + schemaRow[allowDBNull] = (col.ColumnFlags & ColumnFlags.NotNull) == 0; |
| 356 | + schemaRow[scale] = col.Decimals; |
| 357 | + if (col.ColumnType.IsDecimal()) |
| 358 | + { |
| 359 | + schemaRow[precision] = col.ColumnLength - 2 + ((col.ColumnFlags & ColumnFlags.Unsigned) != 0 ? 1 : 0); |
| 360 | + } |
| 361 | + |
| 362 | + schemaRow[baseSchemaName] = col.SchemaName; |
| 363 | + schemaRow[baseTableName] = col.PhysicalTable; |
| 364 | + schemaRow[baseColumnName] = col.PhysicalName; |
| 365 | + schemaRow[isUnique] = false; |
| 366 | + schemaRow[isRowVersion] = false; |
| 367 | + schemaRow[isReadOnly] = false; |
| 368 | + |
| 369 | + // To be consist with Orcale MySQL connector, set baseCatelogName to null and do not set isAliased, isExpression, isIdentity, isHidden value. |
| 370 | + schemaRow[baseCatalogName] = null; |
| 371 | + |
| 372 | + schemaTable.Rows.Add(schemaRow); |
| 373 | + schemaRow.AcceptChanges(); |
| 374 | + } |
| 375 | + |
| 376 | + return schemaTable; |
| 377 | + } |
| 378 | +#endif |
| 379 | + |
273 | 380 | private MySqlDataReader(MySqlCommand command, CommandBehavior behavior)
|
274 | 381 | {
|
275 | 382 | Command = command;
|
@@ -328,6 +435,9 @@ private ResultSet GetResultSet()
|
328 | 435 | int m_recordsAffected;
|
329 | 436 | ResultSet m_resultSet;
|
330 | 437 | ResultSet m_resultSetBuffered;
|
| 438 | +#if !NETSTANDARD1_3 |
| 439 | + DataTable m_schemaTable; |
| 440 | +#endif |
331 | 441 | readonly Queue<ResultSet> m_nextResultSetBuffer = new Queue<ResultSet>();
|
332 | 442 | }
|
333 | 443 | }
|
0 commit comments