Skip to content

Commit 5ad78a5

Browse files
committed
Move GetSchema code to new SchemaProvider class.
Also add MetaDataCollections schema listing available schema collections.
1 parent 6c5f42f commit 5ad78a5

File tree

2 files changed

+119
-85
lines changed

2 files changed

+119
-85
lines changed

src/MySqlConnector/MySqlClient/MySqlConnection.cs

Lines changed: 12 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -217,96 +217,23 @@ private static async Task ClearPoolAsync(MySqlConnection connection, IOBehavior
217217
#if !NETSTANDARD1_3
218218
protected override DbProviderFactory DbProviderFactory => MySqlClientFactory.Instance;
219219

220-
/// <summary>
221-
/// System.Data.Common, initial implementation of API DBConnection.GetSchema(String)
222-
/// Returns schema information for the data source of this DbConnection using the specified string for the schema name.
223-
/// </summary>
224-
/// <param name="collectionName">Specifies the name of the schema to return.</param>
225-
/// <returns>A DataTable that contains schema information.</returns>
226-
public override System.Data.DataTable GetSchema(string collectionName)
227-
{
228-
return GetSchema(collectionName, null);
229-
}
220+
/// <inheritdoc cref="DbConnection.GetSchema()"/>
221+
public override DataTable GetSchema() => GetSchemaProvider().GetSchema();
230222

231-
232-
/// <summary>
233-
/// System.Data.Common, initial implementation of API DBConnection.GetSchema(String)
234-
/// Returns schema information for the data source of this DbConnection using the specified string for the schema name.
235-
/// </summary>
236-
/// <param name="collectionName">Specifies the name of the schema to return.</param>
237-
/// <param name="restrictions">Restrictions not supported yet.</param>
238-
/// <returns>A DataTable that contains schema information.</returns>
239-
public override System.Data.DataTable GetSchema(string collectionName, string[] restrictions)
240-
{
241-
var dt = new DataTable(collectionName);
242-
switch (collectionName)
243-
{
244-
case "DataTypes":
245-
dt.Columns.AddRange(new[] { // The names come from DbMetaDataColumnNames
246-
new DataColumn("DataType", typeof(string)),
247-
new DataColumn("TypeName", typeof(string)),
248-
new DataColumn("ProviderDbType", typeof(int)),
249-
new DataColumn("IsUnsigned", typeof(bool))
250-
});
251-
252-
// Column type mappings:
253-
var colTypes = Types.TypeMapper.Instance.GetColumnMappings();
254-
foreach (var map in colTypes)
255-
{
256-
var dbTypeMap = map.DbTypeMapping;
257-
var dbType = dbTypeMap.DbTypes.FirstOrDefault();
258-
dt.Rows.Add(new object[] {
259-
dbTypeMap.ClrType.FullName,
260-
map.DataTypeName,
261-
(int)dbType,
262-
map.Unsigned
263-
});
264-
}
223+
/// <inheritdoc cref="DbConnection.GetSchema(string)"/>
224+
public override DataTable GetSchema(string collectionName) => GetSchemaProvider().GetSchema(collectionName);
265225

266-
// Data type mappings:
267-
foreach (MySqlDbType mapItem in Enum.GetValues(typeof(MySqlDbType)))
268-
{
269-
var typeName = Enum.GetName(typeof(MySqlDbType), mapItem);
270-
var dbType = Types.TypeMapper.Instance.GetDbTypeForMySqlDbType(mapItem);
271-
var map = Types.TypeMapper.Instance.GetDbTypeMapping(dbType);
272-
if (map != null) // MySqlDbType.Set is not supported by the mapper.
273-
{
274-
dt.Rows.Add(new object[] {
275-
map.ClrType.FullName,
276-
Enum.GetName(typeof(MySqlDbType), mapItem).ToLower(),
277-
(int)dbType,
278-
typeName.Contains("UInt") || typeName.Contains("UByte")
279-
});
280-
}
281-
}
282-
return dt;
283-
284-
case "Procedures":
285-
dt.Columns.AddRange(new[] {
286-
new DataColumn("ROUTINE_TYPE"),
287-
new DataColumn("ROUTINE_SCHEMA"),
288-
new DataColumn("SPECIFIC_NAME")
289-
});
290-
var procsQuery = "SELECT ROUTINE_TYPE, ROUTINE_SCHEMA, SPECIFIC_NAME FROM INFORMATION_SCHEMA.ROUTINES;";
291-
if (m_connectionState != ConnectionState.Open)
292-
{
293-
Open();
294-
}
295-
using (var com = new MySqlCommand(procsQuery, this))
296-
using (var reader = com.ExecuteReader())
297-
{
298-
while (reader.Read())
299-
{
300-
dt.Rows.Add(new object[] { reader.GetString(0), reader.GetString(1), reader.GetString(2) });
301-
}
302-
}
303-
return dt;
226+
/// <inheritdoc cref="DbConnection.GetSchema(string)"/>
227+
public override DataTable GetSchema(string collectionName, string[] restrictions) => GetSchemaProvider().GetSchema(collectionName);
304228

305-
default:
306-
throw new NotImplementedException("Not yet supported: GetSchema(\"" + collectionName + "\"). Please send a PR.");
307-
}
229+
private SchemaProvider GetSchemaProvider()
230+
{
231+
if (m_schemaProvider == null)
232+
m_schemaProvider = new SchemaProvider(this);
233+
return m_schemaProvider;
308234
}
309235

236+
SchemaProvider m_schemaProvider;
310237
#endif
311238

312239
public override int ConnectionTimeout => m_connectionSettings.ConnectionTimeout;
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#if !NETSTANDARD1_3
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Data;
5+
using System.Linq;
6+
7+
namespace MySql.Data.MySqlClient
8+
{
9+
internal sealed class SchemaProvider
10+
{
11+
public SchemaProvider(MySqlConnection connection)
12+
{
13+
m_connection = connection;
14+
m_schemaCollections = new Dictionary<string, Action<DataTable>>
15+
{
16+
{ "MetaDataCollections", FillMetadataCollections },
17+
{ "DataTypes", FillDataTypes },
18+
{ "Procedures", FillProcedures }
19+
};
20+
}
21+
22+
public DataTable GetSchema() => GetSchema("MetaDataCollections");
23+
24+
public DataTable GetSchema(string collectionName)
25+
{
26+
if (!m_schemaCollections.TryGetValue(collectionName, out var fillAction))
27+
throw new ArgumentException("Invalid collection name.", nameof(collectionName));
28+
29+
var dataTable = new DataTable(collectionName);
30+
fillAction(dataTable);
31+
return dataTable;
32+
}
33+
34+
private void FillMetadataCollections(DataTable dataTable)
35+
{
36+
dataTable.Columns.AddRange(new[] {
37+
new DataColumn("CollectionName", typeof(string)),
38+
new DataColumn("NumberOfRestrictions", typeof(int)),
39+
new DataColumn("NumberOfIdentifierParts", typeof(int))
40+
});
41+
42+
foreach (var collectionName in m_schemaCollections.Keys)
43+
dataTable.Rows.Add(collectionName, 0, 0);
44+
}
45+
46+
private void FillDataTypes(DataTable dataTable)
47+
{
48+
dataTable.Columns.AddRange(new[] { // The names come from DbMetaDataColumnNames
49+
new DataColumn("DataType", typeof(string)),
50+
new DataColumn("TypeName", typeof(string)),
51+
new DataColumn("ProviderDbType", typeof(int)),
52+
new DataColumn("IsUnsigned", typeof(bool))
53+
});
54+
55+
// Column type mappings:
56+
var colTypes = Types.TypeMapper.Instance.GetColumnMappings();
57+
foreach (var map in colTypes)
58+
{
59+
var dbTypeMap = map.DbTypeMapping;
60+
var dbType = dbTypeMap.DbTypes.FirstOrDefault();
61+
dataTable.Rows.Add(dbTypeMap.ClrType.FullName, map.DataTypeName, (int)dbType, map.Unsigned);
62+
}
63+
64+
// Data type mappings:
65+
foreach (MySqlDbType mapItem in Enum.GetValues(typeof(MySqlDbType)))
66+
{
67+
var typeName = Enum.GetName(typeof(MySqlDbType), mapItem);
68+
var dbType = Types.TypeMapper.Instance.GetDbTypeForMySqlDbType(mapItem);
69+
var map = Types.TypeMapper.Instance.GetDbTypeMapping(dbType);
70+
if (map != null) // MySqlDbType.Set is not supported by the mapper.
71+
{
72+
dataTable.Rows.Add(map.ClrType.FullName, Enum.GetName(typeof(MySqlDbType), mapItem).ToLower(), (int)dbType, typeName.Contains("UInt") || typeName.Contains("UByte"));
73+
}
74+
}
75+
}
76+
77+
private void FillProcedures(DataTable dataTable)
78+
{
79+
dataTable.Columns.AddRange(new[] {
80+
new DataColumn("ROUTINE_TYPE"),
81+
new DataColumn("ROUTINE_SCHEMA"),
82+
new DataColumn("SPECIFIC_NAME")
83+
});
84+
85+
Action close = null;
86+
if (m_connection.State != ConnectionState.Open)
87+
{
88+
m_connection.Open();
89+
close = m_connection.Close;
90+
}
91+
92+
var procsQuery = "SELECT ROUTINE_TYPE, ROUTINE_SCHEMA, SPECIFIC_NAME FROM INFORMATION_SCHEMA.ROUTINES;";
93+
using (var command = new MySqlCommand(procsQuery, m_connection))
94+
using (var reader = command.ExecuteReader())
95+
{
96+
while (reader.Read())
97+
dataTable.Rows.Add(reader.GetString(0), reader.GetString(1), reader.GetString(2));
98+
}
99+
100+
close?.Invoke();
101+
}
102+
103+
readonly MySqlConnection m_connection;
104+
readonly Dictionary<string, Action<DataTable>> m_schemaCollections;
105+
}
106+
}
107+
#endif

0 commit comments

Comments
 (0)