Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 44c1ce7

Browse files
authored
Porting Sqlconnection.GetSchema (PR #19937) (#20004)
* Porting Sqlconnection.GetSchema (#19937)
1 parent 47032b8 commit 44c1ce7

15 files changed

+3764
-4
lines changed

src/System.Data.SqlClient/ref/System.Data.SqlClient.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,22 @@ internal SqlClientFactory() { }
276276
public override System.Data.Common.DbDataAdapter CreateDataAdapter() { throw null; }
277277
public override System.Data.Common.DbParameter CreateParameter() { throw null; }
278278
}
279+
public static partial class SqlClientMetaDataCollectionNames
280+
{
281+
public static readonly string Columns;
282+
public static readonly string Databases;
283+
public static readonly string ForeignKeys;
284+
public static readonly string IndexColumns;
285+
public static readonly string Indexes;
286+
public static readonly string Parameters;
287+
public static readonly string ProcedureColumns;
288+
public static readonly string Procedures;
289+
public static readonly string Tables;
290+
public static readonly string UserDefinedTypes;
291+
public static readonly string Users;
292+
public static readonly string ViewColumns;
293+
public static readonly string Views;
294+
}
279295
public sealed partial class SqlCommand : System.Data.Common.DbCommand, System.ICloneable
280296
{
281297
public SqlCommand() { }

src/System.Data.SqlClient/src/Resources/Strings.resx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,4 +1051,52 @@
10511051
<data name="SqlProvider_InvalidDataColumnMaxLength" xml:space="preserve">
10521052
<value>The size of column '{0}' is not supported. The size is {1}.</value>
10531053
</data>
1054+
<data name="MDF_InvalidXmlInvalidValue" xml:space="preserve">
1055+
<value>The metadata XML is invalid. The {1} column of the {0} collection must contain a non-empty string.</value>
1056+
</data>
1057+
<data name="MDF_CollectionNameISNotUnique" xml:space="preserve">
1058+
<value>There are multiple collections named '{0}'.</value>
1059+
</data>
1060+
<data name="MDF_InvalidXmlMissingColumn" xml:space="preserve">
1061+
<value>The metadata XML is invalid. The {0} collection must contain a {1} column and it must be a string column.</value>
1062+
</data>
1063+
<data name="MDF_InvalidXml" xml:space="preserve">
1064+
<value>The metadata XML is invalid.</value>
1065+
</data>
1066+
<data name="MDF_NoColumns" xml:space="preserve">
1067+
<value>The schema table contains no columns.</value>
1068+
</data>
1069+
<data name="MDF_QueryFailed" xml:space="preserve">
1070+
<value>Unable to build the '{0}' collection because execution of the SQL query failed. See the inner exception for details.</value>
1071+
</data>
1072+
<data name="MDF_TooManyRestrictions" xml:space="preserve">
1073+
<value>More restrictions were provided than the requested schema ('{0}') supports.</value>
1074+
</data>
1075+
<data name="MDF_DataTableDoesNotExist" xml:space="preserve">
1076+
<value>The collection '{0}' is missing from the metadata XML.</value>
1077+
</data>
1078+
<data name="MDF_UndefinedCollection" xml:space="preserve">
1079+
<value>The requested collection ({0}) is not defined.</value>
1080+
</data>
1081+
<data name="MDF_UnsupportedVersion" xml:space="preserve">
1082+
<value> requested collection ({0}) is not supported by this version of the provider.</value>
1083+
</data>
1084+
<data name="MDF_MissingRestrictionColumn" xml:space="preserve">
1085+
<value>One or more of the required columns of the restrictions collection is missing.</value>
1086+
</data>
1087+
<data name="MDF_MissingRestrictionRow" xml:space="preserve">
1088+
<value>A restriction exists for which there is no matching row in the restrictions collection.</value>
1089+
</data>
1090+
<data name="MDF_IncorrectNumberOfDataSourceInformationRows" xml:space="preserve">
1091+
<value>The DataSourceInformation table must contain exactly one row.</value>
1092+
</data>
1093+
<data name="MDF_MissingDataSourceInformationColumn" xml:space="preserve">
1094+
<value>One of the required DataSourceInformation tables columns is missing.</value>
1095+
</data>
1096+
<data name="MDF_AmbigousCollectionName" xml:space="preserve">
1097+
<value>The collection name '{0}' matches at least two collections with the same name but with different case, but does not match any of them exactly.</value>
1098+
</data>
1099+
<data name="MDF_UnableToBuildCollection" xml:space="preserve">
1100+
<value>Unable to build schema collection '{0}';</value>
1101+
</data>
10541102
</root>

src/System.Data.SqlClient/src/Resources/System.Data.SqlClient.SqlMetaData.xml

Lines changed: 2539 additions & 0 deletions
Large diffs are not rendered by default.

src/System.Data.SqlClient/src/System.Data.SqlClient.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
<Compile Include="System\Data\ProviderBase\DbConnectionPoolIdentity.cs" />
8383
<Compile Include="System\Data\ProviderBase\DbConnectionPoolOptions.cs" />
8484
<Compile Include="System\Data\ProviderBase\DbConnectionPoolProviderInfo.cs" />
85+
<Compile Include="System\Data\ProviderBase\DbMetaDataFactory.cs" />
8586
<Compile Include="System\Data\ProviderBase\DbReferenceCollection.cs" />
8687
<Compile Include="System\Data\ProviderBase\TimeoutTimer.cs" />
8788
<Compile Include="System\Data\Sql\SqlMetaData.cs" />
@@ -99,6 +100,7 @@
99100
<Compile Include="System\Data\SqlClient\SqlCachedBuffer.cs" />
100101
<Compile Include="System\Data\SqlClient\SqlClientDiagnosticListenerExtensions.cs" />
101102
<Compile Include="System\Data\SqlClient\SqlClientFactory.cs" />
103+
<Compile Include="System\Data\SqlClient\SqlClientMetaDataCollectionNames.cs" />
102104
<Compile Include="System\Data\SqlClient\SqlCommand.cs" />
103105
<Compile Include="System\Data\SqlClient\SqlConnection.cs" />
104106
<Compile Include="System\Data\SqlClient\SqlConnectionFactory.cs" />
@@ -120,6 +122,7 @@
120122
<Compile Include="System\Data\SqlClient\SqlInternalConnection.cs" />
121123
<Compile Include="System\Data\SqlClient\SqlInternalConnectionTds.cs" />
122124
<Compile Include="System\Data\SqlClient\sqlinternaltransaction.cs" />
125+
<Compile Include="System\Data\SqlClient\SqlMetadataFactory.cs" />
123126
<Compile Include="System\Data\SqlClient\SqlParameter.cs" />
124127
<Compile Include="System\Data\SqlClient\SqlParameterCollection.cs" />
125128
<Compile Include="System\Data\SqlClient\SqlParameterCollectionHelper.cs" />
@@ -406,6 +409,11 @@
406409
<Reference Include="mscorlib" />
407410
<Reference Include="System.Data" />
408411
</ItemGroup>
412+
<ItemGroup>
413+
<EmbeddedResource Include="Resources\System.Data.SqlClient.SqlMetaData.xml">
414+
<LogicalName>System.Data.SqlClient.SqlMetaData.xml</LogicalName>
415+
</EmbeddedResource>
416+
</ItemGroup>
409417
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
410418
<Import Project=".\GenerateThisAssemblyCs.targets" Condition="'$(IsPartialFacadeAssembly)' != 'true'" />
411419
</Project>

src/System.Data.SqlClient/src/System/Data/Common/AdapterUtil.SqlClient.cs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ internal static ObjectDisposedException ObjectDisposed(object instance)
105105
return e;
106106
}
107107

108+
internal static Exception DataTableDoesNotExist(string collectionName)
109+
{
110+
return Argument(SR.GetString(SR.MDF_DataTableDoesNotExist, collectionName));
111+
}
112+
108113
internal static InvalidOperationException MethodCalledTwice(string method)
109114
{
110115
InvalidOperationException e = new InvalidOperationException(SR.GetString(SR.ADP_CalledTwice, method));
@@ -166,6 +171,11 @@ internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterD
166171
return InvalidEnumerationValue(typeof(ParameterDirection), (int)value);
167172
}
168173

174+
internal static Exception TooManyRestrictions(string collectionName)
175+
{
176+
return Argument(SR.GetString(SR.MDF_TooManyRestrictions, collectionName));
177+
}
178+
169179

170180
// IDbCommand.UpdateRowSource
171181
internal static ArgumentOutOfRangeException InvalidUpdateRowSource(UpdateRowSource value)
@@ -206,6 +216,11 @@ internal static Exception MethodNotImplemented([CallerMemberName] string methodN
206216
return NotImplemented.ByDesignWithMessage(methodName);
207217
}
208218

219+
internal static Exception QueryFailed(string collectionName, Exception e)
220+
{
221+
return InvalidOperation(SR.GetString(SR.MDF_QueryFailed, collectionName), e);
222+
}
223+
209224

210225
//
211226
// : DbConnectionOptions, DataAccess, SqlClient
@@ -251,6 +266,11 @@ internal static Exception CommandTextRequired(string method)
251266
return InvalidOperation(SR.GetString(SR.ADP_CommandTextRequired, method));
252267
}
253268

