public override bool Equals(object obj) { if (obj == null) { return(false); } if (ReferenceEquals(this, obj)) { return(true); } var other = obj as QueryTableDependencyConfiguration; if (other == null) { return(false); } if (!QualifiedTableName.Equals( other.QualifiedTableName, StringComparison.Ordinal)) { return(false); } if (!RegionPrefix.Equals( other.RegionPrefix, StringComparison.Ordinal)) { return(false); } if (IsPollingDependencyUsed != other.IsPollingDependencyUsed) { return(false); } if (DatabaseType != other.DatabaseType) { return(false); } return(true); }
internal void SetBaseTableNames(QualifiedTableName qualifiedTableName) { int count = FieldCount; for(int i=0; i<count; i++) { if (metadata[i].baseTableName == null) { metadata[i].baseTableName = qualifiedTableName.Table; metadata[i].baseSchemaName = qualifiedTableName.Schema; metadata[i].baseCatalogName = qualifiedTableName.Catalog; } } return; }
// Uses SQLStatistics to retrieve key information for a table private int RetrieveKeyInfoFromStatistics(QualifiedTableName qualifiedTableName, bool quoted) { ODBC32.RetCode retcode; String columnname = String.Empty; String indexname = String.Empty; String currentindexname = String.Empty; int[] indexcolumnordinals = new int[16]; int[] pkcolumnordinals = new int[16]; int npkcols = 0; int ncols = 0; // No of cols in the index bool partialcolumnset = false; int ordinal; int indexordinal; IntPtr cbIndexLen = IntPtr.Zero; IntPtr cbColnameLen = IntPtr.Zero; int keyColumns = 0; // devnote: this test is already done by calling method ... // if (IsClosed) return; // protect against dead connection // MDAC String tablename1 = String.Copy(qualifiedTableName.GetTable(quoted)); // Select only unique indexes retcode = KeyInfoStatementHandle.Statistics(tablename1); if (retcode != ODBC32.RetCode.SUCCESS) { // We give up at this point return 0; } CNativeBuffer buffer = Buffer; bool mustRelease = false; Debug.Assert(buffer.Length >= 544, "Native buffer to small (_buffer.Length < 544)"); RuntimeHelpers.PrepareConstrainedRegions(); try { buffer.DangerousAddRef(ref mustRelease); const int colnameBufOffset = 0; const int indexBufOffset = 256; const int ordinalBufOffset = 512; const int colnameActualOffset = 520; const int indexActualOffset = 528; const int ordinalActualOffset = 536; HandleRef colnamebuf = buffer.PtrOffset(colnameBufOffset, 256); HandleRef indexbuf = buffer.PtrOffset(indexBufOffset, 256); HandleRef ordinalbuf = buffer.PtrOffset(ordinalBufOffset, 4); IntPtr colnameActual = buffer.PtrOffset(colnameActualOffset, IntPtr.Size).Handle; IntPtr indexActual = buffer.PtrOffset(indexActualOffset, IntPtr.Size).Handle; IntPtr ordinalActual = buffer.PtrOffset(ordinalActualOffset, IntPtr.Size).Handle; //We are interested in index name, column name, and ordinal buffer.WriteInt16(indexBufOffset, 0); retcode = KeyInfoStatementHandle.BindColumn2( (short)(ODBC32.SQL_STATISTICS.INDEXNAME), ODBC32.SQL_C.WCHAR, indexbuf, (IntPtr)256, indexActual); retcode = KeyInfoStatementHandle.BindColumn2( (short)(ODBC32.SQL_STATISTICS.ORDINAL_POSITION), ODBC32.SQL_C.SSHORT, ordinalbuf, (IntPtr)4, ordinalActual); buffer.WriteInt16(ordinalBufOffset, 0); retcode = KeyInfoStatementHandle.BindColumn2( (short)(ODBC32.SQL_STATISTICS.COLUMN_NAME), ODBC32.SQL_C.WCHAR, colnamebuf, (IntPtr)256, colnameActual); // Find the best unique index on the table, use the ones whose columns are // completely covered by the query. while (ODBC32.RetCode.SUCCESS == (retcode = KeyInfoStatementHandle.Fetch())) { cbColnameLen = buffer.ReadIntPtr(colnameActualOffset); cbIndexLen = buffer.ReadIntPtr(indexActualOffset); // If indexname is not returned, skip this row if (0 == buffer.ReadInt16(indexBufOffset)) continue; // Not an index row, get next row. columnname = buffer.PtrToStringUni(colnameBufOffset, (int)cbColnameLen/2/*cch*/); indexname = buffer.PtrToStringUni(indexBufOffset, (int)cbIndexLen/2/*cch*/); ordinal = (int) buffer.ReadInt16(ordinalBufOffset); if (SameIndexColumn(currentindexname, indexname, ordinal, ncols)) { // We are still working on the same index if (partialcolumnset) continue; // We don't have all the keys for this index, so we can't use it ordinal = this.GetOrdinalFromBaseColName(columnname, qualifiedTableName.Table); if (ordinal == -1) { partialcolumnset = true; } else { // Add the column to the index column set if (ncols < 16) indexcolumnordinals[ncols++] = ordinal; else // Can't deal with indexes > 16 columns partialcolumnset = true; } } else { // We got a new index, save the previous index information if (!partialcolumnset && (ncols != 0)) { // Choose the unique index with least columns as primary key if ((npkcols == 0) || (npkcols > ncols)){ npkcols = ncols; for (int i = 0 ; i < ncols ; i++) pkcolumnordinals[i] = indexcolumnordinals[i]; } } // Reset the parameters for a new index ncols = 0; currentindexname = indexname; partialcolumnset = false; // Add this column to index ordinal = this.GetOrdinalFromBaseColName(columnname, qualifiedTableName.Table); if (ordinal == -1) { partialcolumnset = true; } else { // Add the column to the index column set indexcolumnordinals[ncols++] = ordinal; } } // Go on to the next column } // Do we have an index? if (!partialcolumnset && (ncols != 0)) { // Choose the unique index with least columns as primary key if ((npkcols == 0) || (npkcols > ncols)){ npkcols = ncols; for (int i = 0 ; i < ncols ; i++) pkcolumnordinals[i] = indexcolumnordinals[i]; } } // Mark the chosen index as primary key if (npkcols != 0) { for (int i = 0 ; i < npkcols ; i++) { indexordinal = pkcolumnordinals[i]; keyColumns++; this.metadata[indexordinal].isKeyColumn = true; // should we set isNullable = false? // This makes the QuikTest against Jet fail // // test test test - we don't know if this is nulalble or not so why do we want to set it to a value? this.metadata[indexordinal].isNullable = false; this.metadata[indexordinal].isUnique = true; if (this.metadata[indexordinal].baseTableName == null) { this.metadata[indexordinal].baseTableName = qualifiedTableName.Table; } if (this.metadata[indexordinal].baseColumnName == null) { this.metadata[indexordinal].baseColumnName = columnname; } } } // Unbind the columns _cmdWrapper.FreeKeyInfoStatementHandle(ODBC32.STMT.UNBIND); } finally { if (mustRelease) { buffer.DangerousRelease(); } } return keyColumns; }
internal int RetrieveKeyInfo(bool needkeyinfo, QualifiedTableName qualifiedTableName, bool quoted) { ODBC32.RetCode retcode; string columnname; int ordinal; int keyColumns = 0; IntPtr cbActual = IntPtr.Zero; if (IsClosed || (_cmdWrapper == null)) { return 0; // Can't do anything without a second handle } _cmdWrapper.CreateKeyInfoStatementHandle(); CNativeBuffer buffer = Buffer; bool mustRelease = false; Debug.Assert(buffer.Length >= 264, "Native buffer to small (_buffer.Length < 264)"); RuntimeHelpers.PrepareConstrainedRegions(); try { buffer.DangerousAddRef(ref mustRelease); if (needkeyinfo) { if (!Connection.ProviderInfo.NoSqlPrimaryKeys) { // Get the primary keys retcode = KeyInfoStatementHandle.PrimaryKeys( qualifiedTableName.Catalog, qualifiedTableName.Schema, qualifiedTableName.GetTable(quoted)); if ((retcode == ODBC32.RetCode.SUCCESS) || (retcode == ODBC32.RetCode.SUCCESS_WITH_INFO)) { bool noUniqueKey = false; // We are only interested in column name buffer.WriteInt16(0, 0); retcode = KeyInfoStatementHandle.BindColumn2( (short)(ODBC32.SQL_PRIMARYKEYS.COLUMNNAME), // Column Number ODBC32.SQL_C.WCHAR, buffer.PtrOffset(0, 256), (IntPtr)256, buffer.PtrOffset(256, IntPtr.Size).Handle); while (ODBC32.RetCode.SUCCESS == (retcode = KeyInfoStatementHandle.Fetch())) { cbActual = buffer.ReadIntPtr(256); columnname = buffer.PtrToStringUni(0, (int)cbActual/2/*cch*/); ordinal = this.GetOrdinalFromBaseColName(columnname); if (ordinal != -1) { keyColumns ++; this.metadata[ordinal].isKeyColumn = true; this.metadata[ordinal].isUnique = true; this.metadata[ordinal].isNullable = false; this.metadata[ordinal].baseTableName = qualifiedTableName.Table; if (this.metadata[ordinal].baseColumnName == null) { this.metadata[ordinal].baseColumnName = columnname; } } else { noUniqueKey = true; break; // no need to go over the remaining columns anymore } } // // if we got keyinfo from the column we dont even get to here! // // reset isUnique flag if the key(s) are not unique // if (noUniqueKey) { foreach (MetaData metadata in this.metadata) { metadata.isKeyColumn = false; } } // Unbind the column retcode = KeyInfoStatementHandle.BindColumn3( (short)(ODBC32.SQL_PRIMARYKEYS.COLUMNNAME), // SQLUSMALLINT ColumnNumber ODBC32.SQL_C.WCHAR, // SQLSMALLINT TargetType buffer.DangerousGetHandle()); // SQLLEN * StrLen_or_Ind } else { if ("IM001" == Command.GetDiagSqlState()) { Connection.ProviderInfo.NoSqlPrimaryKeys = true; } } } if (keyColumns == 0) { // SQLPrimaryKeys did not work. Have to use the slower SQLStatistics to obtain key information KeyInfoStatementHandle.MoreResults(); keyColumns += RetrieveKeyInfoFromStatistics(qualifiedTableName, quoted); } KeyInfoStatementHandle.MoreResults(); } // Get the special columns for version retcode = KeyInfoStatementHandle.SpecialColumns(qualifiedTableName.GetTable(quoted)); if ((retcode == ODBC32.RetCode.SUCCESS) || (retcode == ODBC32.RetCode.SUCCESS_WITH_INFO)) { // We are only interested in column name cbActual = IntPtr.Zero; buffer.WriteInt16(0, 0); retcode = KeyInfoStatementHandle.BindColumn2( (short)(ODBC32.SQL_SPECIALCOLUMNSET.COLUMN_NAME), ODBC32.SQL_C.WCHAR, buffer.PtrOffset(0, 256), (IntPtr)256, buffer.PtrOffset(256, IntPtr.Size).Handle); while (ODBC32.RetCode.SUCCESS == (retcode = KeyInfoStatementHandle.Fetch())) { cbActual = buffer.ReadIntPtr(256); columnname = buffer.PtrToStringUni(0, (int)cbActual/2/*cch*/); ordinal = this.GetOrdinalFromBaseColName(columnname); if (ordinal != -1) { this.metadata[ordinal].isRowVersion = true; if (this.metadata[ordinal].baseColumnName == null) { this.metadata[ordinal].baseColumnName = columnname; } } } // Unbind the column retcode = KeyInfoStatementHandle.BindColumn3( (short)(ODBC32.SQL_SPECIALCOLUMNSET.COLUMN_NAME), ODBC32.SQL_C.WCHAR, buffer.DangerousGetHandle()); retcode = KeyInfoStatementHandle.MoreResults(); } else { // i've seen "DIAG [HY000] [Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt (0) " // how did we get here? SqlServer does not allow a second handle (Keyinfostmt) anyway... // /* string msg = "Unexpected failure of SQLSpecialColumns. Code = " + Command.GetDiagSqlState(); Debug.Assert (false, msg); */ } } finally { if (mustRelease) { buffer.DangerousRelease(); } } return keyColumns; }
private void BuildMetaDataInfo() { int count = FieldCount; MetaData[] metaInfos = new MetaData[count]; List<string> qrytables; bool needkeyinfo = IsCommandBehavior(CommandBehavior.KeyInfo); bool isKeyColumn; bool isHidden; ODBC32.SQL_NULLABILITY nullable; if (needkeyinfo) qrytables = new List<string>(); else qrytables = null; // Find out all the metadata info, not all of this info will be available in all cases // for(int i=0; i<count; i++) { metaInfos[i] = new MetaData(); metaInfos[i].ordinal = i; TypeMap typeMap; // for precision and scale we take the SQL_COLUMN_ attributes. // Those attributes are supported by all provider versions. // for size we use the octet length. We can't use column length because there is an incompatibility with the jet driver. // furthermore size needs to be special cased for wchar types // typeMap = TypeMap.FromSqlType((ODBC32.SQL_TYPE)unchecked((int) GetColAttribute(i, ODBC32.SQL_DESC.CONCISE_TYPE, ODBC32.SQL_COLUMN.TYPE, ODBC32.HANDLER.THROW))); if (typeMap._signType == true) { bool sign = (GetColAttribute(i, ODBC32.SQL_DESC.UNSIGNED, ODBC32.SQL_COLUMN.UNSIGNED, ODBC32.HANDLER.THROW).ToInt64() != 0); // sign = true if the column is unsigned typeMap = TypeMap.UpgradeSignedType(typeMap, sign); } metaInfos[i].typemap = typeMap; metaInfos[i].size = GetColAttribute(i, ODBC32.SQL_DESC.OCTET_LENGTH, ODBC32.SQL_COLUMN.LENGTH, ODBC32.HANDLER.IGNORE); // special case the 'n' types // switch(metaInfos[i].typemap._sql_type) { case ODBC32.SQL_TYPE.WCHAR: case ODBC32.SQL_TYPE.WLONGVARCHAR: case ODBC32.SQL_TYPE.WVARCHAR: metaInfos[i].size /= 2; break; } metaInfos[i].precision = (byte) GetColAttribute(i, (ODBC32.SQL_DESC)ODBC32.SQL_COLUMN.PRECISION, ODBC32.SQL_COLUMN.PRECISION, ODBC32.HANDLER.IGNORE); metaInfos[i].scale = (byte) GetColAttribute(i, (ODBC32.SQL_DESC)ODBC32.SQL_COLUMN.SCALE, ODBC32.SQL_COLUMN.SCALE, ODBC32.HANDLER.IGNORE); metaInfos[i].isAutoIncrement = GetColAttribute(i, ODBC32.SQL_DESC.AUTO_UNIQUE_VALUE, ODBC32.SQL_COLUMN.AUTO_INCREMENT, ODBC32.HANDLER.IGNORE) == 1; metaInfos[i].isReadOnly = (GetColAttribute(i, ODBC32.SQL_DESC.UPDATABLE, ODBC32.SQL_COLUMN.UPDATABLE, ODBC32.HANDLER.IGNORE) == (Int32)ODBC32.SQL_UPDATABLE.READONLY); nullable = (ODBC32.SQL_NULLABILITY) (int) GetColAttribute(i, ODBC32.SQL_DESC.NULLABLE, ODBC32.SQL_COLUMN.NULLABLE, ODBC32.HANDLER.IGNORE); metaInfos[i].isNullable = (nullable == ODBC32.SQL_NULLABILITY.NULLABLE); switch(metaInfos[i].typemap._sql_type) { case ODBC32.SQL_TYPE.LONGVARCHAR: case ODBC32.SQL_TYPE.WLONGVARCHAR: case ODBC32.SQL_TYPE.LONGVARBINARY: metaInfos[i].isLong = true; break; default: metaInfos[i].isLong = false; break; } if(IsCommandBehavior(CommandBehavior.KeyInfo)) { // Note: Following two attributes are SQL Server specific (hence _SS in the name) // SSS_WARNINGS_OFF if (!Connection.ProviderInfo.NoSqlCASSColumnKey) { isKeyColumn = GetColAttribute(i, (ODBC32.SQL_DESC)ODBC32.SQL_CA_SS.COLUMN_KEY, (ODBC32.SQL_COLUMN)(-1), ODBC32.HANDLER.IGNORE) == 1; if (isKeyColumn) { metaInfos[i].isKeyColumn = isKeyColumn; metaInfos[i].isUnique = true; needkeyinfo = false; } } // SSS_WARNINGS_ON metaInfos[i].baseSchemaName = GetColAttributeStr(i, ODBC32.SQL_DESC.SCHEMA_NAME, ODBC32.SQL_COLUMN.OWNER_NAME, ODBC32.HANDLER.IGNORE); metaInfos[i].baseCatalogName = GetColAttributeStr(i, ODBC32.SQL_DESC.CATALOG_NAME, (ODBC32.SQL_COLUMN)(-1), ODBC32.HANDLER.IGNORE); metaInfos[i].baseTableName = GetColAttributeStr(i, ODBC32.SQL_DESC.BASE_TABLE_NAME, ODBC32.SQL_COLUMN.TABLE_NAME, ODBC32.HANDLER.IGNORE); metaInfos[i].baseColumnName = GetColAttributeStr(i, ODBC32.SQL_DESC.BASE_COLUMN_NAME, ODBC32.SQL_COLUMN.NAME, ODBC32.HANDLER.IGNORE); if (Connection.IsV3Driver) { if ((metaInfos[i].baseTableName == null) ||(metaInfos[i].baseTableName.Length == 0)) { // Driver didn't return the necessary information from GetColAttributeStr. // Try GetDescField() metaInfos[i].baseTableName = GetDescFieldStr(i, ODBC32.SQL_DESC.BASE_TABLE_NAME, ODBC32.HANDLER.IGNORE); } if ((metaInfos[i].baseColumnName == null) ||(metaInfos[i].baseColumnName.Length == 0)) { // Driver didn't return the necessary information from GetColAttributeStr. // Try GetDescField() metaInfos[i].baseColumnName = GetDescFieldStr(i, ODBC32.SQL_DESC.BASE_COLUMN_NAME, ODBC32.HANDLER.IGNORE); } } if ((metaInfos[i].baseTableName != null) && !(qrytables.Contains(metaInfos[i].baseTableName))) { qrytables.Add(metaInfos[i].baseTableName); } } // If primary key or autoincrement, then must also be unique if (metaInfos[i].isKeyColumn || metaInfos[i].isAutoIncrement ) { if (nullable == ODBC32.SQL_NULLABILITY.UNKNOWN) metaInfos[i].isNullable = false; // We can safely assume these are not nullable } } // now loop over the hidden columns (if any) // SSS_WARNINGS_OFF if (!Connection.ProviderInfo.NoSqlCASSColumnKey) { for (int i=count; i<count+_hiddenColumns; i++) { isKeyColumn = GetColAttribute(i, (ODBC32.SQL_DESC)ODBC32.SQL_CA_SS.COLUMN_KEY, (ODBC32.SQL_COLUMN)(-1), ODBC32.HANDLER.IGNORE) == 1; if (isKeyColumn) { isHidden = GetColAttribute(i, (ODBC32.SQL_DESC)ODBC32.SQL_CA_SS.COLUMN_HIDDEN, (ODBC32.SQL_COLUMN)(-1), ODBC32.HANDLER.IGNORE) == 1; if (isHidden) { for (int j=0; j<count; j++) { metaInfos[j].isKeyColumn = false; // downgrade keycolumn metaInfos[j].isUnique = false; // downgrade uniquecolumn } } } } } // SSS_WARNINGS_ON // Blow away the previous metadata this.metadata = metaInfos; // If key info is requested, then we have to make a few more calls to get the // special columns. This may not succeed for all drivers, so ignore errors and // fill in as much as possible. if (IsCommandBehavior(CommandBehavior.KeyInfo)) { if((qrytables != null) && (qrytables.Count > 0) ) { List<string>.Enumerator tablesEnum = qrytables.GetEnumerator(); QualifiedTableName qualifiedTableName = new QualifiedTableName(Connection.QuoteChar(ADP.GetSchemaTable)); while(tablesEnum.MoveNext()) { // Find the primary keys, identity and autincrement columns qualifiedTableName.Table = tablesEnum.Current; if (RetrieveKeyInfo(needkeyinfo, qualifiedTableName, false) <= 0) { RetrieveKeyInfo(needkeyinfo, qualifiedTableName, true); } } } else { // Some drivers ( < 3.x ?) do not provide base table information. In this case try to // find it by parsing the statement QualifiedTableName qualifiedTableName = new QualifiedTableName(Connection.QuoteChar(ADP.GetSchemaTable), GetTableNameFromCommandText()); if (!ADP.IsEmpty(qualifiedTableName.Table)) { // fxcop SetBaseTableNames(qualifiedTableName); if (RetrieveKeyInfo(needkeyinfo, qualifiedTableName, false) <= 0) { RetrieveKeyInfo(needkeyinfo, qualifiedTableName, true); } } } } }
public override bool Equals(object obj) { if (obj == null) { return(false); } if (ReferenceEquals(this, obj)) { return(true); } var other = obj as QueryCommandDependencyConfiguration; if (other == null) { return(false); } if (!QualifiedTableName.Equals( other.QualifiedTableName, StringComparison.Ordinal)) { return(false); } if (!RegionPrefix.Equals( other.RegionPrefix, StringComparison.Ordinal)) { return(false); } if (IsPollingDependencyUsed != other.IsPollingDependencyUsed) { return(false); } if (DatabaseType != other.DatabaseType) { return(false); } if (KeyColumnNames == null && other.KeyColumnNames != null) { return(false); } if (KeyColumnNames != null && other.KeyColumnNames == null) { return(false); } var keyColumn1 = new HashSet <string>(KeyColumnNames).Select(x => x.Trim()).ToArray(); var keyColumn2 = new HashSet <string>(other.KeyColumnNames).Select(x => x.Trim()).ToArray(); if (keyColumn1.Length != keyColumn2.Length) { return(false); } foreach (var keyColumnName in keyColumn1) { if (!keyColumn2.Contains( keyColumnName)) { return(false); } } return(true); }
private void BuildMetaDataInfo() { List<string> list; int fieldCount = this.FieldCount; MetaData[] dataArray = new MetaData[fieldCount]; bool needkeyinfo = this.IsCommandBehavior(CommandBehavior.KeyInfo); if (needkeyinfo) { list = new List<string>(); } else { list = null; } for (int i = 0; i < fieldCount; i++) { dataArray[i] = new MetaData(); dataArray[i].ordinal = i; TypeMap typeMap = TypeMap.FromSqlType((ODBC32.SQL_TYPE) ((short) this.GetColAttribute(i, ODBC32.SQL_DESC.CONCISE_TYPE, ODBC32.SQL_COLUMN.TYPE, ODBC32.HANDLER.THROW))); if (typeMap._signType) { bool unsigned = this.GetColAttribute(i, ODBC32.SQL_DESC.UNSIGNED, ODBC32.SQL_COLUMN.UNSIGNED, ODBC32.HANDLER.THROW).ToInt64() != 0L; typeMap = TypeMap.UpgradeSignedType(typeMap, unsigned); } dataArray[i].typemap = typeMap; dataArray[i].size = this.GetColAttribute(i, ODBC32.SQL_DESC.OCTET_LENGTH, ODBC32.SQL_COLUMN.LENGTH, ODBC32.HANDLER.IGNORE); switch (dataArray[i].typemap._sql_type) { case ODBC32.SQL_TYPE.WLONGVARCHAR: case ODBC32.SQL_TYPE.WVARCHAR: case ODBC32.SQL_TYPE.WCHAR: { MetaData data1 = dataArray[i]; data1.size /= 2; break; } } dataArray[i].precision = (byte) this.GetColAttribute(i, (ODBC32.SQL_DESC) 4, ODBC32.SQL_COLUMN.PRECISION, ODBC32.HANDLER.IGNORE); dataArray[i].scale = (byte) this.GetColAttribute(i, (ODBC32.SQL_DESC) 5, ODBC32.SQL_COLUMN.SCALE, ODBC32.HANDLER.IGNORE); dataArray[i].isAutoIncrement = this.GetColAttribute(i, ODBC32.SQL_DESC.AUTO_UNIQUE_VALUE, ODBC32.SQL_COLUMN.AUTO_INCREMENT, ODBC32.HANDLER.IGNORE) == 1; dataArray[i].isReadOnly = this.GetColAttribute(i, ODBC32.SQL_DESC.UPDATABLE, ODBC32.SQL_COLUMN.UPDATABLE, ODBC32.HANDLER.IGNORE) == 0; ODBC32.SQL_NULLABILITY sql_nullability = (ODBC32.SQL_NULLABILITY) ((ushort) this.GetColAttribute(i, ODBC32.SQL_DESC.NULLABLE, ODBC32.SQL_COLUMN.NULLABLE, ODBC32.HANDLER.IGNORE)); dataArray[i].isNullable = sql_nullability == ODBC32.SQL_NULLABILITY.NULLABLE; switch (dataArray[i].typemap._sql_type) { case ODBC32.SQL_TYPE.WLONGVARCHAR: case ODBC32.SQL_TYPE.LONGVARBINARY: case ODBC32.SQL_TYPE.LONGVARCHAR: dataArray[i].isLong = true; break; default: dataArray[i].isLong = false; break; } if (this.IsCommandBehavior(CommandBehavior.KeyInfo)) { if (!this.Connection.ProviderInfo.NoSqlCASSColumnKey) { bool flag2 = this.GetColAttribute(i, (ODBC32.SQL_DESC) 0x4bc, ~ODBC32.SQL_COLUMN.COUNT, ODBC32.HANDLER.IGNORE) == 1; if (flag2) { dataArray[i].isKeyColumn = flag2; dataArray[i].isUnique = true; needkeyinfo = false; } } dataArray[i].baseSchemaName = this.GetColAttributeStr(i, ODBC32.SQL_DESC.SCHEMA_NAME, ODBC32.SQL_COLUMN.OWNER_NAME, ODBC32.HANDLER.IGNORE); dataArray[i].baseCatalogName = this.GetColAttributeStr(i, ODBC32.SQL_DESC.CATALOG_NAME, ~ODBC32.SQL_COLUMN.COUNT, ODBC32.HANDLER.IGNORE); dataArray[i].baseTableName = this.GetColAttributeStr(i, ODBC32.SQL_DESC.BASE_TABLE_NAME, ODBC32.SQL_COLUMN.TABLE_NAME, ODBC32.HANDLER.IGNORE); dataArray[i].baseColumnName = this.GetColAttributeStr(i, ODBC32.SQL_DESC.BASE_COLUMN_NAME, ODBC32.SQL_COLUMN.NAME, ODBC32.HANDLER.IGNORE); if (this.Connection.IsV3Driver) { if ((dataArray[i].baseTableName == null) || (dataArray[i].baseTableName.Length == 0)) { dataArray[i].baseTableName = this.GetDescFieldStr(i, ODBC32.SQL_DESC.BASE_TABLE_NAME, ODBC32.HANDLER.IGNORE); } if ((dataArray[i].baseColumnName == null) || (dataArray[i].baseColumnName.Length == 0)) { dataArray[i].baseColumnName = this.GetDescFieldStr(i, ODBC32.SQL_DESC.BASE_COLUMN_NAME, ODBC32.HANDLER.IGNORE); } } if ((dataArray[i].baseTableName != null) && !list.Contains(dataArray[i].baseTableName)) { list.Add(dataArray[i].baseTableName); } } if ((dataArray[i].isKeyColumn || dataArray[i].isAutoIncrement) && (sql_nullability == ODBC32.SQL_NULLABILITY.UNKNOWN)) { dataArray[i].isNullable = false; } } if (!this.Connection.ProviderInfo.NoSqlCASSColumnKey) { for (int j = fieldCount; j < (fieldCount + this._hiddenColumns); j++) { if ((this.GetColAttribute(j, (ODBC32.SQL_DESC) 0x4bc, ~ODBC32.SQL_COLUMN.COUNT, ODBC32.HANDLER.IGNORE) == 1) && (this.GetColAttribute(j, (ODBC32.SQL_DESC) 0x4bb, ~ODBC32.SQL_COLUMN.COUNT, ODBC32.HANDLER.IGNORE) == 1)) { for (int k = 0; k < fieldCount; k++) { dataArray[k].isKeyColumn = false; dataArray[k].isUnique = false; } } } } this.metadata = dataArray; if (this.IsCommandBehavior(CommandBehavior.KeyInfo)) { if ((list != null) && (list.Count > 0)) { List<string>.Enumerator enumerator = list.GetEnumerator(); QualifiedTableName qualifiedTableName = new QualifiedTableName(this.Connection.QuoteChar("GetSchemaTable")); while (enumerator.MoveNext()) { qualifiedTableName.Table = enumerator.Current; if (this.RetrieveKeyInfo(needkeyinfo, qualifiedTableName, false) <= 0) { this.RetrieveKeyInfo(needkeyinfo, qualifiedTableName, true); } } } else { QualifiedTableName name = new QualifiedTableName(this.Connection.QuoteChar("GetSchemaTable"), this.GetTableNameFromCommandText()); if (!ADP.IsEmpty(name.Table)) { this.SetBaseTableNames(name); if (this.RetrieveKeyInfo(needkeyinfo, name, false) <= 0) { this.RetrieveKeyInfo(needkeyinfo, name, true); } } } } }
internal void SetBaseTableNames(QualifiedTableName qualifiedTableName) { int fieldCount = this.FieldCount; for (int i = 0; i < fieldCount; i++) { if (this.metadata[i].baseTableName == null) { this.metadata[i].baseTableName = qualifiedTableName.Table; this.metadata[i].baseSchemaName = qualifiedTableName.Schema; this.metadata[i].baseCatalogName = qualifiedTableName.Catalog; } } }
private int RetrieveKeyInfoFromStatistics(QualifiedTableName qualifiedTableName, bool quoted) { string columnname = string.Empty; string indexname = string.Empty; string currentindexname = string.Empty; int[] numArray = new int[0x10]; int[] numArray2 = new int[0x10]; int num2 = 0; int ncols = 0; bool flag = false; IntPtr zero = IntPtr.Zero; IntPtr ptr = IntPtr.Zero; int num8 = 0; string tableName = string.Copy(qualifiedTableName.GetTable(quoted)); if (this.KeyInfoStatementHandle.Statistics(tableName) != ODBC32.RetCode.SUCCESS) { return 0; } CNativeBuffer buffer = this.Buffer; bool success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { buffer.DangerousAddRef(ref success); HandleRef ref4 = buffer.PtrOffset(0, 0x100); HandleRef ref3 = buffer.PtrOffset(0x100, 0x100); HandleRef ref2 = buffer.PtrOffset(0x200, 4); IntPtr handle = buffer.PtrOffset(520, IntPtr.Size).Handle; IntPtr ptr4 = buffer.PtrOffset(0x210, IntPtr.Size).Handle; IntPtr ptr3 = buffer.PtrOffset(0x218, IntPtr.Size).Handle; buffer.WriteInt16(0x100, 0); ODBC32.RetCode code = this.KeyInfoStatementHandle.BindColumn2(6, ODBC32.SQL_C.WCHAR, ref3, (IntPtr) 0x100, ptr4); code = this.KeyInfoStatementHandle.BindColumn2(8, ODBC32.SQL_C.SSHORT, ref2, (IntPtr) 4, ptr3); buffer.WriteInt16(0x200, 0); code = this.KeyInfoStatementHandle.BindColumn2(9, ODBC32.SQL_C.WCHAR, ref4, (IntPtr) 0x100, handle); while ((code = this.KeyInfoStatementHandle.Fetch()) == ODBC32.RetCode.SUCCESS) { ptr = buffer.ReadIntPtr(520); zero = buffer.ReadIntPtr(0x210); if (buffer.ReadInt16(0x100) != 0) { columnname = buffer.PtrToStringUni(0, ((int) ptr) / 2); indexname = buffer.PtrToStringUni(0x100, ((int) zero) / 2); int ordinal = buffer.ReadInt16(0x200); if (this.SameIndexColumn(currentindexname, indexname, ordinal, ncols)) { if (!flag) { ordinal = this.GetOrdinalFromBaseColName(columnname, qualifiedTableName.Table); if (ordinal == -1) { flag = true; continue; } if (ncols < 0x10) { numArray[ncols++] = ordinal; } else { flag = true; } } } else { if ((!flag && (ncols != 0)) && ((num2 == 0) || (num2 > ncols))) { num2 = ncols; for (int i = 0; i < ncols; i++) { numArray2[i] = numArray[i]; } } ncols = 0; currentindexname = indexname; flag = false; ordinal = this.GetOrdinalFromBaseColName(columnname, qualifiedTableName.Table); if (ordinal == -1) { flag = true; } else { numArray[ncols++] = ordinal; } } } } if ((!flag && (ncols != 0)) && ((num2 == 0) || (num2 > ncols))) { num2 = ncols; for (int j = 0; j < ncols; j++) { numArray2[j] = numArray[j]; } } if (num2 != 0) { for (int k = 0; k < num2; k++) { int index = numArray2[k]; num8++; this.metadata[index].isKeyColumn = true; this.metadata[index].isNullable = false; this.metadata[index].isUnique = true; if (this.metadata[index].baseTableName == null) { this.metadata[index].baseTableName = qualifiedTableName.Table; } if (this.metadata[index].baseColumnName == null) { this.metadata[index].baseColumnName = columnname; } } } this._cmdWrapper.FreeKeyInfoStatementHandle(ODBC32.STMT.UNBIND); } finally { if (success) { buffer.DangerousRelease(); } } return num8; }
internal int RetrieveKeyInfo(bool needkeyinfo, QualifiedTableName qualifiedTableName, bool quoted) { int num2 = 0; IntPtr zero = IntPtr.Zero; if (this.IsClosed || (this._cmdWrapper == null)) { return 0; } this._cmdWrapper.CreateKeyInfoStatementHandle(); CNativeBuffer buffer = this.Buffer; bool success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { int ordinalFromBaseColName; ODBC32.RetCode code; string str; buffer.DangerousAddRef(ref success); if (!needkeyinfo) { goto Label_0206; } if (!this.Connection.ProviderInfo.NoSqlPrimaryKeys) { code = this.KeyInfoStatementHandle.PrimaryKeys(qualifiedTableName.Catalog, qualifiedTableName.Schema, qualifiedTableName.GetTable(quoted)); switch (code) { case ODBC32.RetCode.SUCCESS: case ODBC32.RetCode.SUCCESS_WITH_INFO: { bool flag = false; buffer.WriteInt16(0, 0); code = this.KeyInfoStatementHandle.BindColumn2(4, ODBC32.SQL_C.WCHAR, buffer.PtrOffset(0, 0x100), (IntPtr) 0x100, buffer.PtrOffset(0x100, IntPtr.Size).Handle); while ((code = this.KeyInfoStatementHandle.Fetch()) == ODBC32.RetCode.SUCCESS) { zero = buffer.ReadIntPtr(0x100); str = buffer.PtrToStringUni(0, ((int) zero) / 2); ordinalFromBaseColName = this.GetOrdinalFromBaseColName(str); if (ordinalFromBaseColName != -1) { num2++; this.metadata[ordinalFromBaseColName].isKeyColumn = true; this.metadata[ordinalFromBaseColName].isUnique = true; this.metadata[ordinalFromBaseColName].isNullable = false; this.metadata[ordinalFromBaseColName].baseTableName = qualifiedTableName.Table; if (this.metadata[ordinalFromBaseColName].baseColumnName == null) { this.metadata[ordinalFromBaseColName].baseColumnName = str; } } else { flag = true; break; } } if (flag) { foreach (MetaData data in this.metadata) { data.isKeyColumn = false; } } code = this.KeyInfoStatementHandle.BindColumn3(4, ODBC32.SQL_C.WCHAR, buffer.DangerousGetHandle()); goto Label_01E0; } } if ("IM001" == this.Command.GetDiagSqlState()) { this.Connection.ProviderInfo.NoSqlPrimaryKeys = true; } } Label_01E0: if (num2 == 0) { this.KeyInfoStatementHandle.MoreResults(); num2 += this.RetrieveKeyInfoFromStatistics(qualifiedTableName, quoted); } this.KeyInfoStatementHandle.MoreResults(); Label_0206: code = this.KeyInfoStatementHandle.SpecialColumns(qualifiedTableName.GetTable(quoted)); if ((code != ODBC32.RetCode.SUCCESS) && (code != ODBC32.RetCode.SUCCESS_WITH_INFO)) { return num2; } zero = IntPtr.Zero; buffer.WriteInt16(0, 0); code = this.KeyInfoStatementHandle.BindColumn2(2, ODBC32.SQL_C.WCHAR, buffer.PtrOffset(0, 0x100), (IntPtr) 0x100, buffer.PtrOffset(0x100, IntPtr.Size).Handle); while ((code = this.KeyInfoStatementHandle.Fetch()) == ODBC32.RetCode.SUCCESS) { zero = buffer.ReadIntPtr(0x100); str = buffer.PtrToStringUni(0, ((int) zero) / 2); ordinalFromBaseColName = this.GetOrdinalFromBaseColName(str); if (ordinalFromBaseColName != -1) { this.metadata[ordinalFromBaseColName].isRowVersion = true; if (this.metadata[ordinalFromBaseColName].baseColumnName == null) { this.metadata[ordinalFromBaseColName].baseColumnName = str; } } } code = this.KeyInfoStatementHandle.BindColumn3(2, ODBC32.SQL_C.WCHAR, buffer.DangerousGetHandle()); code = this.KeyInfoStatementHandle.MoreResults(); } finally { if (success) { buffer.DangerousRelease(); } } return num2; }