예제 #1
0
        /*public OdbcCommand CreateCommand() { // MDAC 68309
         *  OdbcCommand cmd = Connection.CreateCommand();
         *  cmd.Transaction = this;
         *  return cmd;
         * }
         *
         * IDbCommand IDbTransaction.CreateCommand() {
         *  return CreateCommand();
         * }*/

        /// <include file='doc\OdbcTransaction.uex' path='docs/doc[@for="OdbcTransaction.Commit"]/*' />
        public void Commit()
        {
            OdbcConnection.OdbcPermission.Demand(); // MDAC 81476

            if (null == this.connection)
            {
                throw ADP.TransactionZombied(this);
            }
            connection.CheckState(ADP.CommitTransaction); // MDAC 68289

            //Note: SQLEndTran success if not actually in a transaction, so we have to throw
            //since the IDbTransaciton spec indicates this is an error for the managed packages
            if (AutoCommit)
            {
                throw ODC.NotInTransaction();
            }

            //Commit the transaction (for just this connection)
            ODBC32.RETCODE retcode = (ODBC32.RETCODE)
                                     UnsafeNativeMethods.Odbc32.SQLEndTran(
                (short)ODBC32.SQL_HANDLE.DBC,
                this.connection._dbcWrapper,
                (Int16)ODBC32.SQL_TXN.COMMIT);
            if (retcode != ODBC32.RETCODE.SUCCESS)
            {
                this.connection.HandleError(this.connection._dbcWrapper, ODBC32.SQL_HANDLE.DBC, retcode);
            }

            //Transaction is complete...
            AutoCommit = true;
            this.connection.weakTransaction = null;
            this.connection._dbcWrapper._isInTransaction = false;
            this.connection = null;
        }
예제 #2
0
        // Helpers
        public static OdbcErrorCollection   GetDiagErrors(string source, HandleRef hrHandle, SQL_HANDLE hType, RETCODE retcode)
        {
            switch (retcode)
            {
            case RETCODE.SUCCESS:
                return(null);

            case RETCODE.INVALID_HANDLE:
                throw ODC.InvalidHandle();

            default:
            {
                Int32 NativeError;
                Int16 iRec      = 0;
                Int16 cchActual = 0;

                OdbcErrorCollection errors = new OdbcErrorCollection();
                try {
                    using (CNativeBuffer message = new CNativeBuffer(1024)) {
                        using (CNativeBuffer state = new CNativeBuffer(12)) {
                            bool moreerrors = true;
                            while (moreerrors)
                            {
                                retcode = (RETCODE)UnsafeNativeMethods.Odbc32.SQLGetDiagRecW(
                                    (short)hType,
                                    hrHandle,
                                    ++iRec,        //Orindals are 1:base in odbc
                                    state,
                                    out NativeError,
                                    message,
                                    (short)(message.Length / 2),       //cch
                                    out cchActual);                    //cch

                                //Note: SUCCESS_WITH_INFO from SQLGetDiagRec would be because
                                //the buffer is not large enough for the error string.
                                moreerrors = (retcode == RETCODE.SUCCESS || retcode == RETCODE.SUCCESS_WITH_INFO);
                                if (moreerrors)
                                {
                                    //Sets up the InnerException as well...
                                    errors.Add(new OdbcError(
                                                   source,
                                                   (string)message.MarshalToManaged(SQL_C.WCHAR, SQL_NTS),
                                                   (string)state.MarshalToManaged(SQL_C.WCHAR, SQL_NTS),
                                                   NativeError
                                                   )
                                               );
                                }
                            }
                        }
                    }
                }
                catch {
                    throw;
                }
                return(errors);
            }
            }
        }
