Exemple #1
0
        internal void SetInputValue(object value, ODBC32.SQL_C sql_c_type, int cbsize, int sizeorprecision, int offset, CNativeBuffer parameterBuffer)
        {
            if ((ParameterDirection.Input != this._internalDirection) && (ParameterDirection.InputOutput != this._internalDirection))
            {
                this._internalValue = null;
                parameterBuffer.WriteIntPtr(this._preparedIntOffset, (IntPtr)(-1));
            }
            else if (value == null)
            {
                parameterBuffer.WriteIntPtr(this._preparedIntOffset, (IntPtr)(-5));
            }
            else if (Convert.IsDBNull(value))
            {
                parameterBuffer.WriteIntPtr(this._preparedIntOffset, (IntPtr)(-1));
            }
            else
            {
                switch (sql_c_type)
                {
                case ODBC32.SQL_C.WCHAR:
                case ODBC32.SQL_C.BINARY:
                case ODBC32.SQL_C.CHAR:
                    parameterBuffer.WriteIntPtr(this._preparedIntOffset, (IntPtr)cbsize);
                    break;

                default:
                    parameterBuffer.WriteIntPtr(this._preparedIntOffset, IntPtr.Zero);
                    break;
                }
                parameterBuffer.MarshalToNative(this._preparedValueOffset, value, sql_c_type, sizeorprecision, offset);
            }
        }
Exemple #2
0
 internal static extern /*SQLRETURN*/ ODBC32.RetCode SQLGetData(
     /*SQLHSTMT*/ OdbcStatementHandle StatementHandle,
     /*SQLUSMALLINT*/ ushort ColumnNumber,
     /*SQLSMALLINT*/ ODBC32.SQL_C TargetType,
     /*SQLPOINTER*/ CNativeBuffer TargetValue,
     /*SQLLEN*/ IntPtr BufferLength, // sql.h differs from MSDN
                                     /*SQLLEN* */ out IntPtr StrLen_or_Ind);
Exemple #3
0
 internal static extern /*SQLRETURN*/ ODBC32.RetCode SQLBindCol(
     /*SQLHSTMT*/ OdbcStatementHandle StatementHandle,
     /*SQLUSMALLINT*/ ushort ColumnNumber,
     /*SQLSMALLINT*/ ODBC32.SQL_C TargetType,
     /*SQLPOINTER*/ IntPtr TargetValue,
     /*SQLLEN*/ IntPtr BufferLength,
     /*SQLLEN* */ IntPtr StrLen_or_Ind);
        internal object MarshalToManaged(int offset, ODBC32.SQL_C sqlctype, int cb)
        {
            switch (sqlctype)
            {
            case ODBC32.SQL_C.SLONG:
                return(base.ReadInt32(offset));

            case ODBC32.SQL_C.SSHORT:
                return(base.ReadInt16(offset));

            case ODBC32.SQL_C.SBIGINT:
                return(base.ReadInt64(offset));

            case ODBC32.SQL_C.UTINYINT:
                return(base.ReadByte(offset));

            case ODBC32.SQL_C.GUID:
                return(base.ReadGuid(offset));

            case ODBC32.SQL_C.WCHAR:
                if (cb != -3)
                {
                    cb = Math.Min((int)(cb / 2), (int)((base.Length - 2) / 2));
                    return(base.PtrToStringUni(offset, cb));
                }
                return(base.PtrToStringUni(offset));

            case ODBC32.SQL_C.BIT:
                return(base.ReadByte(offset) != 0);

            case ODBC32.SQL_C.BINARY:
            case ODBC32.SQL_C.CHAR:
                cb = Math.Min(cb, base.Length);
                return(base.ReadBytes(offset, cb));

            case ODBC32.SQL_C.NUMERIC:
                return(base.ReadNumeric(offset));

            case ODBC32.SQL_C.REAL:
                return(base.ReadSingle(offset));

            case ODBC32.SQL_C.DOUBLE:
                return(base.ReadDouble(offset));

            case ODBC32.SQL_C.TYPE_DATE:
                return(base.ReadDate(offset));

            case ODBC32.SQL_C.TYPE_TIME:
                return(base.ReadTime(offset));

            case ODBC32.SQL_C.TYPE_TIMESTAMP:
                return(base.ReadDateTime(offset));
            }
            return(null);
        }
Exemple #5
0
 internal static extern /*SQLRETURN*/ ODBC32.RetCode SQLBindParameter(
     /*SQLHSTMT*/ OdbcStatementHandle StatementHandle,
     /*SQLUSMALLINT*/ ushort ParameterNumber,
     /*SQLSMALLINT*/ short ParamDirection,
     /*SQLSMALLINT*/ ODBC32.SQL_C SQLCType,
     /*SQLSMALLINT*/ short SQLType,
     /*SQLULEN*/ IntPtr cbColDef,
     /*SQLSMALLINT*/ IntPtr ibScale,
     /*SQLPOINTER*/ HandleRef rgbValue,
     /*SQLLEN*/ IntPtr BufferLength,
     /*SQLLEN* */ HandleRef StrLen_or_Ind);
        internal static partial /*SQLRETURN*/ ODBC32.SQLRETURN SQLBindCol(
            /*SQLHSTMT*/ OdbcStatementHandle StatementHandle,
            /*SQLUSMALLINT*/ ushort ColumnNumber,
            /*SQLSMALLINT*/ ODBC32.SQL_C TargetType,
            /*SQLPOINTER*/
#if NET7_0_OR_GREATER
            [MarshalUsing(typeof(HandleRefMarshaller))]
#endif
            HandleRef TargetValue,
            /*SQLLEN*/ IntPtr BufferLength,
            /*SQLLEN* */ IntPtr StrLen_or_Ind);
 internal ODBC32.RetCode GetData(int index, ODBC32.SQL_C sqlctype, CNativeBuffer buffer, int cb, out IntPtr cbActual)
 {
     ODBC32.RetCode retcode = Interop.Odbc.SQLGetData(this,
                                                      checked ((ushort)index),
                                                      sqlctype,
                                                      buffer,
                                                      new IntPtr(cb),
                                                      out cbActual);
     ODBC.TraceODBC(3, "SQLGetData", retcode);
     return(retcode);
 }
 private TypeMap(OdbcType odbcType, DbType dbType, Type type, ODBC32.SQL_TYPE sql_type, ODBC32.SQL_C sql_c, ODBC32.SQL_C param_sql_c, int bsize, int csize, bool signType)
 {
     this._odbcType = odbcType;
     this._dbType = dbType;
     this._type = type;
     this._sql_type = sql_type;
     this._sql_c = sql_c;
     this._param_sql_c = param_sql_c;
     this._bufferSize = bsize;
     this._columnSize = csize;
     this._signType = signType;
 }
Exemple #9
0
 private TypeMap(OdbcType odbcType, DbType dbType, Type type, ODBC32.SQL_TYPE sql_type, ODBC32.SQL_C sql_c, ODBC32.SQL_C param_sql_c, int bsize, int csize, bool signType)
 {
     this._odbcType    = odbcType;
     this._dbType      = dbType;
     this._type        = type;
     this._sql_type    = sql_type;
     this._sql_c       = sql_c;
     this._param_sql_c = param_sql_c;
     this._bufferSize  = bsize;
     this._columnSize  = csize;
     this._signType    = signType;
 }
Exemple #10
0
        internal readonly bool _signType;   // this type may be has signature information

        private TypeMap(OdbcType odbcType, DbType dbType, Type type, ODBC32.SQL_TYPE sql_type, ODBC32.SQL_C sql_c, ODBC32.SQL_C param_sql_c, int bsize, int csize, bool signType)
        {
            _odbcType = odbcType;
            _dbType   = dbType;
            _type     = type;

            _sql_type    = sql_type;
            _sql_c       = sql_c;
            _param_sql_c = param_sql_c; // alternative sql_c type for parameters

            _bufferSize = bsize;
            _columnSize = csize;
            _signType   = signType;
        }
