e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
640 lines
33 KiB
C#
640 lines
33 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="OleDbMetaDataFactory.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//
|
|
// <owner current="true" primary="true">[....]</owner>
|
|
// <owner current="true" primary="false">Mugunm</owner>
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace System.Data.OleDb{
|
|
|
|
using System;
|
|
using System.Data;
|
|
using System.IO;
|
|
using System.Collections;
|
|
using System.Data.ProviderBase;
|
|
using System.Data.Common;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using System.Xml.Schema;
|
|
|
|
internal sealed class OleDbMetaDataFactory : DbMetaDataFactory{ // V1.2.3300
|
|
|
|
private struct SchemaRowsetName {
|
|
internal SchemaRowsetName(string schemaName, Guid schemaRowset) {
|
|
_schemaName = schemaName;
|
|
_schemaRowset = schemaRowset;
|
|
}
|
|
internal readonly string _schemaName;
|
|
internal readonly Guid _schemaRowset;
|
|
}
|
|
|
|
|
|
|
|
private const string _collectionName = "CollectionName";
|
|
private const string _populationMechanism = "PopulationMechanism";
|
|
private const string _prepareCollection = "PrepareCollection";
|
|
|
|
private readonly SchemaRowsetName[] _schemaMapping;
|
|
|
|
internal OleDbMetaDataFactory(Stream XMLStream,
|
|
string serverVersion,
|
|
string serverVersionNormalized,
|
|
SchemaSupport[] schemaSupport):
|
|
base(XMLStream, serverVersion, serverVersionNormalized) {
|
|
|
|
// set up the colletion mane schema rowset guid mapping
|
|
_schemaMapping = new SchemaRowsetName[] {
|
|
|
|
new SchemaRowsetName(DbMetaDataCollectionNames.DataTypes,OleDbSchemaGuid.Provider_Types),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.Catalogs,OleDbSchemaGuid.Catalogs),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.Collations,OleDbSchemaGuid.Collations),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.Columns,OleDbSchemaGuid.Columns),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.Indexes,OleDbSchemaGuid.Indexes),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.Procedures,OleDbSchemaGuid.Procedures),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.ProcedureColumns,OleDbSchemaGuid.Procedure_Columns),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.ProcedureParameters,OleDbSchemaGuid.Procedure_Parameters),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.Tables,OleDbSchemaGuid.Tables),
|
|
new SchemaRowsetName(OleDbMetaDataCollectionNames.Views,OleDbSchemaGuid.Views)};
|
|
|
|
// verify the existance of the table in the data set
|
|
DataTable metaDataCollectionsTable = CollectionDataSet.Tables[DbMetaDataCollectionNames.MetaDataCollections];
|
|
if (metaDataCollectionsTable == null){
|
|
throw ADP.UnableToBuildCollection(DbMetaDataCollectionNames.MetaDataCollections);
|
|
}
|
|
|
|
// copy the table filtering out any rows that don't apply to the current version of the provider
|
|
metaDataCollectionsTable = CloneAndFilterCollection(DbMetaDataCollectionNames.MetaDataCollections, null);
|
|
|
|
// verify the existance of the table in the data set
|
|
DataTable restrictionsTable = CollectionDataSet.Tables[DbMetaDataCollectionNames.Restrictions];
|
|
if (restrictionsTable != null){
|
|
// copy the table filtering out any rows that don't apply to the current version of the provider
|
|
restrictionsTable= CloneAndFilterCollection(DbMetaDataCollectionNames.Restrictions, null);
|
|
}
|
|
|
|
// need to filter out any of the collections where
|
|
// 1) it is populated using prepare collection
|
|
// 2) it is in the collection to schema rowset mapping above
|
|
// 3) the provider does not support the necessary schema rowset
|
|
|
|
|
|
|
|
DataColumn populationMechanism = metaDataCollectionsTable.Columns[_populationMechanism];
|
|
if ((null == populationMechanism) || (typeof(System.String) != populationMechanism.DataType)) {
|
|
throw ADP.InvalidXmlMissingColumn(DbMetaDataCollectionNames.MetaDataCollections,_populationMechanism);
|
|
}
|
|
DataColumn collectionName = metaDataCollectionsTable.Columns[_collectionName];
|
|
if ((null == collectionName) || (typeof(System.String) != collectionName.DataType)) {
|
|
throw ADP.InvalidXmlMissingColumn(DbMetaDataCollectionNames.MetaDataCollections,_collectionName);
|
|
}
|
|
DataColumn restrictionCollectionName = null;
|
|
if (restrictionsTable != null){
|
|
restrictionCollectionName = restrictionsTable.Columns[_collectionName];
|
|
if ((null == restrictionCollectionName) || (typeof(System.String) != restrictionCollectionName.DataType)) {
|
|
throw ADP.InvalidXmlMissingColumn(DbMetaDataCollectionNames.Restrictions,_collectionName);
|
|
}
|
|
}
|
|
|
|
foreach (DataRow collection in metaDataCollectionsTable.Rows){
|
|
|
|
string populationMechanismValue = collection[populationMechanism] as string;
|
|
if (ADP.IsEmpty(populationMechanismValue )) {
|
|
throw ADP.InvalidXmlInvalidValue(DbMetaDataCollectionNames.MetaDataCollections,_populationMechanism);
|
|
}
|
|
string collectionNameValue = collection[collectionName] as string;
|
|
if (ADP.IsEmpty(collectionNameValue)) {
|
|
throw ADP.InvalidXmlInvalidValue(DbMetaDataCollectionNames.MetaDataCollections,_collectionName);
|
|
}
|
|
|
|
if (populationMechanismValue == _prepareCollection) {
|
|
// is the collection in the mapping
|
|
int mapping = -1;
|
|
for (int i = 0; i < _schemaMapping.Length; i++){
|
|
if (_schemaMapping[i]._schemaName == collectionNameValue){
|
|
mapping = i;
|
|
break;
|
|
}
|
|
}
|
|
// no go on to the next collection
|
|
if (mapping == -1) {
|
|
continue;
|
|
}
|
|
|
|
// does the provider support the necessary schema rowset
|
|
bool isSchemaRowsetSupported = false;
|
|
if (schemaSupport != null){
|
|
for (int i = 0; i < schemaSupport.Length; i++){
|
|
if (_schemaMapping[mapping]._schemaRowset == schemaSupport[i]._schemaRowset){
|
|
isSchemaRowsetSupported = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// if not delete the row from the table
|
|
if (isSchemaRowsetSupported == false){
|
|
// but first delete any related restrictions
|
|
if (restrictionsTable != null) {
|
|
foreach (DataRow restriction in restrictionsTable.Rows) {
|
|
string restrictionCollectionNameValue = restriction[restrictionCollectionName] as string;
|
|
if (ADP.IsEmpty(restrictionCollectionNameValue)) {
|
|
throw ADP.InvalidXmlInvalidValue(DbMetaDataCollectionNames.Restrictions,_collectionName);
|
|
}
|
|
if (collectionNameValue == restrictionCollectionNameValue) {
|
|
restriction.Delete();
|
|
}
|
|
}
|
|
restrictionsTable.AcceptChanges();
|
|
}
|
|
collection.Delete();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// replace the original table with the updated one
|
|
metaDataCollectionsTable.AcceptChanges();
|
|
CollectionDataSet.Tables.Remove(CollectionDataSet.Tables[DbMetaDataCollectionNames.MetaDataCollections]);
|
|
CollectionDataSet.Tables.Add(metaDataCollectionsTable);
|
|
|
|
if (restrictionsTable != null) {
|
|
CollectionDataSet.Tables.Remove(CollectionDataSet.Tables[DbMetaDataCollectionNames.Restrictions]);
|
|
CollectionDataSet.Tables.Add(restrictionsTable);
|
|
}
|
|
|
|
}
|
|
|
|
private String BuildRegularExpression(string invalidChars, string invalidStartingChars){
|
|
|
|
StringBuilder regularExpression = new StringBuilder("[^");
|
|
ADP.EscapeSpecialCharacters(invalidStartingChars,regularExpression);
|
|
regularExpression.Append("][^");
|
|
ADP.EscapeSpecialCharacters(invalidChars,regularExpression);
|
|
regularExpression.Append("]*");
|
|
|
|
return regularExpression.ToString();
|
|
}
|
|
|
|
|
|
|
|
private DataTable GetDataSourceInformationTable(OleDbConnection connection, OleDbConnectionInternal internalConnection){
|
|
|
|
// verify that the data source information table is in the data set
|
|
DataTable dataSourceInformationTable = CollectionDataSet.Tables[DbMetaDataCollectionNames.DataSourceInformation];
|
|
if (dataSourceInformationTable == null){
|
|
throw ADP.UnableToBuildCollection(DbMetaDataCollectionNames.DataSourceInformation);
|
|
}
|
|
|
|
// copy the table filtering out any rows that don't apply to tho current version of the prrovider
|
|
dataSourceInformationTable = CloneAndFilterCollection(DbMetaDataCollectionNames.DataSourceInformation, null);
|
|
|
|
// after filtering there better be just one row
|
|
if (dataSourceInformationTable.Rows.Count != 1){
|
|
throw ADP.IncorrectNumberOfDataSourceInformationRows();
|
|
}
|
|
DataRow dataSourceInformation = dataSourceInformationTable.Rows[0];
|
|
|
|
// update the identifier separator
|
|
string catalogSeparatorPattern = internalConnection.GetLiteralInfo(ODB.DBLITERAL_CATALOG_SEPARATOR);
|
|
string schemaSeparatorPattern = internalConnection.GetLiteralInfo(ODB.DBLITERAL_SCHEMA_SEPARATOR);
|
|
|
|
if (catalogSeparatorPattern != null) {
|
|
StringBuilder compositeSeparatorPattern = new StringBuilder();
|
|
StringBuilder patternEscaped = new StringBuilder();
|
|
ADP.EscapeSpecialCharacters(catalogSeparatorPattern,patternEscaped);
|
|
compositeSeparatorPattern.Append(patternEscaped.ToString());
|
|
if ((schemaSeparatorPattern != null) && (schemaSeparatorPattern != catalogSeparatorPattern)) {
|
|
compositeSeparatorPattern.Append("|");
|
|
patternEscaped.Length = 0;
|
|
ADP.EscapeSpecialCharacters(schemaSeparatorPattern,patternEscaped);
|
|
compositeSeparatorPattern.Append(patternEscaped.ToString());
|
|
}
|
|
dataSourceInformation[DbMetaDataColumnNames.CompositeIdentifierSeparatorPattern] = compositeSeparatorPattern.ToString();
|
|
}
|
|
else if (schemaSeparatorPattern != null){
|
|
StringBuilder patternEscaped = new StringBuilder();
|
|
ADP.EscapeSpecialCharacters(schemaSeparatorPattern, patternEscaped);
|
|
dataSourceInformation[DbMetaDataColumnNames.CompositeIdentifierSeparatorPattern] = patternEscaped.ToString();;
|
|
}
|
|
|
|
// update the DataSourceProductName
|
|
object property;
|
|
property = connection.GetDataSourcePropertyValue(OleDbPropertySetGuid.DataSourceInfo,ODB.DBPROP_DBMSNAME);
|
|
if (property != null) {
|
|
dataSourceInformation[DbMetaDataColumnNames.DataSourceProductName] = (string) property;
|
|
}
|
|
|
|
// update the server version strings
|
|
dataSourceInformation[DbMetaDataColumnNames.DataSourceProductVersion] = ServerVersion;
|
|
dataSourceInformation[DbMetaDataColumnNames.DataSourceProductVersionNormalized] = ServerVersionNormalized;
|
|
|
|
|
|
// values that are the same for all OLE DB Providers. See SQLBU 308529
|
|
dataSourceInformation[DbMetaDataColumnNames.ParameterMarkerFormat] = "?";
|
|
dataSourceInformation[DbMetaDataColumnNames.ParameterMarkerPattern] = "\\?";
|
|
dataSourceInformation[DbMetaDataColumnNames.ParameterNameMaxLength] = 0;
|
|
|
|
|
|
property = connection.GetDataSourcePropertyValue(OleDbPropertySetGuid.DataSourceInfo,ODB.DBPROP_GROUPBY);
|
|
GroupByBehavior groupByBehavior = GroupByBehavior.Unknown;
|
|
if (property != null) {
|
|
switch ((int)property) {
|
|
|
|
case ODB.DBPROPVAL_GB_CONTAINS_SELECT:
|
|
groupByBehavior = GroupByBehavior.MustContainAll;
|
|
break;
|
|
|
|
case ODB.DBPROPVAL_GB_EQUALS_SELECT:
|
|
groupByBehavior = GroupByBehavior.ExactMatch;
|
|
break;
|
|
|
|
case ODB.DBPROPVAL_GB_NO_RELATION:
|
|
groupByBehavior = GroupByBehavior.Unrelated;
|
|
break;
|
|
|
|
case ODB.DBPROPVAL_GB_NOT_SUPPORTED:
|
|
groupByBehavior = GroupByBehavior.NotSupported;
|
|
break;
|
|
}
|
|
}
|
|
dataSourceInformation[DbMetaDataColumnNames.GroupByBehavior] = groupByBehavior;
|
|
|
|
SetIdentifierCase(DbMetaDataColumnNames.IdentifierCase,ODB.DBPROP_IDENTIFIERCASE,dataSourceInformation, connection);
|
|
SetIdentifierCase(DbMetaDataColumnNames.QuotedIdentifierCase,ODB.DBPROP_QUOTEDIDENTIFIERCASE,dataSourceInformation, connection);
|
|
|
|
property = connection.GetDataSourcePropertyValue(OleDbPropertySetGuid.DataSourceInfo,ODB.DBPROP_ORDERBYCOLUNSINSELECT);
|
|
if (property != null) {
|
|
dataSourceInformation[DbMetaDataColumnNames.OrderByColumnsInSelect] = (bool) property;
|
|
}
|
|
|
|
DataTable infoLiterals = internalConnection.BuildInfoLiterals();
|
|
if (infoLiterals != null){
|
|
DataRow[] tableNameRow = infoLiterals.Select("Literal = " + ODB.DBLITERAL_TABLE_NAME.ToString(CultureInfo.InvariantCulture));
|
|
if (tableNameRow != null) {
|
|
object invalidCharsObject = tableNameRow[0]["InvalidChars"];
|
|
if (invalidCharsObject.GetType() == typeof(string)) {
|
|
string invalidChars = (string)invalidCharsObject;
|
|
object invalidStartingCharsObject = tableNameRow[0]["InvalidStartingChars"];
|
|
string invalidStartingChars;
|
|
if (invalidStartingCharsObject.GetType() == typeof(string)) {
|
|
invalidStartingChars = (string)invalidStartingCharsObject;
|
|
}
|
|
else {
|
|
invalidStartingChars = invalidChars;
|
|
}
|
|
dataSourceInformation[DbMetaDataColumnNames.IdentifierPattern] =
|
|
BuildRegularExpression(invalidChars,invalidStartingChars);
|
|
}
|
|
}
|
|
}
|
|
|
|
// build the QuotedIdentifierPattern using the quote prefix and suffix from the provider and
|
|
// assuming that the quote suffix is escaped via repetion (i.e " becomes "")
|
|
string quotePrefix;
|
|
string quoteSuffix;
|
|
connection.GetLiteralQuotes(ADP.GetSchema, out quotePrefix, out quoteSuffix);
|
|
|
|
if (quotePrefix != null){
|
|
|
|
// if the quote suffix is null assume that it is the same as the prefix (See OLEDB spec
|
|
// IDBInfo::GetLiteralInfo DBLITERAL_QUOTE_SUFFIX.)
|
|
if (quoteSuffix == null) {
|
|
quoteSuffix = quotePrefix;
|
|
}
|
|
|
|
// only know how to build the parttern if the suffix is 1 character
|
|
// in all other cases just leave the field null
|
|
if (quoteSuffix.Length == 1) {
|
|
StringBuilder scratchStringBuilder = new StringBuilder();
|
|
ADP.EscapeSpecialCharacters(quoteSuffix,scratchStringBuilder );
|
|
string escapedQuoteSuffixString = scratchStringBuilder.ToString();
|
|
scratchStringBuilder.Length = 0;
|
|
|
|
ADP.EscapeSpecialCharacters(quotePrefix, scratchStringBuilder);
|
|
scratchStringBuilder.Append("(([^");
|
|
scratchStringBuilder.Append(escapedQuoteSuffixString);
|
|
scratchStringBuilder.Append("]|");
|
|
scratchStringBuilder.Append(escapedQuoteSuffixString);
|
|
scratchStringBuilder.Append(escapedQuoteSuffixString);
|
|
scratchStringBuilder.Append(")*)");
|
|
scratchStringBuilder.Append(escapedQuoteSuffixString);
|
|
dataSourceInformation[DbMetaDataColumnNames.QuotedIdentifierPattern] = scratchStringBuilder.ToString();
|
|
}
|
|
}
|
|
|
|
dataSourceInformationTable.AcceptChanges();
|
|
|
|
return dataSourceInformationTable;
|
|
}
|
|
|
|
private DataTable GetDataTypesTable(OleDbConnection connection){
|
|
|
|
// verify the existance of the table in the data set
|
|
DataTable dataTypesTable = CollectionDataSet.Tables[DbMetaDataCollectionNames.DataTypes];
|
|
if (dataTypesTable == null){
|
|
throw ADP.UnableToBuildCollection(DbMetaDataCollectionNames.DataTypes);
|
|
}
|
|
|
|
// copy the table filtering out any rows that don't apply to tho current version of the prrovider
|
|
dataTypesTable = CloneAndFilterCollection(DbMetaDataCollectionNames.DataTypes, null);
|
|
|
|
DataTable providerTypesTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Provider_Types,null);
|
|
|
|
|
|
DataColumn[] targetColumns = new DataColumn[] {
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.TypeName],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.ColumnSize],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.CreateParameters],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.IsAutoIncrementable],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.IsCaseSensitive],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.IsFixedLength],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.IsFixedPrecisionScale],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.IsLong],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.IsNullable],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.IsUnsigned],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.MaximumScale],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.MinimumScale],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.LiteralPrefix],
|
|
dataTypesTable.Columns[DbMetaDataColumnNames.LiteralSuffix],
|
|
dataTypesTable.Columns[OleDbMetaDataColumnNames.NativeDataType]};
|
|
|
|
DataColumn[] sourceColumns = new DataColumn[] {
|
|
providerTypesTable.Columns["TYPE_NAME"],
|
|
providerTypesTable.Columns["COLUMN_SIZE"],
|
|
providerTypesTable.Columns["CREATE_PARAMS"],
|
|
providerTypesTable.Columns["AUTO_UNIQUE_VALUE"],
|
|
providerTypesTable.Columns["CASE_SENSITIVE"],
|
|
providerTypesTable.Columns["IS_FIXEDLENGTH"],
|
|
providerTypesTable.Columns["FIXED_PREC_SCALE"],
|
|
providerTypesTable.Columns["IS_LONG"],
|
|
providerTypesTable.Columns["IS_NULLABLE"],
|
|
providerTypesTable.Columns["UNSIGNED_ATTRIBUTE"],
|
|
providerTypesTable.Columns["MAXIMUM_SCALE"],
|
|
providerTypesTable.Columns["MINIMUM_SCALE"],
|
|
providerTypesTable.Columns["LITERAL_PREFIX"],
|
|
providerTypesTable.Columns["LITERAL_SUFFIX"],
|
|
providerTypesTable.Columns["DATA_TYPE"]};
|
|
|
|
Debug.Assert(sourceColumns.Length == targetColumns.Length);
|
|
|
|
DataColumn isSearchable = dataTypesTable.Columns[DbMetaDataColumnNames.IsSearchable];
|
|
DataColumn isSearchableWithLike = dataTypesTable.Columns[DbMetaDataColumnNames.IsSearchableWithLike];
|
|
DataColumn providerDbType = dataTypesTable.Columns[DbMetaDataColumnNames.ProviderDbType];
|
|
DataColumn clrType = dataTypesTable.Columns[DbMetaDataColumnNames.DataType];
|
|
DataColumn isLong = dataTypesTable.Columns[DbMetaDataColumnNames.IsLong];
|
|
DataColumn isFixed = dataTypesTable.Columns[DbMetaDataColumnNames.IsFixedLength];
|
|
DataColumn sourceOleDbType = providerTypesTable.Columns["DATA_TYPE"];
|
|
|
|
DataColumn searchable = providerTypesTable.Columns["SEARCHABLE"];
|
|
|
|
|
|
foreach (DataRow sourceRow in providerTypesTable.Rows) {
|
|
DataRow newRow = dataTypesTable.NewRow();
|
|
for (int i = 0; i < sourceColumns.Length; i++) {
|
|
if ((sourceColumns[i] != null) && (targetColumns[i] != null)){
|
|
newRow[targetColumns[i]] = sourceRow[sourceColumns[i]];
|
|
}
|
|
}
|
|
|
|
|
|
short nativeDataType = (short) Convert.ChangeType(sourceRow[sourceOleDbType],typeof(short), CultureInfo.InvariantCulture);
|
|
NativeDBType nativeType = NativeDBType.FromDBType(nativeDataType,(bool)newRow[isLong], (bool)newRow[isFixed]);
|
|
|
|
newRow[clrType] = nativeType.dataType.FullName;
|
|
newRow[providerDbType] = nativeType.enumOleDbType;
|
|
|
|
// searchable has to be special cased becasue it is not an eaxct mapping
|
|
if ((isSearchable != null) && (isSearchableWithLike != null) && (searchable != null)) {
|
|
|
|
newRow[isSearchable] = DBNull.Value;
|
|
newRow[isSearchableWithLike] = DBNull.Value;
|
|
if ( DBNull.Value != sourceRow[searchable]){
|
|
|
|
Int64 searchableValue = (Int64)(sourceRow[searchable]);
|
|
switch (searchableValue){
|
|
|
|
case ODB.DB_UNSEARCHABLE:
|
|
newRow[isSearchable] = false;
|
|
newRow[isSearchableWithLike] = false;
|
|
break;
|
|
|
|
case ODB.DB_LIKE_ONLY:
|
|
newRow[isSearchable] = false;
|
|
newRow[isSearchableWithLike] = true;
|
|
break;
|
|
|
|
case ODB.DB_ALL_EXCEPT_LIKE:
|
|
newRow[isSearchable] = true;
|
|
newRow[isSearchableWithLike] = false;
|
|
break;
|
|
|
|
case ODB.DB_SEARCHABLE:
|
|
newRow[isSearchable] = true;
|
|
newRow[isSearchableWithLike] = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
dataTypesTable.Rows.Add(newRow);
|
|
}
|
|
|
|
|
|
dataTypesTable.AcceptChanges();
|
|
|
|
return dataTypesTable;
|
|
|
|
}
|
|
|
|
|
|
private DataTable GetReservedWordsTable(OleDbConnectionInternal internalConnection){
|
|
|
|
// verify the existance of the table in the data set
|
|
DataTable reservedWordsTable = CollectionDataSet.Tables[DbMetaDataCollectionNames.ReservedWords];
|
|
if (null == reservedWordsTable){
|
|
throw ADP.UnableToBuildCollection(DbMetaDataCollectionNames.ReservedWords);
|
|
}
|
|
|
|
// copy the table filtering out any rows that don't apply to tho current version of the prrovider
|
|
reservedWordsTable = CloneAndFilterCollection(DbMetaDataCollectionNames.ReservedWords, null);
|
|
|
|
DataColumn reservedWordColumn = reservedWordsTable.Columns[DbMetaDataColumnNames.ReservedWord];
|
|
if (null == reservedWordColumn){
|
|
throw ADP.UnableToBuildCollection(DbMetaDataCollectionNames.ReservedWords);
|
|
}
|
|
|
|
if (!internalConnection.AddInfoKeywordsToTable(reservedWordsTable, reservedWordColumn)){
|
|
throw ODB.IDBInfoNotSupported();
|
|
}
|
|
|
|
return reservedWordsTable;
|
|
}
|
|
|
|
|
|
|
|
protected override DataTable PrepareCollection(String collectionName, String[] restrictions, DbConnection connection){
|
|
|
|
OleDbConnection oleDbConnection = (OleDbConnection) connection;
|
|
OleDbConnectionInternal oleDbInternalConnection = (OleDbConnectionInternal) (oleDbConnection.InnerConnection);
|
|
DataTable resultTable = null;
|
|
if (collectionName == DbMetaDataCollectionNames.DataSourceInformation){
|
|
if (ADP.IsEmptyArray(restrictions) == false){
|
|
throw ADP.TooManyRestrictions(DbMetaDataCollectionNames.DataSourceInformation);
|
|
}
|
|
resultTable = GetDataSourceInformationTable(oleDbConnection, oleDbInternalConnection);
|
|
}
|
|
else if (collectionName == DbMetaDataCollectionNames.DataTypes){
|
|
if (ADP.IsEmptyArray(restrictions) == false){
|
|
throw ADP.TooManyRestrictions(DbMetaDataCollectionNames.DataTypes);
|
|
}
|
|
resultTable = GetDataTypesTable(oleDbConnection);
|
|
}
|
|
else if (collectionName == DbMetaDataCollectionNames.ReservedWords){
|
|
if (ADP.IsEmptyArray(restrictions) == false){
|
|
throw ADP.TooManyRestrictions(DbMetaDataCollectionNames.ReservedWords);
|
|
}
|
|
resultTable = GetReservedWordsTable(oleDbInternalConnection);
|
|
}
|
|
else {
|
|
for (int i=0; i < _schemaMapping.Length; i++){
|
|
if (_schemaMapping[i]._schemaName== collectionName) {
|
|
|
|
// need to special case the oledb schema rowset restrictions on columns that are not
|
|
// string tpyes
|
|
object[] mungedRestrictions = restrictions;;
|
|
if (restrictions != null){
|
|
//verify that there are not too many restrictions
|
|
DataTable metaDataCollectionsTable = CollectionDataSet.Tables[DbMetaDataCollectionNames.MetaDataCollections];
|
|
int numberOfSupportedRestictions = -1;
|
|
// prepare colletion is called with the exact collection name so
|
|
// we can do an exact string comparision here
|
|
foreach (DataRow row in metaDataCollectionsTable.Rows){
|
|
string candidateCollectionName = ((string)row[DbMetaDataColumnNames.CollectionName,DataRowVersion.Current]);
|
|
|
|
if (collectionName == candidateCollectionName) {
|
|
numberOfSupportedRestictions = (int)row[DbMetaDataColumnNames.NumberOfRestrictions];
|
|
if (numberOfSupportedRestictions < restrictions.Length){
|
|
throw ADP.TooManyRestrictions(collectionName);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
Debug.Assert(numberOfSupportedRestictions != -1, "PrepareCollection was called for an collection that is not supported.");
|
|
|
|
// the 4th restrictionon the indexes schema rowset(type) is an I2 - enum
|
|
const int indexRestrictionTypeSlot = 3;
|
|
|
|
if ((collectionName == OleDbMetaDataCollectionNames.Indexes) &&
|
|
(restrictions.Length >= indexRestrictionTypeSlot+1) &&
|
|
(restrictions[indexRestrictionTypeSlot] != null)){
|
|
|
|
mungedRestrictions = new object[restrictions.Length];
|
|
for (int j = 0; j <restrictions.Length; j++){
|
|
mungedRestrictions[j] = restrictions[j];
|
|
}
|
|
|
|
UInt16 indexTypeValue;
|
|
|
|
if ((restrictions[indexRestrictionTypeSlot] == "DBPROPVAL_IT_BTREE") ||
|
|
(restrictions[indexRestrictionTypeSlot] == "1")){
|
|
indexTypeValue = 1;
|
|
}
|
|
else if ((restrictions[indexRestrictionTypeSlot] == "DBPROPVAL_IT_HASH") ||
|
|
(restrictions[indexRestrictionTypeSlot] == "2")){
|
|
indexTypeValue = 2;
|
|
}
|
|
else if ((restrictions[indexRestrictionTypeSlot] == "DBPROPVAL_IT_CONTENT") ||
|
|
(restrictions[indexRestrictionTypeSlot] == "3")){
|
|
indexTypeValue = 3;
|
|
}
|
|
else if ((restrictions[indexRestrictionTypeSlot] == "DBPROPVAL_IT_OTHER") ||
|
|
(restrictions[indexRestrictionTypeSlot] == "4")){
|
|
indexTypeValue = 4;
|
|
}
|
|
else {
|
|
throw ADP.InvalidRestrictionValue(collectionName,"TYPE",restrictions[indexRestrictionTypeSlot]);
|
|
}
|
|
|
|
mungedRestrictions[indexRestrictionTypeSlot] = indexTypeValue;
|
|
|
|
}
|
|
|
|
// the 4th restrictionon the procedures schema rowset(type) is an I2 - enum
|
|
const int procedureRestrictionTypeSlot = 3;
|
|
|
|
if ((collectionName == OleDbMetaDataCollectionNames.Procedures) &&
|
|
(restrictions.Length >= procedureRestrictionTypeSlot+1) &&
|
|
(restrictions[procedureRestrictionTypeSlot] != null)){
|
|
|
|
mungedRestrictions = new object[restrictions.Length];
|
|
for (int j = 0; j <restrictions.Length; j++){
|
|
mungedRestrictions[j] = restrictions[j];
|
|
}
|
|
|
|
Int16 procedureTypeValue;
|
|
|
|
if ((restrictions[procedureRestrictionTypeSlot] == "DB_PT_UNKNOWN") ||
|
|
(restrictions[procedureRestrictionTypeSlot] == "1")){
|
|
procedureTypeValue = 1;
|
|
}
|
|
else if ((restrictions[procedureRestrictionTypeSlot] == "DB_PT_PROCEDURE")||
|
|
(restrictions[procedureRestrictionTypeSlot] == "2")){
|
|
procedureTypeValue = 2;
|
|
}
|
|
else if ((restrictions[procedureRestrictionTypeSlot] == "DB_PT_FUNCTION")||
|
|
(restrictions[procedureRestrictionTypeSlot] == "3")){
|
|
procedureTypeValue = 3;
|
|
}
|
|
else {
|
|
throw ADP.InvalidRestrictionValue(collectionName,"PROCEDURE_TYPE",restrictions[procedureRestrictionTypeSlot]);
|
|
}
|
|
|
|
mungedRestrictions[procedureRestrictionTypeSlot] = procedureTypeValue;
|
|
|
|
}
|
|
}
|
|
|
|
resultTable = oleDbConnection.GetOleDbSchemaTable((System.Guid)_schemaMapping[i]._schemaRowset,mungedRestrictions);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (resultTable == null){
|
|
throw ADP.UnableToBuildCollection(collectionName);
|
|
}
|
|
|
|
return resultTable;
|
|
}
|
|
|
|
private void SetIdentifierCase(string columnName, int propertyID, DataRow row, OleDbConnection connection) {
|
|
|
|
object property = connection.GetDataSourcePropertyValue(OleDbPropertySetGuid.DataSourceInfo,propertyID);
|
|
IdentifierCase identifierCase = IdentifierCase.Unknown;
|
|
if (property != null) {
|
|
int propertyValue = (int)property;
|
|
switch (propertyValue) {
|
|
case ODB.DBPROPVAL_IC_UPPER:
|
|
case ODB.DBPROPVAL_IC_LOWER:
|
|
case ODB.DBPROPVAL_IC_MIXED:
|
|
identifierCase = IdentifierCase.Insensitive;
|
|
break;
|
|
|
|
case ODB.DBPROPVAL_IC_SENSITIVE:
|
|
identifierCase = IdentifierCase.Sensitive;
|
|
break;
|
|
}
|
|
}
|
|
row[columnName] = identifierCase;
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|