269+
internal static Exception NoColumns()
270+
{
271+
return Argument(SR.GetString(SR.MDF_NoColumns));
272+
}
273+
254274
internal static InvalidOperationException ConnectionRequired(string method)
255275
{
256276
return InvalidOperation(SR.GetString(SR.ADP_ConnectionRequired, method));
@@ -279,11 +299,21 @@ internal static Exception NonSeqByteAccess(long badIndex, long currIndex, string
279299
return InvalidOperation(SR.GetString(SR.ADP_NonSeqByteAccess, badIndex.ToString(CultureInfo.InvariantCulture), currIndex.ToString(CultureInfo.InvariantCulture), method));
280300
}
281301

302+
internal static Exception InvalidXml()
303+
{
304+
return Argument(SR.GetString(SR.MDF_InvalidXml));
305+
}
306+
282307
internal static Exception NegativeParameter(string parameterName)
283308
{
284309
return InvalidOperation(SR.GetString(SR.ADP_NegativeParameter, parameterName));
285310
}
286311

312+
internal static Exception InvalidXmlMissingColumn(string collectionName, string columnName)
313+
{
314+
return Argument(SR.GetString(SR.MDF_InvalidXmlMissingColumn, collectionName, columnName));
315+
}
316+
287317
//
288318
// SqlMetaData, SqlTypes, SqlClient
289319
//
@@ -297,6 +327,21 @@ internal static InvalidOperationException NonSequentialColumnAccess(int badCol,
297327
return InvalidOperation(SR.GetString(SR.ADP_NonSequentialColumnAccess, badCol.ToString(CultureInfo.InvariantCulture), currCol.ToString(CultureInfo.InvariantCulture)));
298328
}
299329

330+
internal static bool CompareInsensitiveInvariant(string strvalue, string strconst)
331+
{
332+
return (0 == CultureInfo.InvariantCulture.CompareInfo.Compare(strvalue, strconst, CompareOptions.IgnoreCase));
333+
}
334+
335+
static internal Exception InvalidXmlInvalidValue(string collectionName, string columnName)
336+
{
337+
return Argument(SR.GetString(SR.MDF_InvalidXmlInvalidValue, collectionName, columnName));
338+
}
339+
340+
internal static Exception CollectionNameIsNotUnique(string collectionName)
341+
{
342+
return Argument(SR.GetString(SR.MDF_CollectionNameISNotUnique, collectionName));
343+
}
344+
300345

301346
//
302347
// : IDbCommand
@@ -309,10 +354,32 @@ internal static Exception UninitializedParameterSize(int index, Type dataType)
309354
{
310355
return InvalidOperation(SR.GetString(SR.ADP_UninitializedParameterSize, index.ToString(CultureInfo.InvariantCulture), dataType.Name));
311356
}
357+
358+
internal static Exception UnableToBuildCollection(string collectionName)
359+
{
360+
return Argument(SR.GetString(SR.MDF_UnableToBuildCollection, collectionName));
361+
}
362+
312363
internal static Exception PrepareParameterType(DbCommand cmd)
313364
{
314365
return InvalidOperation(SR.GetString(SR.ADP_PrepareParameterType, cmd.GetType().Name));
315366
}
367+
368+
internal static Exception UndefinedCollection(string collectionName)
369+
{
370+
return Argument(SR.GetString(SR.MDF_UndefinedCollection, collectionName));
371+
}
372+
373+
internal static Exception UnsupportedVersion(string collectionName)
374+
{
375+
return Argument(SR.GetString(SR.MDF_UnsupportedVersion, collectionName));
376+
}
377+
378+
internal static Exception AmbigousCollectionName(string collectionName)
379+
{
380+
return Argument(SR.GetString(SR.MDF_AmbigousCollectionName, collectionName));
381+
}
382+
316383
internal static Exception PrepareParameterSize(DbCommand cmd)
317384
{
318385
return InvalidOperation(SR.GetString(SR.ADP_PrepareParameterSize, cmd.GetType().Name));
@@ -321,6 +388,17 @@ internal static Exception PrepareParameterScale(DbCommand cmd, string type)
321388
{
322389
return InvalidOperation(SR.GetString(SR.ADP_PrepareParameterScale, cmd.GetType().Name, type));
323390
}
391+
392+
internal static Exception MissingDataSourceInformationColumn()
393+
{
394+
return Argument(SR.GetString(SR.MDF_MissingDataSourceInformationColumn));
395+
}
396+
397+
internal static Exception IncorrectNumberOfDataSourceInformationRows()
398+
{
399+
return Argument(SR.GetString(SR.MDF_IncorrectNumberOfDataSourceInformationRows));
400+
}
401+
324402
internal static Exception MismatchedAsyncResult(string expectedMethod, string gotMethod)
325403
{
326404
return InvalidOperation(SR.GetString(SR.ADP_MismatchedAsyncResult, expectedMethod, gotMethod));
@@ -353,6 +431,12 @@ internal enum ConnectionError
353431
ConnectionOptionsMissing,
354432
CouldNotSwitchToClosedPreviouslyOpenedState,
355433
}
434+
435+
internal static Exception MissingRestrictionColumn()
436+
{
437+
return Argument(SR.GetString(SR.MDF_MissingRestrictionColumn));
438+
}
439+
356440
internal static Exception InternalConnectionError(ConnectionError internalError)
357441
{
358442
return InvalidOperation(SR.GetString(SR.ADP_InternalConnectionError, (int)internalError));
@@ -363,6 +447,11 @@ internal static Exception InvalidConnectRetryCountValue()
363447
return Argument(SR.GetString(SR.SQLCR_InvalidConnectRetryCountValue));
364448
}
365449

450+
internal static Exception MissingRestrictionRow()
451+
{
452+
return Argument(SR.GetString(SR.MDF_MissingRestrictionRow));
453+
}
454+
366455
internal static Exception InvalidConnectRetryIntervalValue()
367456
{
368457
return Argument(SR.GetString(SR.SQLCR_InvalidConnectRetryIntervalValue));
@@ -392,6 +481,12 @@ internal static ArgumentException UnknownDataType(Type dataType)
392481
{
393482
return Argument(SR.GetString(SR.ADP_UnknownDataType, dataType.FullName));
394483
}
484+
485+
internal static bool IsEmptyArray(string[] array)
486+
{
487+
return (array == null || array.Length == 0);
488+
}
489+
395490
internal static ArgumentException DbTypeNotSupported(DbType type, Type enumtype)
396491
{
397492
return Argument(SR.GetString(SR.ADP_DbTypeNotSupported, type.ToString(), enumtype.Name));
@@ -462,6 +557,12 @@ internal static Exception ParameterNull(string parameter, DbParameterCollection
462557
{
463558
return CollectionNullValue(parameter, collection.GetType(), parameterType);
464559
}
560+
561+
internal static Exception UndefinedPopulationMechanism(string populationMechanism)
562+
{
563+
throw new NotImplementedException();
564+
}
565+
465566
internal static Exception InvalidParameterType(DbParameterCollection collection, Type parameterType, object invalidValue)
466567
{
467568
return CollectionInvalidType(collection.GetType(), parameterType, invalidValue);

src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionFactory.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,36 @@ virtual protected DbConnectionInternal CreateConnection(DbConnectionOptions opti
541541
return CreateConnection(options, poolKey, poolGroupProviderInfo, pool, owningConnection);
542542
}
543543

544+
internal DbMetaDataFactory GetMetaDataFactory(DbConnectionPoolGroup connectionPoolGroup, DbConnectionInternal internalConnection)
545+
{
546+
Debug.Assert(connectionPoolGroup != null, "connectionPoolGroup may not be null.");
547+
548+
// get the matadatafactory from the pool entry. If it does not already have one
549+
// create one and save it on the pool entry
550+
DbMetaDataFactory metaDataFactory = connectionPoolGroup.MetaDataFactory;
551+
552+
// consider serializing this so we don't construct multiple metadata factories
553+
// if two threads happen to hit this at the same time. One will be GC'd
554+
if (metaDataFactory == null)
555+
{
556+
bool allowCache = false;
557+
metaDataFactory = CreateMetaDataFactory(internalConnection, out allowCache);
558+
if (allowCache)
559+
{
560+
connectionPoolGroup.MetaDataFactory = metaDataFactory;
561+
}
562+
}
563+
return metaDataFactory;
564+
}
565+
566+
protected virtual DbMetaDataFactory CreateMetaDataFactory(DbConnectionInternal internalConnection, out bool cacheMetaDataFactory)
567+
{
568+
// providers that support GetSchema must override this with a method that creates a meta data
569+
// factory appropriate for them.
570+
cacheMetaDataFactory = false;
571+
throw ADP.NotSupported();
572+
}
573+
544574
abstract protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection);
545575

546576
abstract protected DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous);

src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionInternal.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//------------------------------------------------------------------------------
88

99
using System.Data.Common;
10+
using System.Data.SqlClient;
1011
using System.Diagnostics;
1112
using System.Threading;
1213
using System.Threading.Tasks;
@@ -549,5 +550,15 @@ internal virtual bool IsConnectionAlive(bool throwOnException = false)
549550
{
550551
return true;
551552
}
553+
554+
protected internal virtual DataTable GetSchema(DbConnectionFactory factory, DbConnectionPoolGroup poolGroup, DbConnection outerConnection, string collectionName, string[] restrictions)
555+
{
556+
Debug.Assert(outerConnection != null, "outerConnection may not be null.");
557+
558+
DbMetaDataFactory metaDataFactory = factory.GetMetaDataFactory(poolGroup, this);
559+
Debug.Assert(metaDataFactory != null, "metaDataFactory may not be null.");
560+
561+
return metaDataFactory.GetSchema(outerConnection, collectionName, restrictions);
562+
}
552563
}
553564
}

src/System.Data.SqlClient/src/System/Data/ProviderBase/DbConnectionPoolGroup.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ sealed internal class DbConnectionPoolGroup
3838
private int _state; // see PoolGroupState* below
3939

4040
private DbConnectionPoolGroupProviderInfo _providerInfo;
41+
private DbMetaDataFactory _metaDataFactory;
4142

4243
// always lock this before changing _state, we don't want to move out of the 'Disabled' state
4344
// PoolGroupStateUninitialized = 0;
@@ -110,6 +111,18 @@ internal DbConnectionPoolGroupOptions PoolGroupOptions
110111
}
111112
}
112113

114+
internal DbMetaDataFactory MetaDataFactory
115+
{
116+
get
117+
{
118+
return _metaDataFactory;
119+
}
120+
121+
set
122+
{
123+
_metaDataFactory = value;
124+
}
125+
}
113126

114127
internal int Clear()
115128
{

0 commit comments

Comments
 (0)