Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data / System / Data / SqlClient / sqlmetadatafactory.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="SqlMetaDataFactory.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // <owner current="true" primary="true">Microsoft</owner>
7 // <owner current="true" primary="false">Mugunm</owner>
8 //
9 //------------------------------------------------------------------------------
10
11 namespace System.Data.SqlClient{
12
13     using System;
14     using System.Data;
15     using System.IO;
16     using System.Collections;        
17     using System.Data.ProviderBase;
18     using System.Data.Common;
19     using System.Data.SqlClient;
20     using System.Diagnostics;
21     using System.Globalization;
22     using System.Text;
23     using System.Xml;
24     using System.Xml.Schema;
25
26     
27     internal sealed class SqlMetaDataFactory : DbMetaDataFactory{ // V1.2.3300
28
29         private const string _serverVersionNormalized90 = "09.00.0000";
30         private const string _serverVersionNormalized90782 = "09.00.0782";
31         private const string _serverVersionNormalized10 = "10.00.0000";
32
33
34         public SqlMetaDataFactory(Stream XMLStream, 
35                                     string serverVersion, 
36                                     string serverVersionNormalized): 
37                 base(XMLStream, serverVersion, serverVersionNormalized) {
38   
39            
40         }
41
42         private void addUDTsToDataTypesTable(DataTable dataTypesTable, SqlConnection connection , String  ServerVersion) {
43
44             const string sqlCommand = 
45                 "select " + 
46                     "assemblies.name, " +
47                     "types.assembly_class, " +
48                     "ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') as version_major, " +
49                     "ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') as version_minor, " +
50                     "ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') as version_build, " +
51                     "ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') as version_revision, " +
52                     "ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') as culture_info, " +
53                     "ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') as public_key, " +
54                     "is_nullable, " +
55                     "is_fixed_length, " +
56                     "max_length " +
57                 "from sys.assemblies as assemblies  join sys.assembly_types as types " +
58                 "on assemblies.assembly_id = types.assembly_id ";
59
60             // pre 9.0/Yukon servers do not have UDTs
61             if (0 > string.Compare(ServerVersion,  _serverVersionNormalized90, StringComparison.OrdinalIgnoreCase)){
62                 return;
63             }
64                      
65             
66             // Execute the SELECT statement
67             SqlCommand command = connection.CreateCommand();
68             command.CommandText = sqlCommand;
69             DataRow newRow = null;
70             DataColumn providerDbtype = dataTypesTable.Columns[DbMetaDataColumnNames.ProviderDbType];
71             DataColumn columnSize = dataTypesTable.Columns[DbMetaDataColumnNames.ColumnSize];
72             DataColumn isFixedLength = dataTypesTable.Columns[DbMetaDataColumnNames.IsFixedLength];
73             DataColumn isSearchable = dataTypesTable.Columns[DbMetaDataColumnNames.IsSearchable];
74             DataColumn isLiteralSupported = dataTypesTable.Columns[DbMetaDataColumnNames.IsLiteralSupported];
75             DataColumn typeName = dataTypesTable.Columns[DbMetaDataColumnNames.TypeName];
76             DataColumn isNullable = dataTypesTable.Columns[DbMetaDataColumnNames.IsNullable];
77
78             if ((providerDbtype == null) ||
79                 (columnSize == null) || 
80                 (isFixedLength == null) ||
81                 (isSearchable == null) || 
82                 (isLiteralSupported == null) || 
83                 (typeName == null) || 
84                 (isNullable == null)) {
85                 throw ADP.InvalidXml();
86             }
87                     
88             const int columnSizeIndex = 10;
89             const int isFixedLengthIndex = 9;
90             const int isNullableIndex = 8;
91             const int assemblyNameIndex = 0;
92             const int assemblyClassIndex = 1;
93             const int versionMajorIndex = 2;
94             const int versionMinorIndex = 3;
95             const int versionBuildIndex = 4;
96             const int versionRevisionIndex = 5;
97             const int cultureInfoIndex = 6;
98             const int publicKeyIndex = 7;
99                     
100                     
101             using (IDataReader reader = command.ExecuteReader()) {
102                 
103                 object[] values = new object[11];
104                 while (reader.Read()) {
105                     
106                     reader.GetValues(values);
107                     newRow = dataTypesTable.NewRow();
108
109                     newRow[providerDbtype] = SqlDbType.Udt;
110
111                     if (values[columnSizeIndex] != DBNull.Value) {
112                         newRow[columnSize] = values[columnSizeIndex];
113                     }
114
115                     if (values[isFixedLengthIndex] != DBNull.Value) {
116                         newRow[isFixedLength] = values[isFixedLengthIndex];
117                     }
118
119                     newRow[isSearchable] = true;
120                     newRow[isLiteralSupported] = false;
121                     if (values[isNullableIndex] != DBNull.Value) {
122                         newRow[isNullable] = values[isNullableIndex];
123                     }
124                            
125                     if ((values[assemblyNameIndex] != DBNull.Value) &&
126                         (values[assemblyClassIndex] != DBNull.Value) &&
127                         (values[versionMajorIndex] != DBNull.Value) &&
128                         (values[versionMinorIndex] != DBNull.Value) &&
129                         (values[versionBuildIndex] != DBNull.Value) &&
130                         (values[versionRevisionIndex] != DBNull.Value)) {
131                         
132                         StringBuilder nameString = new StringBuilder();
133                         nameString.Append(values[assemblyClassIndex].ToString());
134                         nameString.Append(", ");
135                         nameString.Append(values[assemblyNameIndex].ToString());
136                         nameString.Append(", Version=");
137
138                         nameString.Append(values[versionMajorIndex].ToString());
139                         nameString.Append(".");
140                         nameString.Append(values[versionMinorIndex].ToString());
141                         nameString.Append(".");
142                         nameString.Append(values[versionBuildIndex].ToString());
143                         nameString.Append(".");
144                         nameString.Append(values[versionRevisionIndex].ToString());
145
146                         if (values[cultureInfoIndex] != DBNull.Value) {
147                             nameString.Append(", Culture=");
148                             nameString.Append(values[cultureInfoIndex].ToString());
149                         }
150
151                         if (values[publicKeyIndex] != DBNull.Value) {
152                         
153                             nameString.Append(", PublicKeyToken=");
154                         
155                             StringBuilder resultString = new StringBuilder();
156                             Byte[] byteArrayValue = (Byte[])values[publicKeyIndex];
157                             foreach (byte b in byteArrayValue) {
158                                 resultString.Append(String.Format((IFormatProvider)null, "{0,-2:x2}", b));
159                             }
160                             nameString.Append(resultString.ToString());
161                         }
162                                                
163                         newRow[typeName] = nameString.ToString();
164                         dataTypesTable.Rows.Add(newRow);
165                         newRow.AcceptChanges();
166                     } // if assembly name
167                      
168                 }//end while
169             } // end using
170         }
171
172         private void AddTVPsToDataTypesTable(DataTable dataTypesTable, SqlConnection connection , String  ServerVersion) {
173
174             const string sqlCommand = 
175                 "select " + 
176                     "name, " +
177                     "is_nullable, " +
178                     "max_length " +
179                 "from sys.types " +
180                 "where is_table_type = 1";
181
182             // 
183
184             if (0 > string.Compare(ServerVersion,  _serverVersionNormalized10, StringComparison.OrdinalIgnoreCase)){
185                 return;
186             }
187                      
188             
189             // Execute the SELECT statement
190             SqlCommand command = connection.CreateCommand();
191             command.CommandText = sqlCommand;
192             DataRow newRow = null;
193             DataColumn providerDbtype = dataTypesTable.Columns[DbMetaDataColumnNames.ProviderDbType];
194             DataColumn columnSize = dataTypesTable.Columns[DbMetaDataColumnNames.ColumnSize];
195             DataColumn isSearchable = dataTypesTable.Columns[DbMetaDataColumnNames.IsSearchable];
196             DataColumn isLiteralSupported = dataTypesTable.Columns[DbMetaDataColumnNames.IsLiteralSupported];
197             DataColumn typeName = dataTypesTable.Columns[DbMetaDataColumnNames.TypeName];
198             DataColumn isNullable = dataTypesTable.Columns[DbMetaDataColumnNames.IsNullable];
199
200             if ((providerDbtype == null) ||
201                 (columnSize == null) || 
202                 (isSearchable == null) || 
203                 (isLiteralSupported == null) || 
204                 (typeName == null) || 
205                 (isNullable == null)) {
206                 throw ADP.InvalidXml();
207             }
208                     
209             const int columnSizeIndex = 2;
210             const int isNullableIndex = 1;
211             const int typeNameIndex = 0;
212                     
213             using (IDataReader reader = command.ExecuteReader()) {
214                 
215                 object[] values = new object[11];
216                 while (reader.Read()) {
217                     
218                     reader.GetValues(values);
219                     newRow = dataTypesTable.NewRow();
220
221                     newRow[providerDbtype] = SqlDbType.Structured;
222
223                     if (values[columnSizeIndex] != DBNull.Value) {
224                         newRow[columnSize] = values[columnSizeIndex];
225                     }
226
227                     newRow[isSearchable] = false;
228                     newRow[isLiteralSupported] = false;
229                     if (values[isNullableIndex] != DBNull.Value) {
230                         newRow[isNullable] = values[isNullableIndex];
231                     }
232                            
233                     if (values[typeNameIndex] != DBNull.Value) {
234                         newRow[typeName] = values[typeNameIndex];
235                         dataTypesTable.Rows.Add(newRow);
236                         newRow.AcceptChanges();
237                     } // if type name
238                 }//end while
239             } // end using
240         }
241
242         private DataTable GetDataTypesTable(SqlConnection connection){
243         
244                                  
245             // verify the existance of the table in the data set
246             DataTable dataTypesTable = CollectionDataSet.Tables[DbMetaDataCollectionNames.DataTypes]; 
247             if (dataTypesTable == null){
248                 throw ADP.UnableToBuildCollection(DbMetaDataCollectionNames.DataTypes);
249             }
250         
251              // copy the table filtering out any rows that don't apply to tho current version of the prrovider
252             dataTypesTable = CloneAndFilterCollection(DbMetaDataCollectionNames.DataTypes, null);
253         
254             addUDTsToDataTypesTable(dataTypesTable, connection, ServerVersionNormalized);
255             AddTVPsToDataTypesTable(dataTypesTable, connection, ServerVersionNormalized);
256                                     
257             dataTypesTable.AcceptChanges();
258             return  dataTypesTable;
259                         
260         }
261
262         protected override DataTable PrepareCollection(String collectionName, String[] restrictions, DbConnection connection){
263
264             SqlConnection sqlConnection = (SqlConnection) connection;
265             DataTable resultTable = null;
266
267             if (collectionName == DbMetaDataCollectionNames.DataTypes){
268                 if (ADP.IsEmptyArray(restrictions) == false) {
269                     throw ADP.TooManyRestrictions(DbMetaDataCollectionNames.DataTypes);
270                 }
271                 resultTable = GetDataTypesTable(sqlConnection);
272             }
273
274             if (resultTable == null){
275                throw ADP.UnableToBuildCollection(collectionName);
276             }
277
278             return resultTable;
279             
280         }
281
282        
283         
284     }
285 }
286
287
288