Exemple #11
0
        internal void SetInputValue(object value, ODBC32.SQL_C sql_c_type, int cbsize, int sizeorprecision, int offset, CNativeBuffer parameterBuffer)
        { //Handle any input params
            if ((ParameterDirection.Input == _internalDirection) || (ParameterDirection.InputOutput == _internalDirection))
            {
                //Note: (lang) "null" means to use the servers default (not DBNull).
                //We probably should just not have bound this parameter, period, but that
                //would mess up the users question marks, etc...
                if ((null == value))
                {
                    parameterBuffer.WriteIntPtr(_preparedIntOffset, (IntPtr)ODBC32.SQL_DEFAULT_PARAM);
                }
                else if (Convert.IsDBNull(value))
                {
                    parameterBuffer.WriteIntPtr(_preparedIntOffset, (IntPtr)ODBC32.SQL_NULL_DATA);
                }
                else
                {
                    switch (sql_c_type)
                    {
                    case ODBC32.SQL_C.CHAR:
                    case ODBC32.SQL_C.WCHAR:
                    case ODBC32.SQL_C.BINARY:
                        //StrLen_or_IndPtr is ignored except for Character or Binary or data.
                        parameterBuffer.WriteIntPtr(_preparedIntOffset, (IntPtr)cbsize);
                        break;

                    default:
                        parameterBuffer.WriteIntPtr(_preparedIntOffset, IntPtr.Zero);
                        break;
                    }

                    //Place the input param value into the native buffer
                    parameterBuffer.MarshalToNative(_preparedValueOffset, value, sql_c_type, sizeorprecision, offset);
                }
            }
            else
            {
                // always set ouput only and return value parameter values to null when executing
                _internalValue = null;

                //Always initialize the intbuffer (for output params).  Since we need to know
                //if/when the parameters are available for output. (ie: when is the buffer valid...)
                //if (_sqldirection != ODBC32.SQL_PARAM.INPUT)
                parameterBuffer.WriteIntPtr(_preparedIntOffset, (IntPtr)ODBC32.SQL_NULL_DATA);
            }
        }
        internal static partial /*SQLRETURN*/ ODBC32.SQLRETURN SQLBindParameter(
            /*SQLHSTMT*/ OdbcStatementHandle StatementHandle,
            /*SQLUSMALLINT*/ ushort ParameterNumber,
            /*SQLSMALLINT*/ short ParamDirection,
            /*SQLSMALLINT*/ ODBC32.SQL_C SQLCType,
            /*SQLSMALLINT*/ short SQLType,
            /*SQLULEN*/ IntPtr cbColDef,
            /*SQLSMALLINT*/ IntPtr ibScale,
            /*SQLPOINTER*/
#if NET7_0_OR_GREATER
            [MarshalUsing(typeof(HandleRefMarshaller))]
#endif
            HandleRef rgbValue,
            /*SQLLEN*/ IntPtr BufferLength,
            /*SQLLEN* */
#if NET7_0_OR_GREATER
            [MarshalUsing(typeof(HandleRefMarshaller))]
#endif
            HandleRef StrLen_or_Ind);
 internal ODBC32.RetCode BindColumn3(int columnNumber, ODBC32.SQL_C targetType, IntPtr srLen_or_Ind)
 {
     ODBC32.RetCode retcode = Interop.Odbc.SQLBindCol(this, checked ((ushort)columnNumber), targetType, ADP.PtrZero, ADP.PtrZero, srLen_or_Ind);
     ODBC.TraceODBC(3, "SQLBindCol", retcode);
     return(retcode);
 }
 internal ODBC32.RetCode BindColumn2(int columnNumber, ODBC32.SQL_C targetType, HandleRef buffer, IntPtr length, IntPtr srLen_or_Ind)
 {
     ODBC32.RetCode retcode = Interop.Odbc.SQLBindCol(this, checked ((ushort)columnNumber), targetType, buffer, length, srLen_or_Ind);
     ODBC.TraceODBC(3, "SQLBindCol", retcode);
     return(retcode);
 }
 internal static extern ODBC32.RetCode SQLGetData(OdbcStatementHandle StatementHandle, ushort ColumnNumber, ODBC32.SQL_C TargetType, CNativeBuffer TargetValue, IntPtr BufferLength, out IntPtr StrLen_or_Ind);
 internal static extern ODBC32.RetCode SQLBindCol(OdbcStatementHandle StatementHandle, ushort ColumnNumber, ODBC32.SQL_C TargetType, HandleRef TargetValue, IntPtr BufferLength, IntPtr StrLen_or_Ind);
        internal void PrepareForBind(OdbcCommand command, short ordinal, ref int parameterBufferSize) {
            // make a snapshot of the current properties. Properties may change while we work on them
            //
            CopyParameterInternal();

            object value  = ProcessAndGetParameterValue();
            int    offset = _internalOffset;
            int    size   = _internalSize;
            ODBC32.SQL_C sql_c_type;


            // offset validation based on the values type
            //
            if (offset > 0) {
                if (value is string) {
                    if (offset > ((string)value).Length) {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else if (value is char[]) {
                    if (offset > ((char[])value).Length) {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else if (value is byte[]) {
                    if (offset > ((byte[])value).Length) {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else {
                    // for all other types offset has no meaning
                    // this is important since we might upgrade some types to strings
                    offset = 0;
                }
            }

            // type support verification for certain data types
            //
            switch(_bindtype._sql_type) {
                case ODBC32.SQL_TYPE.DECIMAL:
                case ODBC32.SQL_TYPE.NUMERIC:
                    if (
                        !command.Connection.IsV3Driver                                      // for non V3 driver we always do the conversion
                        || !command.Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC)     // otherwise we convert if the driver does not support numeric
                        || command.Connection.TestRestrictedSqlBindType(_bindtype._sql_type)// or the type is not supported
                    ){
                        // No support for NUMERIC
                        // Change the type
                        _bindtype = TypeMap._VarChar;
                        if ((null != value) && !Convert.IsDBNull(value)) {
                            value = ((Decimal)value).ToString(CultureInfo.CurrentCulture);
                            size = ((string)value).Length;
                            offset = 0;
                        }
                    }
                    break;
                case ODBC32.SQL_TYPE.BIGINT:
                    if (!command.Connection.IsV3Driver){
                        // No support for BIGINT
                        // Change the type
                        _bindtype = TypeMap._VarChar;
                        if ((null != value) && !Convert.IsDBNull(value)) {
                            value = ((Int64)value).ToString(CultureInfo.CurrentCulture);
                            size = ((string)value).Length;
                            offset = 0;
                        }
                    }
                    break;
                case ODBC32.SQL_TYPE.WCHAR: // MDAC 68993
                case ODBC32.SQL_TYPE.WVARCHAR:
                case ODBC32.SQL_TYPE.WLONGVARCHAR:
                    if (value is Char) {
                        value = value.ToString();
                        size = ((string)value).Length;
                        offset = 0;
                    }
                    if (!command.Connection.TestTypeSupport (_bindtype._sql_type)) {
                        // No support for WCHAR, WVARCHAR or WLONGVARCHAR
                        // Change the type
                        if (ODBC32.SQL_TYPE.WCHAR == _bindtype._sql_type) { _bindtype = TypeMap._Char; }
                        else if (ODBC32.SQL_TYPE.WVARCHAR == _bindtype._sql_type) { _bindtype = TypeMap._VarChar; }
                        else if (ODBC32.SQL_TYPE.WLONGVARCHAR == _bindtype._sql_type) {
                            _bindtype = TypeMap._Text;
                        }
                    }
                    break;
            } // end switch

            // Conversation from WCHAR to CHAR, VARCHAR or LONVARCHAR (AnsiString) is different for some providers
            // we need to chonvert WCHAR to CHAR and bind as sql_c_type = CHAR
            //
            sql_c_type = _bindtype._sql_c;

            if (!command.Connection.IsV3Driver) {
                  if (sql_c_type == ODBC32.SQL_C.WCHAR) {
                    sql_c_type = ODBC32.SQL_C.CHAR;

                    if (null != value){
                        if (!Convert.IsDBNull(value) && value is string) {
                            int lcid = System.Globalization.CultureInfo.CurrentCulture.LCID;
                            CultureInfo culInfo = new CultureInfo(lcid);
                            Encoding cpe = System.Text.Encoding.GetEncoding(culInfo.TextInfo.ANSICodePage);
                            value = cpe.GetBytes(value.ToString());
                            size = ((byte[])value).Length;
                        }
                    }
                }
            };

            int cbParameterSize = GetParameterSize(value, offset, ordinal);      // count of bytes for the data, for SQLBindParameter

            // here we upgrade the datatypes if the given values size is bigger than the types columnsize
            //
            switch(_bindtype._sql_type) {
                case ODBC32.SQL_TYPE.VARBINARY: // MDAC 74372
                    // Note: per definition DbType.Binary does not support more than 8000 bytes so we change the type for binding
                    if ((cbParameterSize > 8000))
                        { _bindtype = TypeMap._Image; } // will change to LONGVARBINARY
                    break;
                case ODBC32.SQL_TYPE.VARCHAR: // MDAC 74372
                    // Note: per definition DbType.Binary does not support more than 8000 bytes so we change the type for binding
                    if ((cbParameterSize > 8000))
                        { _bindtype = TypeMap._Text; }  // will change to LONGVARCHAR
                    break;
                case ODBC32.SQL_TYPE.WVARCHAR : // MDAC 75099
                    // Note: per definition DbType.Binary does not support more than 8000 bytes so we change the type for binding
                    if ((cbParameterSize > 4000))
                        { _bindtype = TypeMap._NText; }  // will change to WLONGVARCHAR
                    break;
            }

            _prepared_Sql_C_Type = sql_c_type;
            _preparedOffset      = offset;
            _preparedSize        = size;
            _preparedValue       = value;
            _preparedBufferSize  = cbParameterSize;
            _preparedIntOffset   = parameterBufferSize;
            _preparedValueOffset = _preparedIntOffset + IntPtr.Size;
            parameterBufferSize += (cbParameterSize + IntPtr.Size);
        }
Exemple #18
0
        internal void PrepareForBind(OdbcCommand command, short ordinal, ref int parameterBufferSize)
        {
            this.CopyParameterInternal();
            object bytes  = this.ProcessAndGetParameterValue();
            int    offset = this._internalOffset;
            int    length = this._internalSize;

            if (offset > 0)
            {
                if (bytes is string)
                {
                    if (offset > ((string)bytes).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else if (bytes is char[])
                {
                    if (offset > ((char[])bytes).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else if (bytes is byte[])
                {
                    if (offset > ((byte[])bytes).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else
                {
                    offset = 0;
                }
            }
            switch (this._bindtype._sql_type)
            {
            case ODBC32.SQL_TYPE.WLONGVARCHAR:
            case ODBC32.SQL_TYPE.WVARCHAR:
            case ODBC32.SQL_TYPE.WCHAR:
                if (bytes is char)
                {
                    bytes  = bytes.ToString();
                    length = ((string)bytes).Length;
                    offset = 0;
                }
                if (!command.Connection.TestTypeSupport(this._bindtype._sql_type))
                {
                    if (ODBC32.SQL_TYPE.WCHAR == this._bindtype._sql_type)
                    {
                        this._bindtype = TypeMap._Char;
                    }
                    else if (ODBC32.SQL_TYPE.WVARCHAR == this._bindtype._sql_type)
                    {
                        this._bindtype = TypeMap._VarChar;
                    }
                    else if (ODBC32.SQL_TYPE.WLONGVARCHAR == this._bindtype._sql_type)
                    {
                        this._bindtype = TypeMap._Text;
                    }
                }
                break;

            case ODBC32.SQL_TYPE.BIGINT:
                if (!command.Connection.IsV3Driver)
                {
                    this._bindtype = TypeMap._VarChar;
                    if ((bytes != null) && !Convert.IsDBNull(bytes))
                    {
                        bytes  = ((long)bytes).ToString(CultureInfo.CurrentCulture);
                        length = ((string)bytes).Length;
                        offset = 0;
                    }
                }
                break;

            case ODBC32.SQL_TYPE.NUMERIC:
            case ODBC32.SQL_TYPE.DECIMAL:
                if ((!command.Connection.IsV3Driver || !command.Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC)) || command.Connection.TestRestrictedSqlBindType(this._bindtype._sql_type))
                {
                    this._bindtype = TypeMap._VarChar;
                    if ((bytes != null) && !Convert.IsDBNull(bytes))
                    {
                        bytes  = ((decimal)bytes).ToString(CultureInfo.CurrentCulture);
                        length = ((string)bytes).Length;
                        offset = 0;
                    }
                }
                break;
            }
            ODBC32.SQL_C cHAR = this._bindtype._sql_c;
            if (!command.Connection.IsV3Driver && (cHAR == ODBC32.SQL_C.WCHAR))
            {
                cHAR = ODBC32.SQL_C.CHAR;
                if (((bytes != null) && !Convert.IsDBNull(bytes)) && (bytes is string))
                {
                    CultureInfo info = new CultureInfo(CultureInfo.CurrentCulture.LCID);
                    bytes  = Encoding.GetEncoding(info.TextInfo.ANSICodePage).GetBytes(bytes.ToString());
                    length = ((byte[])bytes).Length;
                }
            }
            int num2 = this.GetParameterSize(bytes, offset, ordinal);

            switch (this._bindtype._sql_type)
            {
            case ODBC32.SQL_TYPE.WVARCHAR:
                if (num2 > 0xfa0)
                {
                    this._bindtype = TypeMap._NText;
                }
                break;

            case ODBC32.SQL_TYPE.VARBINARY:
                if (num2 > 0x1f40)
                {
                    this._bindtype = TypeMap._Image;
                }
                break;

            case ODBC32.SQL_TYPE.VARCHAR:
                if (num2 > 0x1f40)
                {
                    this._bindtype = TypeMap._Text;
                }
                break;
            }
            this._prepared_Sql_C_Type = cHAR;
            this._preparedOffset      = offset;
            this._preparedSize        = length;
            this._preparedValue       = bytes;
            this._preparedBufferSize  = num2;
            this._preparedIntOffset   = parameterBufferSize;
            this._preparedValueOffset = this._preparedIntOffset + IntPtr.Size;
            parameterBufferSize      += num2 + IntPtr.Size;
        }
Exemple #19
0
        internal object MarshalToManaged(int offset, ODBC32.SQL_C sqlctype, int cb)
        {
            object value;

            switch (sqlctype)
            {
            case ODBC32.SQL_C.WCHAR:
                //Note: We always bind as unicode
                if (cb == ODBC32.SQL_NTS)
                {
                    value = PtrToStringUni(offset);
                    break;
                }
                Debug.Assert((cb > 0), "Character count negative ");
                Debug.Assert((Length >= cb), "Native buffer too small ");
                cb    = Math.Min(cb / 2, (Length - 2) / 2);
                value = PtrToStringUni(offset, cb);
                break;

            case ODBC32.SQL_C.CHAR:
            case ODBC32.SQL_C.BINARY:
                Debug.Assert((cb > 0), "Character count negative ");
                Debug.Assert((Length >= cb), "Native buffer too small ");
                cb    = Math.Min(cb, Length);
                value = ReadBytes(offset, cb);
                break;

            case ODBC32.SQL_C.SSHORT:
                value = ReadInt16(offset);
                break;

            case ODBC32.SQL_C.SLONG:
                value = ReadInt32(offset);
                break;

            case ODBC32.SQL_C.SBIGINT:
                value = ReadInt64(offset);
                break;

            case ODBC32.SQL_C.BIT:
                byte b = ReadByte(offset);
                value = (b != 0x00);
                break;

            case ODBC32.SQL_C.REAL:
                value = ReadSingle(offset);
                break;

            case ODBC32.SQL_C.DOUBLE:
                value = ReadDouble(offset);
                break;

            case ODBC32.SQL_C.UTINYINT:
                value = ReadByte(offset);
                break;

            case ODBC32.SQL_C.GUID:
                value = ReadGuid(offset);
                break;

            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)
                //}

                value = ReadDateTime(offset);
                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;

                value = ReadDate(offset);
                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;

                value = ReadTime(offset);
                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;   /* 1 if positive, 0 if negative */
                //  SQLCHAR     val[SQL_MAX_NUMERIC_LEN];
                //} SQL_NUMERIC_STRUCT;

                value = ReadNumeric(offset);
                break;

            default:
                Debug.Fail("UnknownSQLCType");
                value = null;
                break;
            }
            ;
            return(value);
        }
Exemple #20
0
        internal void Bind(OdbcStatementHandle hstmt, OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance)
        {
            ODBC32.SQL_C     sql_c       = this._prepared_Sql_C_Type;
            ODBC32.SQL_PARAM sql_param   = this.SqlDirectionFromParameterDirection();
            int       offset             = this._preparedOffset;
            int       sizeorprecision    = this._preparedSize;
            object    obj2               = this._preparedValue;
            int       valueSize          = this.GetValueSize(obj2, offset);
            int       num4               = this.GetColumnSize(obj2, offset, ordinal);
            byte      parameterPrecision = this.GetParameterPrecision(obj2);
            byte      parameterScale     = this.GetParameterScale(obj2);
            HandleRef buffer             = parameterBuffer.PtrOffset(this._preparedValueOffset, this._preparedBufferSize);
            HandleRef intbuffer          = parameterBuffer.PtrOffset(this._preparedIntOffset, IntPtr.Size);

            if (ODBC32.SQL_C.NUMERIC == sql_c)
            {
                if (((ODBC32.SQL_PARAM.INPUT_OUTPUT == sql_param) && (obj2 is decimal)) && (parameterScale < this._internalScale))
                {
                    while (parameterScale < this._internalScale)
                    {
                        obj2           = ((decimal)obj2) * 10M;
                        parameterScale = (byte)(parameterScale + 1);
                    }
                }
                this.SetInputValue(obj2, sql_c, valueSize, parameterPrecision, 0, parameterBuffer);
                if (ODBC32.SQL_PARAM.INPUT != sql_param)
                {
                    parameterBuffer.WriteInt16(this._preparedValueOffset, (short)((parameterScale << 8) | parameterPrecision));
                }
            }
            else
            {
                this.SetInputValue(obj2, sql_c, valueSize, sizeorprecision, offset, parameterBuffer);
            }
            if (((this._hasChanged || (this._boundSqlCType != sql_c)) || ((this._boundParameterType != this._bindtype._sql_type) || (this._boundSize != num4))) || (((this._boundScale != parameterScale) || (this._boundBuffer != buffer.Handle)) || (this._boundIntbuffer != intbuffer.Handle)))
            {
                ODBC32.RetCode retcode = hstmt.BindParameter(ordinal, (short)sql_param, sql_c, this._bindtype._sql_type, (IntPtr)num4, (IntPtr)parameterScale, buffer, (IntPtr)this._preparedBufferSize, intbuffer);
                if (retcode != ODBC32.RetCode.SUCCESS)
                {
                    if ("07006" == command.GetDiagSqlState())
                    {
                        Bid.Trace("<odbc.OdbcParameter.Bind|ERR> Call to BindParameter returned errorcode [07006]\n");
                        command.Connection.FlagRestrictedSqlBindType(this._bindtype._sql_type);
                        if (allowReentrance)
                        {
                            this.Bind(hstmt, command, ordinal, parameterBuffer, false);
                            return;
                        }
                    }
                    command.Connection.HandleError(hstmt, retcode);
                }
                this._hasChanged         = false;
                this._boundSqlCType      = sql_c;
                this._boundParameterType = this._bindtype._sql_type;
                this._boundSize          = num4;
                this._boundScale         = parameterScale;
                this._boundBuffer        = buffer.Handle;
                this._boundIntbuffer     = intbuffer.Handle;
                if (ODBC32.SQL_C.NUMERIC == sql_c)
                {
                    OdbcDescriptorHandle descriptorHandle = command.GetDescriptorHandle(ODBC32.SQL_ATTR.APP_PARAM_DESC);
                    retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.TYPE, (IntPtr)2L);
                    if (retcode != ODBC32.RetCode.SUCCESS)
                    {
                        command.Connection.HandleError(hstmt, retcode);
                    }
                    int num2 = parameterPrecision;
                    retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.PRECISION, (IntPtr)num2);
                    if (retcode != ODBC32.RetCode.SUCCESS)
                    {
                        command.Connection.HandleError(hstmt, retcode);
                    }
                    num2    = parameterScale;
                    retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.SCALE, (IntPtr)num2);
                    if (retcode != ODBC32.RetCode.SUCCESS)
                    {
                        command.Connection.HandleError(hstmt, retcode);
                    }
                    retcode = descriptorHandle.SetDescriptionField2(ordinal, ODBC32.SQL_DESC.DATA_PTR, buffer);
                    if (retcode != ODBC32.RetCode.SUCCESS)
                    {
                        command.Connection.HandleError(hstmt, retcode);
                    }
                }
            }
        }
Exemple #21
0
        internal void PrepareForBind(OdbcCommand command, short ordinal, ref int parameterBufferSize)
        {
            // make a snapshot of the current properties. Properties may change while we work on them
            //
            CopyParameterInternal();

            object value  = ProcessAndGetParameterValue();
            int    offset = _internalOffset;
            int    size   = _internalSize;

            ODBC32.SQL_C sql_c_type;


            // offset validation based on the values type
            //
            if (offset > 0)
            {
                if (value is string)
                {
                    if (offset > ((string)value).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else if (value is char[])
                {
                    if (offset > ((char[])value).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else if (value is byte[])
                {
                    if (offset > ((byte[])value).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else
                {
                    // for all other types offset has no meaning
                    // this is important since we might upgrade some types to strings
                    offset = 0;
                }
            }

            // type support verification for certain data types
            //
            switch (_bindtype._sql_type)
            {
            case ODBC32.SQL_TYPE.DECIMAL:
            case ODBC32.SQL_TYPE.NUMERIC:
                if (
                    !command.Connection.IsV3Driver ||                                       // for non V3 driver we always do the conversion
                    !command.Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC) ||         // otherwise we convert if the driver does not support numeric
                    command.Connection.TestRestrictedSqlBindType(_bindtype._sql_type)       // or the type is not supported
                    )
                {
                    // No support for NUMERIC
                    // Change the type
                    _bindtype = TypeMap._VarChar;
                    if ((null != value) && !Convert.IsDBNull(value))
                    {
                        value  = ((Decimal)value).ToString(CultureInfo.CurrentCulture);
                        size   = ((string)value).Length;
                        offset = 0;
                    }
                }
                break;

            case ODBC32.SQL_TYPE.BIGINT:
                if (!command.Connection.IsV3Driver)
                {
                    // No support for BIGINT
                    // Change the type
                    _bindtype = TypeMap._VarChar;
                    if ((null != value) && !Convert.IsDBNull(value))
                    {
                        value  = ((Int64)value).ToString(CultureInfo.CurrentCulture);
                        size   = ((string)value).Length;
                        offset = 0;
                    }
                }
                break;

            case ODBC32.SQL_TYPE.WCHAR:     // MDAC 68993
            case ODBC32.SQL_TYPE.WVARCHAR:
            case ODBC32.SQL_TYPE.WLONGVARCHAR:
                if (value is char)
                {
                    value  = value.ToString();
                    size   = ((string)value).Length;
                    offset = 0;
                }
                if (!command.Connection.TestTypeSupport(_bindtype._sql_type))
                {
                    // No support for WCHAR, WVARCHAR or WLONGVARCHAR
                    // Change the type
                    if (ODBC32.SQL_TYPE.WCHAR == _bindtype._sql_type)
                    {
                        _bindtype = TypeMap._Char;
                    }
                    else if (ODBC32.SQL_TYPE.WVARCHAR == _bindtype._sql_type)
                    {
                        _bindtype = TypeMap._VarChar;
                    }
                    else if (ODBC32.SQL_TYPE.WLONGVARCHAR == _bindtype._sql_type)
                    {
                        _bindtype = TypeMap._Text;
                    }
                }
                break;
            } // end switch

            // Conversation from WCHAR to CHAR, VARCHAR or LONVARCHAR (AnsiString) is different for some providers
            // we need to chonvert WCHAR to CHAR and bind as sql_c_type = CHAR
            //
            sql_c_type = _bindtype._sql_c;

            if (!command.Connection.IsV3Driver)
            {
                if (sql_c_type == ODBC32.SQL_C.WCHAR)
                {
                    sql_c_type = ODBC32.SQL_C.CHAR;

                    if (null != value)
                    {
                        if (!Convert.IsDBNull(value) && value is string)
                        {
                            int         lcid    = System.Globalization.CultureInfo.CurrentCulture.LCID;
                            CultureInfo culInfo = new CultureInfo(lcid);
                            Encoding    cpe     = System.Text.Encoding.GetEncoding(culInfo.TextInfo.ANSICodePage);
                            value = cpe.GetBytes(value.ToString());
                            size  = ((byte[])value).Length;
                        }
                    }
                }
            }
            ;

            int cbParameterSize = GetParameterSize(value, offset, ordinal); // count of bytes for the data, for SQLBindParameter

            // Upgrade input value type if the size of input value is bigger than the max size of the input value type.
            switch (_bindtype._sql_type)
            {
            case ODBC32.SQL_TYPE.VARBINARY:
                // Max length of VARBINARY is 8,000 of byte array.
                if (size > 8000)
                {
                    _bindtype = TypeMap._Image;     // will change to LONGVARBINARY
                }
                break;

            case ODBC32.SQL_TYPE.VARCHAR:
                // Max length of VARCHAR is 8,000 of non-unicode characters.
                if (size > 8000)
                {
                    _bindtype = TypeMap._Text;     // will change to LONGVARCHAR
                }
                break;

            case ODBC32.SQL_TYPE.WVARCHAR:
                // Max length of WVARCHAR (NVARCHAR) is 4,000 of unicode characters.
                if (size > 4000)
                {
                    _bindtype = TypeMap._NText;     // will change to WLONGVARCHAR
                }
                break;
            }

            _prepared_Sql_C_Type = sql_c_type;
            _preparedOffset      = offset;
            _preparedSize        = size;
            _preparedValue       = value;
            _preparedBufferSize  = cbParameterSize;
            _preparedIntOffset   = parameterBufferSize;
            _preparedValueOffset = _preparedIntOffset + IntPtr.Size;
            parameterBufferSize += (cbParameterSize + IntPtr.Size);
        }
Exemple #22
0
 static internal Exception UnknownSQLCType(ODBC32.SQL_C sqlctype)
 {
     return(Argument(Res.GetString(GetCultureInfo(), Res.Odbc_UnknownSQLCType, sqlctype.ToString())));
 }
        internal void MarshalToNative(int offset, object value, ODBC32.SQL_C sqlctype, int sizeorprecision, int valueOffset)
        {
            ODBC32.SQL_C sql_c = sqlctype;
            if (sql_c <= ODBC32.SQL_C.SSHORT)
            {
                if (sql_c != ODBC32.SQL_C.UTINYINT)
                {
                    switch (sql_c)
                    {
                    case ODBC32.SQL_C.SLONG:
                        base.WriteInt32(offset, (int)value);
                        return;

                    case ODBC32.SQL_C.SSHORT:
                        base.WriteInt16(offset, (short)value);
                        return;

                    case ODBC32.SQL_C.SBIGINT:
                        base.WriteInt64(offset, (long)value);
                        return;
                    }
                }
                else
                {
                    base.WriteByte(offset, (byte)value);
                }
            }
            else if (sql_c <= ODBC32.SQL_C.NUMERIC)
            {
                switch (sql_c)
                {
                case ODBC32.SQL_C.GUID:
                    base.WriteGuid(offset, (Guid)value);
                    return;

                case ~(ODBC32.SQL_C.CHAR | ODBC32.SQL_C.DOUBLE):
                case ~ODBC32.SQL_C.DOUBLE:
                case ((ODBC32.SQL_C)(-1)):
                case ((ODBC32.SQL_C) 0):
                    return;

                case ODBC32.SQL_C.WCHAR:
                    int    num;
                    char[] chArray;
                    if (value is string)
                    {
                        num = Math.Max(0, ((string)value).Length - valueOffset);
                        if ((sizeorprecision > 0) && (sizeorprecision < num))
                        {
                            num = sizeorprecision;
                        }
                        chArray = ((string)value).ToCharArray(valueOffset, num);
                        base.WriteCharArray(offset, chArray, 0, chArray.Length);
                        base.WriteInt16(offset + (chArray.Length * 2), 0);
                        return;
                    }
                    num = Math.Max(0, ((char[])value).Length - valueOffset);
                    if ((sizeorprecision > 0) && (sizeorprecision < num))
                    {
                        num = sizeorprecision;
                    }
                    chArray = (char[])value;
                    base.WriteCharArray(offset, chArray, valueOffset, num);
                    base.WriteInt16(offset + (chArray.Length * 2), 0);
                    return;

                case ODBC32.SQL_C.BIT:
                    base.WriteByte(offset, ((bool)value) ? ((byte)1) : ((byte)0));
                    return;

                case ODBC32.SQL_C.BINARY:
                case ODBC32.SQL_C.CHAR:
                {
                    byte[] source = (byte[])value;
                    int    length = source.Length;
                    length -= valueOffset;
                    if ((sizeorprecision > 0) && (sizeorprecision < length))
                    {
                        length = sizeorprecision;
                    }
                    base.WriteBytes(offset, source, valueOffset, length);
                    return;
                }

                case ODBC32.SQL_C.NUMERIC:
                    base.WriteNumeric(offset, (decimal)value, (byte)sizeorprecision);
                    return;
                }
            }
            else
            {
                switch (sql_c)
                {
                case ODBC32.SQL_C.REAL:
                    base.WriteSingle(offset, (float)value);
                    return;

                case ODBC32.SQL_C.DOUBLE:
                    base.WriteDouble(offset, (double)value);
                    return;

                case ODBC32.SQL_C.TYPE_DATE:
                    base.WriteDate(offset, (DateTime)value);
                    return;

                case ODBC32.SQL_C.TYPE_TIME:
                    base.WriteTime(offset, (TimeSpan)value);
                    return;

                case ODBC32.SQL_C.TYPE_TIMESTAMP:
                    this.WriteODBCDateTime(offset, (DateTime)value);
                    return;

                default:
                    return;
                }
            }
        }
 internal void Bind(OdbcStatementHandle hstmt, OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance)
 {
     ODBC32.SQL_C sql_c = this._prepared_Sql_C_Type;
     ODBC32.SQL_PARAM sql_param = this.SqlDirectionFromParameterDirection();
     int offset = this._preparedOffset;
     int sizeorprecision = this._preparedSize;
     object obj2 = this._preparedValue;
     int valueSize = this.GetValueSize(obj2, offset);
     int num4 = this.GetColumnSize(obj2, offset, ordinal);
     byte parameterPrecision = this.GetParameterPrecision(obj2);
     byte parameterScale = this.GetParameterScale(obj2);
     HandleRef buffer = parameterBuffer.PtrOffset(this._preparedValueOffset, this._preparedBufferSize);
     HandleRef intbuffer = parameterBuffer.PtrOffset(this._preparedIntOffset, IntPtr.Size);
     if (ODBC32.SQL_C.NUMERIC == sql_c)
     {
         if (((ODBC32.SQL_PARAM.INPUT_OUTPUT == sql_param) && (obj2 is decimal)) && (parameterScale < this._internalScale))
         {
             while (parameterScale < this._internalScale)
             {
                 obj2 = ((decimal) obj2) * 10M;
                 parameterScale = (byte) (parameterScale + 1);
             }
         }
         this.SetInputValue(obj2, sql_c, valueSize, parameterPrecision, 0, parameterBuffer);
         if (ODBC32.SQL_PARAM.INPUT != sql_param)
         {
             parameterBuffer.WriteInt16(this._preparedValueOffset, (short) ((parameterScale << 8) | parameterPrecision));
         }
     }
     else
     {
         this.SetInputValue(obj2, sql_c, valueSize, sizeorprecision, offset, parameterBuffer);
     }
     if (((this._hasChanged || (this._boundSqlCType != sql_c)) || ((this._boundParameterType != this._bindtype._sql_type) || (this._boundSize != num4))) || (((this._boundScale != parameterScale) || (this._boundBuffer != buffer.Handle)) || (this._boundIntbuffer != intbuffer.Handle)))
     {
         ODBC32.RetCode retcode = hstmt.BindParameter(ordinal, (short) sql_param, sql_c, this._bindtype._sql_type, (IntPtr) num4, (IntPtr) parameterScale, buffer, (IntPtr) this._preparedBufferSize, intbuffer);
         if (retcode != ODBC32.RetCode.SUCCESS)
         {
             if ("07006" == command.GetDiagSqlState())
             {
                 Bid.Trace("<odbc.OdbcParameter.Bind|ERR> Call to BindParameter returned errorcode [07006]\n");
                 command.Connection.FlagRestrictedSqlBindType(this._bindtype._sql_type);
                 if (allowReentrance)
                 {
                     this.Bind(hstmt, command, ordinal, parameterBuffer, false);
                     return;
                 }
             }
             command.Connection.HandleError(hstmt, retcode);
         }
         this._hasChanged = false;
         this._boundSqlCType = sql_c;
         this._boundParameterType = this._bindtype._sql_type;
         this._boundSize = num4;
         this._boundScale = parameterScale;
         this._boundBuffer = buffer.Handle;
         this._boundIntbuffer = intbuffer.Handle;
         if (ODBC32.SQL_C.NUMERIC == sql_c)
         {
             OdbcDescriptorHandle descriptorHandle = command.GetDescriptorHandle(ODBC32.SQL_ATTR.APP_PARAM_DESC);
             retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.TYPE, (IntPtr) 2L);
             if (retcode != ODBC32.RetCode.SUCCESS)
             {
                 command.Connection.HandleError(hstmt, retcode);
             }
             int num2 = parameterPrecision;
             retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.PRECISION, (IntPtr) num2);
             if (retcode != ODBC32.RetCode.SUCCESS)
             {
                 command.Connection.HandleError(hstmt, retcode);
             }
             num2 = parameterScale;
             retcode = descriptorHandle.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.SCALE, (IntPtr) num2);
             if (retcode != ODBC32.RetCode.SUCCESS)
             {
                 command.Connection.HandleError(hstmt, retcode);
             }
             retcode = descriptorHandle.SetDescriptionField2(ordinal, ODBC32.SQL_DESC.DATA_PTR, buffer);
             if (retcode != ODBC32.RetCode.SUCCESS)
             {
                 command.Connection.HandleError(hstmt, retcode);
             }
         }
     }
 }
        internal void Bind(OdbcStatementHandle hstmt, OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance) {
            ODBC32.RetCode  retcode;
            ODBC32.SQL_C    sql_c_type = _prepared_Sql_C_Type;
            ODBC32.SQL_PARAM sqldirection = SqlDirectionFromParameterDirection();

            int offset      = _preparedOffset;
            int size        = _preparedSize;
            object value    = _preparedValue;
            int cbValueSize = GetValueSize(value, offset);             // count of bytes for the data
            int cchSize     = GetColumnSize(value, offset, ordinal);   // count of bytes for the data, used to allocate the buffer length
            byte precision  = GetParameterPrecision(value);
            byte scale      = GetParameterScale(value);
            int cbActual;

            HandleRef valueBuffer  = parameterBuffer.PtrOffset(_preparedValueOffset, _preparedBufferSize);
            HandleRef intBuffer    = parameterBuffer.PtrOffset(_preparedIntOffset, IntPtr.Size);

            // for the numeric datatype we need to do some special case handling ...
            //
            if (ODBC32.SQL_C.NUMERIC == sql_c_type) {

                // for input/output parameters we need to adjust the scale of the input value since the convert function in
                // sqlsrv32 takes this scale for the output parameter (possible bug in sqlsrv32?)
                //
                if ((ODBC32.SQL_PARAM.INPUT_OUTPUT == sqldirection) && (value is Decimal)) {
                    if (scale < _internalScale) {
                        while (scale < _internalScale) {
                            value = ((decimal)value ) * 10;
                            scale++;
                        }
                    }
                }
                SetInputValue(value, sql_c_type, cbValueSize, precision, 0, parameterBuffer);

                // for output parameters we need to write precision and scale to the buffer since the convert function in
                // sqlsrv32 expects these values there (possible bug in sqlsrv32?)
                //
                if (ODBC32.SQL_PARAM.INPUT != sqldirection) {
                    parameterBuffer.WriteInt16(_preparedValueOffset, (short)(((ushort)scale << 8) | (ushort)precision));
                }
            }
            else {
                SetInputValue(value, sql_c_type, cbValueSize, size, offset, parameterBuffer);
            }


            // Try to reuse existing bindings if
            //  the binding is valid (means we already went through binding all parameters)
            //  the parametercollection is bound already
            //  the bindtype ParameterType did not change (forced upgrade)

            if (!_hasChanged
                && (_boundSqlCType == sql_c_type)
                && (_boundParameterType == _bindtype._sql_type)
                && (_boundSize == cchSize)
                && (_boundScale == scale)
                && (_boundBuffer == valueBuffer.Handle)
                && (_boundIntbuffer == intBuffer.Handle)
            ) {
                return;
            }

            //SQLBindParameter
            retcode = hstmt.BindParameter(
                                    ordinal,                    // Parameter Number
                                    (short)sqldirection,        // InputOutputType
                                    sql_c_type,                 // ValueType
                                    _bindtype._sql_type,        // ParameterType
                                    (IntPtr)cchSize,            // ColumnSize
                                    (IntPtr)scale,              // DecimalDigits
                                    valueBuffer,                // ParameterValuePtr
                                    (IntPtr)_preparedBufferSize,
                                    intBuffer);                 // StrLen_or_IndPtr

            if (ODBC32.RetCode.SUCCESS != retcode) {
                if ("07006" == command.GetDiagSqlState()) {
                    Bid.Trace("<odbc.OdbcParameter.Bind|ERR> Call to BindParameter returned errorcode [07006]\n");
                    command.Connection.FlagRestrictedSqlBindType(_bindtype._sql_type);
                    if (allowReentrance) {
                        this.Bind(hstmt, command, ordinal, parameterBuffer, false);
                        return;
                    }
                }
                command.Connection.HandleError(hstmt, retcode);
            }
            _hasChanged = false;
            _boundSqlCType = sql_c_type;
            _boundParameterType = _bindtype._sql_type;
            _boundSize = cchSize;
            _boundScale = scale;
            _boundBuffer = valueBuffer.Handle;
            _boundIntbuffer = intBuffer.Handle;

            if (ODBC32.SQL_C.NUMERIC == sql_c_type) {
                OdbcDescriptorHandle hdesc = command.GetDescriptorHandle(ODBC32.SQL_ATTR.APP_PARAM_DESC);
                // descriptor handle is cached on command wrapper, don't release it

                // Set descriptor Type
                //
                //SQLSetDescField(hdesc, i+1, SQL_DESC_TYPE, (void *)SQL_C_NUMERIC, 0);
                retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.TYPE, (IntPtr)ODBC32.SQL_C.NUMERIC);

                if (ODBC32.RetCode.SUCCESS != retcode) {
                    command.Connection.HandleError(hstmt, retcode);
                }


                // Set precision
                //
                cbActual= (int)precision;
                //SQLSetDescField(hdesc, i+1, SQL_DESC_PRECISION, (void *)precision, 0);
                retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.PRECISION, (IntPtr)cbActual);

                if (ODBC32.RetCode.SUCCESS != retcode) {
                    command.Connection.HandleError(hstmt, retcode);
                }


                // Set scale
                //
                // SQLSetDescField(hdesc, i+1, SQL_DESC_SCALE,  (void *)llen, 0);
                cbActual= (int)scale;
                retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.SCALE, (IntPtr)cbActual);

                if (ODBC32.RetCode.SUCCESS != retcode) {
                    command.Connection.HandleError(hstmt, retcode);
                }

                // Set data pointer
                //
                // SQLSetDescField(hdesc, i+1, SQL_DESC_DATA_PTR,  (void *)&numeric, 0);
                retcode = hdesc.SetDescriptionField2(ordinal, ODBC32.SQL_DESC.DATA_PTR, valueBuffer);

                if (ODBC32.RetCode.SUCCESS != retcode) {
                    command.Connection.HandleError(hstmt, retcode);
                }
            }
        }
 internal ODBC32.RetCode BindParameter(short ordinal, short parameterDirection, ODBC32.SQL_C sqlctype, ODBC32.SQL_TYPE sqltype, IntPtr cchSize, IntPtr scale, HandleRef buffer, IntPtr bufferLength, HandleRef intbuffer)
 {
     ODBC32.RetCode retcode = Interop.Odbc.SQLBindParameter(this,
                                                            checked ((ushort)ordinal), // Parameter Number
                                                            parameterDirection,        // InputOutputType
                                                            sqlctype,                  // ValueType
                                                            checked ((short)sqltype),  // ParameterType
                                                            cchSize,                   // ColumnSize
                                                            scale,                     // DecimalDigits
                                                            buffer,                    // ParameterValuePtr
                                                            bufferLength,              // BufferLength
                                                            intbuffer);                // StrLen_or_IndPtr
     ODBC.TraceODBC(3, "SQLBindParameter", retcode);
     return(retcode);
 }
Exemple #27
0
        // if sizeorprecision applies only for wchar and numeric values
        // for wchar the a value of null means take the value's size
        //
        internal void MarshalToNative(int offset, object value, ODBC32.SQL_C sqlctype, int sizeorprecision, int valueOffset)
        {
            switch (sqlctype)
            {
            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;
                int    length;
                Debug.Assert(value is string || value is char[], "Only string or char[] can be marshaled to WCHAR");

                if (value is string)
                {
                    length = Math.Max(0, ((string)value).Length - valueOffset);

                    if ((sizeorprecision > 0) && (sizeorprecision < length))
                    {
                        length = sizeorprecision;
                    }

                    rgChars = ((string)value).ToCharArray(valueOffset, length);
                    Debug.Assert(rgChars.Length < (base.Length - valueOffset), "attempting to extend parameter buffer!");

                    WriteCharArray(offset, rgChars, 0, rgChars.Length);
                    WriteInt16(offset + (rgChars.Length * 2), 0);         // Add the null terminator
                }
                else
                {
                    length = Math.Max(0, ((char[])value).Length - valueOffset);
                    if ((sizeorprecision > 0) && (sizeorprecision < length))
                    {
                        length = sizeorprecision;
                    }
                    rgChars = (char[])value;
                    Debug.Assert(rgChars.Length < (base.Length - valueOffset), "attempting to extend parameter buffer!");

                    WriteCharArray(offset, rgChars, valueOffset, length);
                    WriteInt16(offset + (rgChars.Length * 2), 0);         // Add the null terminator
                }
                break;
            }

            case ODBC32.SQL_C.BINARY:
            case ODBC32.SQL_C.CHAR:
            {
                byte[] rgBytes = (byte[])value;
                int    length  = rgBytes.Length;

                Debug.Assert((valueOffset <= length), "Offset out of Range");

                // reduce length by the valueOffset
                //
                length -= valueOffset;

                // reduce length to be no more than size (if size is given)
                //
                if ((sizeorprecision > 0) && (sizeorprecision < length))
                {
                    length = sizeorprecision;
                }

                //AdjustSize(rgBytes.Length+1);
                //buffer = DangerousAllocateAndGetHandle();      // Realloc may have changed buffer address
                Debug.Assert(length < (base.Length - valueOffset), "attempting to extend parameter buffer!");

                WriteBytes(offset, rgBytes, valueOffset, length);
                break;
            }

            case ODBC32.SQL_C.UTINYINT:
                WriteByte(offset, (byte)value);
                break;

            case ODBC32.SQL_C.SSHORT:       //Int16
                WriteInt16(offset, (short)value);
                break;

            case ODBC32.SQL_C.SLONG:        //Int32
                WriteInt32(offset, (int)value);
                break;

            case ODBC32.SQL_C.REAL:         //float
                WriteSingle(offset, (float)value);
                break;

            case ODBC32.SQL_C.SBIGINT:      //Int64
                WriteInt64(offset, (long)value);
                break;

            case ODBC32.SQL_C.DOUBLE:       //Double
                WriteDouble(offset, (double)value);
                break;

            case ODBC32.SQL_C.GUID:         //Guid
                WriteGuid(offset, (Guid)value);
                break;

            case ODBC32.SQL_C.BIT:
                WriteByte(offset, (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)

                WriteODBCDateTime(offset, (DateTime)value);
                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;

                WriteDate(offset, (DateTime)value);
                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;

                WriteTime(offset, (TimeSpan)value);
                break;
            }

            case ODBC32.SQL_C.NUMERIC:
            {
                WriteNumeric(offset, (decimal)value, checked ((byte)sizeorprecision));
                break;
            }

            default:
                Debug.Fail("UnknownSQLCType");
                break;
            }
        }
 internal ODBC32.RetCode GetData(int index, ODBC32.SQL_C sqlctype, CNativeBuffer buffer, int cb, out IntPtr cbActual)
 {
     ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetData(this, (ushort)index, sqlctype, buffer, new IntPtr(cb), out cbActual);
     ODBC.TraceODBC(3, "SQLGetData", retcode);
     return(retcode);
 }
        internal readonly bool _signType;   // this type may be has signature information

        private TypeMap(OdbcType odbcType, DbType dbType, Type type, ODBC32.SQL_TYPE sql_type, ODBC32.SQL_C sql_c, ODBC32.SQL_C param_sql_c, int bsize, int csize, bool signType) {
            _odbcType = odbcType;
            _dbType = dbType;
            _type = type;

            _sql_type = sql_type;
            _sql_c = sql_c;
            _param_sql_c = param_sql_c; // alternative sql_c type for parameters

            _bufferSize = bsize;
            _columnSize = csize;
            _signType = signType;
        }
 internal static extern ODBC32.RetCode SQLBindParameter(OdbcStatementHandle StatementHandle, ushort ParameterNumber, short ParamDirection, ODBC32.SQL_C SQLCType, short SQLType, IntPtr cbColDef, IntPtr ibScale, HandleRef rgbValue, IntPtr BufferLength, HandleRef StrLen_or_Ind);
 internal ODBC32.RetCode BindColumn2(int columnNumber, ODBC32.SQL_C targetType, HandleRef buffer, IntPtr length, IntPtr srLen_or_Ind)
 {
     ODBC32.RetCode retcode = UnsafeNativeMethods.SQLBindCol(this, (ushort)columnNumber, targetType, buffer, length, srLen_or_Ind);
     ODBC.TraceODBC(3, "SQLBindCol", retcode);
     return(retcode);
 }
        internal void PrepareForBind(OdbcCommand command, short ordinal, ref int parameterBufferSize)
        {
            this.CopyParameterInternal();
            object bytes = this.ProcessAndGetParameterValue();
            int offset = this._internalOffset;
            int length = this._internalSize;
            if (offset > 0)
            {
                if (bytes is string)
                {
                    if (offset > ((string) bytes).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else if (bytes is char[])
                {
                    if (offset > ((char[]) bytes).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else if (bytes is byte[])
                {
                    if (offset > ((byte[]) bytes).Length)
                    {
                        throw ADP.OffsetOutOfRangeException();
                    }
                }
                else
                {
                    offset = 0;
                }
            }
            switch (this._bindtype._sql_type)
            {
                case ODBC32.SQL_TYPE.WLONGVARCHAR:
                case ODBC32.SQL_TYPE.WVARCHAR:
                case ODBC32.SQL_TYPE.WCHAR:
                    if (bytes is char)
                    {
                        bytes = bytes.ToString();
                        length = ((string) bytes).Length;
                        offset = 0;
                    }
                    if (!command.Connection.TestTypeSupport(this._bindtype._sql_type))
                    {
                        if (ODBC32.SQL_TYPE.WCHAR == this._bindtype._sql_type)
                        {
                            this._bindtype = TypeMap._Char;
                        }
                        else if (ODBC32.SQL_TYPE.WVARCHAR == this._bindtype._sql_type)
                        {
                            this._bindtype = TypeMap._VarChar;
                        }
                        else if (ODBC32.SQL_TYPE.WLONGVARCHAR == this._bindtype._sql_type)
                        {
                            this._bindtype = TypeMap._Text;
                        }
                    }
                    break;

                case ODBC32.SQL_TYPE.BIGINT:
                    if (!command.Connection.IsV3Driver)
                    {
                        this._bindtype = TypeMap._VarChar;
                        if ((bytes != null) && !Convert.IsDBNull(bytes))
                        {
                            bytes = ((long) bytes).ToString(CultureInfo.CurrentCulture);
                            length = ((string) bytes).Length;
                            offset = 0;
                        }
                    }
                    break;

                case ODBC32.SQL_TYPE.NUMERIC:
                case ODBC32.SQL_TYPE.DECIMAL:
                    if ((!command.Connection.IsV3Driver || !command.Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC)) || command.Connection.TestRestrictedSqlBindType(this._bindtype._sql_type))
                    {
                        this._bindtype = TypeMap._VarChar;
                        if ((bytes != null) && !Convert.IsDBNull(bytes))
                        {
                            bytes = ((decimal) bytes).ToString(CultureInfo.CurrentCulture);
                            length = ((string) bytes).Length;
                            offset = 0;
                        }
                    }
                    break;
            }
            ODBC32.SQL_C cHAR = this._bindtype._sql_c;
            if (!command.Connection.IsV3Driver && (cHAR == ODBC32.SQL_C.WCHAR))
            {
                cHAR = ODBC32.SQL_C.CHAR;
                if (((bytes != null) && !Convert.IsDBNull(bytes)) && (bytes is string))
                {
                    CultureInfo info = new CultureInfo(CultureInfo.CurrentCulture.LCID);
                    bytes = Encoding.GetEncoding(info.TextInfo.ANSICodePage).GetBytes(bytes.ToString());
                    length = ((byte[]) bytes).Length;
                }
            }
            int num2 = this.GetParameterSize(bytes, offset, ordinal);
            switch (this._bindtype._sql_type)
            {
                case ODBC32.SQL_TYPE.WVARCHAR:
                    if (num2 > 0xfa0)
                    {
                        this._bindtype = TypeMap._NText;
                    }
                    break;

                case ODBC32.SQL_TYPE.VARBINARY:
                    if (num2 > 0x1f40)
                    {
                        this._bindtype = TypeMap._Image;
                    }
                    break;

                case ODBC32.SQL_TYPE.VARCHAR:
                    if (num2 > 0x1f40)
                    {
                        this._bindtype = TypeMap._Text;
                    }
                    break;
            }
            this._prepared_Sql_C_Type = cHAR;
            this._preparedOffset = offset;
            this._preparedSize = length;
            this._preparedValue = bytes;
            this._preparedBufferSize = num2;
            this._preparedIntOffset = parameterBufferSize;
            this._preparedValueOffset = this._preparedIntOffset + IntPtr.Size;
            parameterBufferSize += num2 + IntPtr.Size;
        }
 internal ODBC32.RetCode BindColumn3(int columnNumber, ODBC32.SQL_C targetType, IntPtr srLen_or_Ind)
 {
     ODBC32.RetCode retcode = UnsafeNativeMethods.SQLBindCol(this, (ushort)columnNumber, targetType, ADP.PtrZero, ADP.PtrZero, srLen_or_Ind);
     ODBC.TraceODBC(3, "SQLBindCol", retcode);
     return(retcode);
 }
 internal ODBC32.RetCode BindParameter(short ordinal, short parameterDirection, ODBC32.SQL_C sqlctype, ODBC32.SQL_TYPE sqltype, IntPtr cchSize, IntPtr scale, HandleRef buffer, IntPtr bufferLength, HandleRef intbuffer)
 {
     ODBC32.RetCode retcode = UnsafeNativeMethods.SQLBindParameter(this, (ushort)ordinal, parameterDirection, sqlctype, (short)sqltype, cchSize, scale, buffer, bufferLength, intbuffer);
     ODBC.TraceODBC(3, "SQLBindParameter", retcode);
     return(retcode);
 }
Exemple #35
0
        internal void Bind(OdbcStatementHandle hstmt, OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance)
        {
            ODBC32.RetCode   retcode;
            ODBC32.SQL_C     sql_c_type   = _prepared_Sql_C_Type;
            ODBC32.SQL_PARAM sqldirection = SqlDirectionFromParameterDirection();

            int    offset      = _preparedOffset;
            int    size        = _preparedSize;
            object value       = _preparedValue;
            int    cbValueSize = GetValueSize(value, offset);           // count of bytes for the data
            int    cchSize     = GetColumnSize(value, offset, ordinal); // count of bytes for the data, used to allocate the buffer length
            byte   precision   = GetParameterPrecision(value);
            byte   scale       = GetParameterScale(value);
            int    cbActual;

            HandleRef valueBuffer = parameterBuffer.PtrOffset(_preparedValueOffset, _preparedBufferSize);
            HandleRef intBuffer   = parameterBuffer.PtrOffset(_preparedIntOffset, IntPtr.Size);

            // for the numeric datatype we need to do some special case handling ...
            //
            if (ODBC32.SQL_C.NUMERIC == sql_c_type)
            {
                // for input/output parameters we need to adjust the scale of the input value since the convert function in
                // sqlsrv32 takes this scale for the output parameter (possible bug in sqlsrv32?)
                //
                if ((ODBC32.SQL_PARAM.INPUT_OUTPUT == sqldirection) && (value is decimal))
                {
                    if (scale < _internalScale)
                    {
                        while (scale < _internalScale)
                        {
                            value = ((decimal)value) * 10;
                            scale++;
                        }
                    }
                }
                SetInputValue(value, sql_c_type, cbValueSize, precision, 0, parameterBuffer);

                // for output parameters we need to write precision and scale to the buffer since the convert function in
                // sqlsrv32 expects these values there (possible bug in sqlsrv32?)
                //
                if (ODBC32.SQL_PARAM.INPUT != sqldirection)
                {
                    parameterBuffer.WriteInt16(_preparedValueOffset, (short)(((ushort)scale << 8) | (ushort)precision));
                }
            }
            else
            {
                SetInputValue(value, sql_c_type, cbValueSize, size, offset, parameterBuffer);
            }


            // Try to reuse existing bindings if
            //  the binding is valid (means we already went through binding all parameters)
            //  the parametercollection is bound already
            //  the bindtype ParameterType did not change (forced upgrade)

            if (!_hasChanged &&
                (_boundSqlCType == sql_c_type) &&
                (_boundParameterType == _bindtype._sql_type) &&
                (_boundSize == cchSize) &&
                (_boundScale == scale) &&
                (_boundBuffer == valueBuffer.Handle) &&
                (_boundIntbuffer == intBuffer.Handle)
                )
            {
                return;
            }

            //SQLBindParameter
            retcode = hstmt.BindParameter(
                ordinal,                                        // Parameter Number
                (short)sqldirection,                            // InputOutputType
                sql_c_type,                                     // ValueType
                _bindtype._sql_type,                            // ParameterType
                (IntPtr)cchSize,                                // ColumnSize
                (IntPtr)scale,                                  // DecimalDigits
                valueBuffer,                                    // ParameterValuePtr
                (IntPtr)_preparedBufferSize,
                intBuffer);                                     // StrLen_or_IndPtr

            if (ODBC32.RetCode.SUCCESS != retcode)
            {
                if ("07006" == command.GetDiagSqlState())
                {
                    command.Connection.FlagRestrictedSqlBindType(_bindtype._sql_type);
                    if (allowReentrance)
                    {
                        this.Bind(hstmt, command, ordinal, parameterBuffer, false);
                        return;
                    }
                }
                command.Connection.HandleError(hstmt, retcode);
            }
            _hasChanged         = false;
            _boundSqlCType      = sql_c_type;
            _boundParameterType = _bindtype._sql_type;
            _boundSize          = cchSize;
            _boundScale         = scale;
            _boundBuffer        = valueBuffer.Handle;
            _boundIntbuffer     = intBuffer.Handle;

            if (ODBC32.SQL_C.NUMERIC == sql_c_type)
            {
                OdbcDescriptorHandle hdesc = command.GetDescriptorHandle(ODBC32.SQL_ATTR.APP_PARAM_DESC);
                // descriptor handle is cached on command wrapper, don't release it

                // Set descriptor Type
                //
                //SQLSetDescField(hdesc, i+1, SQL_DESC_TYPE, (void *)SQL_C_NUMERIC, 0);
                retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.TYPE, (IntPtr)ODBC32.SQL_C.NUMERIC);

                if (ODBC32.RetCode.SUCCESS != retcode)
                {
                    command.Connection.HandleError(hstmt, retcode);
                }


                // Set precision
                //
                cbActual = (int)precision;
                //SQLSetDescField(hdesc, i+1, SQL_DESC_PRECISION, (void *)precision, 0);
                retcode = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.PRECISION, (IntPtr)cbActual);

                if (ODBC32.RetCode.SUCCESS != retcode)
                {
                    command.Connection.HandleError(hstmt, retcode);
                }


                // Set scale
                //
                // SQLSetDescField(hdesc, i+1, SQL_DESC_SCALE,  (void *)llen, 0);
                cbActual = (int)scale;
                retcode  = hdesc.SetDescriptionField1(ordinal, ODBC32.SQL_DESC.SCALE, (IntPtr)cbActual);

                if (ODBC32.RetCode.SUCCESS != retcode)
                {
                    command.Connection.HandleError(hstmt, retcode);
                }

                // Set data pointer
                //
                // SQLSetDescField(hdesc, i+1, SQL_DESC_DATA_PTR,  (void *)&numeric, 0);
                retcode = hdesc.SetDescriptionField2(ordinal, ODBC32.SQL_DESC.DATA_PTR, valueBuffer);

                if (ODBC32.RetCode.SUCCESS != retcode)
                {
                    command.Connection.HandleError(hstmt, retcode);
                }
            }
        }
        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);
            }
            ;
        }