예제 #3
0
        static internal TypeMap FromSqlType(ODBC32.SQL_TYPE sqltype)
        {
            switch (sqltype)
            {
            case ODBC32.SQL_TYPE.CHAR: return(_Char);

            case ODBC32.SQL_TYPE.VARCHAR: return(_VarChar);

            case ODBC32.SQL_TYPE.LONGVARCHAR: return(_Text);

            case ODBC32.SQL_TYPE.WCHAR: return(_NChar);

            case ODBC32.SQL_TYPE.WVARCHAR: return(_NVarChar);

            case ODBC32.SQL_TYPE.WLONGVARCHAR: return(_NText);

            case ODBC32.SQL_TYPE.DECIMAL: return(_Decimal);

            case ODBC32.SQL_TYPE.NUMERIC: return(_Numeric);

            case ODBC32.SQL_TYPE.SMALLINT: return(_SmallInt);

            case ODBC32.SQL_TYPE.INTEGER: return(_Int);

            case ODBC32.SQL_TYPE.REAL: return(_Real);

            case ODBC32.SQL_TYPE.FLOAT: return(_Double);

            case ODBC32.SQL_TYPE.DOUBLE: return(_Double);

            case ODBC32.SQL_TYPE.BIT: return(_Bit);

            case ODBC32.SQL_TYPE.TINYINT: return(_TinyInt);

            case ODBC32.SQL_TYPE.BIGINT: return(_BigInt);

            case ODBC32.SQL_TYPE.BINARY: return(_Binary);

            case ODBC32.SQL_TYPE.VARBINARY: return(_VarBinary);

            case ODBC32.SQL_TYPE.LONGVARBINARY: return(_Image);

            case ODBC32.SQL_TYPE.TYPE_DATE: return(_Date);

            case ODBC32.SQL_TYPE.TYPE_TIME: return(_Time);

            case ODBC32.SQL_TYPE.TYPE_TIMESTAMP: return(_DateTime);

            case ODBC32.SQL_TYPE.GUID: return(_UniqueId);

            case (ODBC32.SQL_TYPE)ODBC32.SQL_SS.VARIANT: return(_Variant);

            default: throw ODC.UnknownSQLType(sqltype);
            }
        }
예제 #4
0
        static internal TypeMap FromOdbcType(OdbcType odbcType)
        {
            switch (odbcType)
            {
            case OdbcType.BigInt: return(_BigInt);

            case OdbcType.Binary: return(_Binary);

            case OdbcType.Bit: return(_Bit);

            case OdbcType.Char: return(_Char);

            case OdbcType.DateTime: return(_DateTime);

            case OdbcType.Date: return(_Date);

            case OdbcType.Time: return(_Time);

            case OdbcType.Double: return(_Double);

            case OdbcType.Decimal: return(_Decimal);

            case OdbcType.Image: return(_Image);

            case OdbcType.Int: return(_Int);

            case OdbcType.NChar: return(_NChar);

            case OdbcType.NText: return(_NText);

            case OdbcType.Numeric: return(_Numeric);

            case OdbcType.NVarChar: return(_NVarChar);

            case OdbcType.Real: return(_Real);

            case OdbcType.UniqueIdentifier: return(_UniqueId);

            case OdbcType.SmallDateTime: return(_SmallDT);

            case OdbcType.SmallInt: return(_SmallInt);

            case OdbcType.Text: return(_Text);

            case OdbcType.Timestamp: return(_Timestamp);

            case OdbcType.TinyInt: return(_TinyInt);

            case OdbcType.VarBinary: return(_VarBinary);

            case OdbcType.VarChar: return(_VarChar);

            default: throw ODC.UnknownOdbcType(odbcType);
            }
        }
예제 #5
0
        /// <include file='doc\OdbcTransaction.uex' path='docs/doc[@for="OdbcTransaction.Rollback"]/*' />
        public void Rollback()
        {
            if (null == this.connection)
            {
                throw ADP.TransactionZombied(this);
            }
            connection.CheckState(ADP.RollbackTransaction); // MDAC 68289

            //Note: SQLEndTran success if not actually in a transaction, so we have to throw
            //since the IDbTransaciton spec indicates this is an error for the managed packages
            if (AutoCommit)
            {
                throw ODC.NotInTransaction();
            }

            try { // try-finally inside try-catch-throw
                try {
                    //Abort the transaction (for just this connection)
                    ODBC32.RETCODE retcode = (ODBC32.RETCODE)
                                             UnsafeNativeMethods.Odbc32.SQLEndTran(
                        (short)ODBC32.SQL_HANDLE.DBC,
                        this.connection._dbcWrapper,
                        (Int16)ODBC32.SQL_TXN.ROLLBACK);
                    if (retcode != ODBC32.RETCODE.SUCCESS)
                    {
                        this.connection.HandleError(this.connection._dbcWrapper, ODBC32.SQL_HANDLE.DBC, retcode);
                    }

                    //Transaction is complete...
                    AutoCommit = true;
                }
                finally {
                    this.connection.weakTransaction = null;
                    this.connection._dbcWrapper._isInTransaction = false;
                    this.connection = null;
                }
            }
            catch { // MDAC 81875
                throw;
            }
        }
