Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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;
        }
Exemplo n.º 3
0
        // 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;
        }
Exemplo n.º 4
0
        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;
        }
Exemplo n.º 5
0
        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;
 }