예제 #6
0
        internal void MarshalToNative(object value, ODBC32.SQL_C sqlctype, byte precision)
        {
            IntPtr buffer = this.Ptr;

            switch (sqlctype)
            {
/*
 #if DEBUG
 *              case ODBC32.SQL_C.CHAR:
 *                  Debug.Assert(false, "should have bound as SQL_C.WCHAR");
 *                  goto default;
 #endif
 */
            case ODBC32.SQL_C.WCHAR:
            {
                //Note: We always bind as unicode
                //Note: StructureToPtr fails indicating string it a non-blittable type
                //and there is no MarshalStringTo* that moves to an existing buffer,
                //they all alloc and return a new one, not at all what we want...

                //So we have to copy the raw bytes of the string ourself?!
                Char[] rgChars = ((string)value).ToCharArray();
                EnsureAlloc((rgChars.Length + 1) * 2);
                buffer = this.Ptr;                                 // Realloc may have changed buffer address
                Marshal.Copy(rgChars, 0, buffer, rgChars.Length);
                Marshal.WriteInt16(buffer, rgChars.Length * 2, 0); // Add the null terminator
                break;
            }

            case ODBC32.SQL_C.BINARY:
            case ODBC32.SQL_C.CHAR:
            {
                Byte[] rgBytes = (Byte[])value;
                EnsureAlloc(rgBytes.Length + 1);
                buffer = this.Ptr;          // Realloc may have changed buffer address
                Marshal.Copy(rgBytes, 0, buffer, rgBytes.Length);
                break;
            }

            case ODBC32.SQL_C.UTINYINT:
                Debug.Assert((Length >= 1), "Native buffer too small ");
                Marshal.WriteByte(buffer, (Byte)value);
                break;

            case ODBC32.SQL_C.SSHORT:       //Int16
                Debug.Assert((Length >= 2), "Native buffer too small ");
                Marshal.WriteInt16(buffer, (Int16)value);
                break;

            case ODBC32.SQL_C.SLONG:        //Int32
            case ODBC32.SQL_C.REAL:         //float
                Debug.Assert((Length >= 4), "Native buffer too small ");
                Marshal.StructureToPtr(value, buffer, false /*deleteold*/);
                break;

            case ODBC32.SQL_C.SBIGINT:      //Int64
            case ODBC32.SQL_C.DOUBLE:       //Double
                Debug.Assert((Length >= 8), "Native buffer too small ");
                Marshal.StructureToPtr(value, buffer, false /*deleteold*/);
                break;

            case ODBC32.SQL_C.GUID:         //Guid
                //All of these we can just delegate
                Debug.Assert(16 <= Length, "Native buffer too small ");
                Marshal.StructureToPtr(value, buffer, false /*deleteold*/);
                break;

            case ODBC32.SQL_C.BIT:
                Debug.Assert((Length >= 1), "Native buffer too small ");
                Marshal.WriteByte(buffer, (Byte)(((bool)value) ? 1 : 0));
                break;

            case ODBC32.SQL_C.TYPE_TIMESTAMP:
            {
                //typedef struct tagTIMESTAMP_STRUCT
                //{
                //      SQLSMALLINT    year;
                //      SQLUSMALLINT   month;
                //      SQLUSMALLINT   day;
                //      SQLUSMALLINT   hour;
                //      SQLUSMALLINT   minute;
                //      SQLUSMALLINT   second;
                //      SQLUINTEGER    fraction;    (billoniths of a second)
                //}

                //We have to map this ourselves, due to the different structures between
                //ODBC TIMESTAMP and URT DateTime, (ie: can't use StructureToPtr)

                Debug.Assert(16 <= Length, "Native buffer too small ");
                DateTime datetime = (DateTime)value;
                Marshal.WriteInt16(buffer, 0, (short)datetime.Year);                //year
                Marshal.WriteInt16(buffer, 2, (short)datetime.Month);               //month
                Marshal.WriteInt16(buffer, 4, (short)datetime.Day);                 //day
                Marshal.WriteInt16(buffer, 6, (short)datetime.Hour);                //hour
                Marshal.WriteInt16(buffer, 8, (short)datetime.Minute);              //minute
                Marshal.WriteInt16(buffer, 10, (short)datetime.Second);             //second
                Marshal.WriteInt32(buffer, 12, datetime.Millisecond * 1000000);     //fraction
                break;
            }

            // Note: System does not provide a date-only type
            case ODBC32.SQL_C.TYPE_DATE:
            {
                //  typedef struct tagDATE_STRUCT
                //  {
                //      SQLSMALLINT    year;
                //      SQLUSMALLINT   month;
                //      SQLUSMALLINT   day;
                //  } DATE_STRUCT;

                Debug.Assert(6 <= Length, "Native buffer too small ");
                DateTime datetime = (DateTime)value;
                Marshal.WriteInt16(buffer, 0, (short)datetime.Year);                //year
                Marshal.WriteInt16(buffer, 2, (short)datetime.Month);               //month
                Marshal.WriteInt16(buffer, 4, (short)datetime.Day);                 //day
                break;
            }

            // Note: System does not provide a date-only type
            case ODBC32.SQL_C.TYPE_TIME:
            {
                //  typedef struct tagTIME_STRUCT
                //  {
                //      SQLUSMALLINT   hour;
                //      SQLUSMALLINT   minute;
                //      SQLUSMALLINT   second;
                //  } TIME_STRUCT;

                Debug.Assert(6 <= Length, "Native buffer too small ");
                TimeSpan timespan = (TimeSpan)value;
                Marshal.WriteInt16(buffer, 0, (short)timespan.Hours);               //hours
                Marshal.WriteInt16(buffer, 2, (short)timespan.Minutes);             //minutes
                Marshal.WriteInt16(buffer, 4, (short)timespan.Seconds);             //seconds
                break;
            }

            case ODBC32.SQL_C.NUMERIC:
            {
                //Note: Unfortunatly the ODBC NUMERIC structure and the URT DECIMAL structure do not
                //align, so we can't so do the typical "PtrToStructure" call (below) like other types
                //We actually have to go through the pain of pulling our raw bytes and building the decimal
                //  Marshal.PtrToStructure(buffer, typeof(decimal));

                //So we are mapping this ourselves
                //typedef struct tagSQL_NUMERIC_STRUCT
                //{
                //  SQLCHAR     precision;
                //  SQLSCHAR    scale;
                //  SQLCHAR     sign;
                //  SQLCHAR     val[SQL_MAX_NUMERIC_LEN];
                //} SQL_NUMERIC_STRUCT;
                int[]  parts = Decimal.GetBits((Decimal)value);
                byte[] bits  = BitConverter.GetBytes(parts[3]);

                Debug.Assert(19 <= Length, "Native buffer too small ");
                Marshal.WriteByte(buffer, 0, (Byte)precision);                //precision
                Marshal.WriteByte(buffer, 1, bits[2]);                        //Bits 16-23 scale
                Marshal.WriteByte(buffer, 2, (Byte)((0 == bits[3]) ? 1 : 0)); //Bit 31 - sign(isnegative)

                Marshal.WriteInt32(buffer, 3, parts[0]);                      //val(low)
                Marshal.WriteInt32(buffer, 7, parts[1]);                      //val(mid)
                Marshal.WriteInt32(buffer, 11, parts[2]);                     //val(hi)
                Marshal.WriteInt32(buffer, 15, 0);                            //val(xhi)
                break;
            }

            default:
                throw ODC.UnknownSQLCType(sqlctype);
            }
            ;
        }
예제 #7
0
        public object      MarshalToManaged(ODBC32.SQL_C sqlctype, int cb)
        {
            IntPtr buffer = this.Ptr;

            switch (sqlctype)
            {
/*
 #if DEBUG
 *             case ODBC32.SQL_C.CHAR:
 *                  Debug.Assert(false, "should have bound as WCHAR");
 *                  goto default;
 #endif
 */
            case ODBC32.SQL_C.WCHAR:
                //Note: We always bind as unicode
                if (cb < 0)
                {
                    String retstr = Marshal.PtrToStringUni(buffer);
                    Debug.Assert(retstr.Length <= this.Length / 2);
                    return(retstr);
                }
                Debug.Assert((Length >= cb), "Native buffer too small ");
                cb = Math.Min(cb / 2, (Length - 2) / 2);
                return(Marshal.PtrToStringUni(buffer, cb));

            case ODBC32.SQL_C.CHAR:
            case ODBC32.SQL_C.BINARY:
            {
                Debug.Assert((Length >= cb), "Native buffer too small ");
                cb = Math.Min(cb, Length);
                Byte[] rgBytes = new Byte[cb];
                Marshal.Copy(buffer, rgBytes, 0, cb);
                return(rgBytes);
            }

            case ODBC32.SQL_C.SSHORT:
                Debug.Assert((Length >= 2), "Native buffer too small ");
                return(Marshal.PtrToStructure(buffer, typeof(Int16)));

            case ODBC32.SQL_C.SLONG:
                Debug.Assert((Length >= 4), "Native buffer too small ");
                return(Marshal.PtrToStructure(buffer, typeof(int)));

            case ODBC32.SQL_C.SBIGINT:
                Debug.Assert((Length >= 8), "Native buffer too small ");
                return(Marshal.PtrToStructure(buffer, typeof(Int64)));

            case ODBC32.SQL_C.BIT:
            {
                Debug.Assert((Length >= 1), "Native buffer too small ");
                Byte b = Marshal.ReadByte(buffer);
                return(b != 0x00);
            }

            case ODBC32.SQL_C.REAL:
                Debug.Assert((Length >= 8), "Native buffer too small ");
                return(Marshal.PtrToStructure(buffer, typeof(float)));

            case ODBC32.SQL_C.DOUBLE:
                Debug.Assert((Length >= 8), "Native buffer too small ");
                return(Marshal.PtrToStructure(buffer, typeof(double)));

            case ODBC32.SQL_C.UTINYINT:
                Debug.Assert((Length >= 1), "Native buffer too small ");
                return(Marshal.ReadByte(buffer));

            case ODBC32.SQL_C.GUID:
                Debug.Assert((Length >= 16), "Native buffer too small ");
                return(Marshal.PtrToStructure(buffer, typeof(Guid)));

            case ODBC32.SQL_C.TYPE_TIMESTAMP:
            {
                //So we are mapping this ourselves.
                //typedef struct tagTIMESTAMP_STRUCT
                //{
                //      SQLSMALLINT    year;
                //      SQLUSMALLINT   month;
                //      SQLUSMALLINT   day;
                //      SQLUSMALLINT   hour;
                //      SQLUSMALLINT   minute;
                //      SQLUSMALLINT   second;
                //      SQLUINTEGER    fraction;    (billoniths of a second)
                //}

                //          return (DateTime)Marshal.PtrToStructure(buffer, typeof(DateTime));
                Debug.Assert(16 <= Length, "Native buffer too small ");
                return(new DateTime(
                           Marshal.ReadInt16(buffer, 0),           //year
                           Marshal.ReadInt16(buffer, 2),           //month
                           Marshal.ReadInt16(buffer, 4),           //day
                           Marshal.ReadInt16(buffer, 6),           //hour
                           Marshal.ReadInt16(buffer, 8),           //mintue
                           Marshal.ReadInt16(buffer, 10),          //second
                           Marshal.ReadInt32(buffer, 12) / 1000000 //milliseconds
                           ));
            }

            // Note: System does not provide a date-only type
            case ODBC32.SQL_C.TYPE_DATE:
            {
                //  typedef struct tagDATE_STRUCT
                //  {
                //      SQLSMALLINT    year;
                //      SQLUSMALLINT   month;
                //      SQLUSMALLINT   day;
                //  } DATE_STRUCT;

                return(new DateTime(
                           Marshal.ReadInt16(buffer, 0),        //year
                           Marshal.ReadInt16(buffer, 2),        //month
                           Marshal.ReadInt16(buffer, 4)         //day
                           ));
            }

            // Note: System does not provide a date-only type
            case ODBC32.SQL_C.TYPE_TIME:
            {
                //  typedef struct tagTIME_STRUCT
                //  {
                //      SQLUSMALLINT   hour;
                //      SQLUSMALLINT   minute;
                //      SQLUSMALLINT   second;
                //  } TIME_STRUCT;

                return(new TimeSpan(
                           Marshal.ReadInt16(buffer, 0),       //hours
                           Marshal.ReadInt16(buffer, 2),       //minutes
                           Marshal.ReadInt16(buffer, 4)        //seconds
                           ));
            }

            case ODBC32.SQL_C.NUMERIC:
            {
                //Note: Unfortunatly the ODBC NUMERIC structure and the URT DECIMAL structure do not
                //align, so we can't so do the typical "PtrToStructure" call (below) like other types
                //We actually have to go through the pain of pulling our raw bytes and building the decimal
                //  Marshal.PtrToStructure(buffer, typeof(decimal));

                //So we are mapping this ourselves
                //typedef struct tagSQL_NUMERIC_STRUCT
                //{
                //  SQLCHAR     precision;
                //  SQLSCHAR    scale;
                //  SQLCHAR     sign;   /* 1 if positive, 0 if negative */
                //  SQLCHAR     val[SQL_MAX_NUMERIC_LEN];
                //} SQL_NUMERIC_STRUCT;
                Debug.Assert(19 <= Length, "Native buffer too small ");
                return(new Decimal(
                           Marshal.ReadInt32(buffer, 3),     //val(low)
                           Marshal.ReadInt32(buffer, 7),     //val(mid)
                           Marshal.ReadInt32(buffer, 11),    //val(hi)
                           Marshal.ReadByte(buffer, 2) == 0, //sign(isnegative)
                           Marshal.ReadByte(buffer, 1)       //scale
                           //              Marshal.ReadByte(buffer, 0),        //precision
                           ));
            }

            default:
                throw ODC.UnknownSQLCType(sqlctype);
            }
            ;
        }