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 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 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.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(HandleRef hstmt, OdbcCommand parent, short ordinal, CNativeBuffer buffer, CNativeBuffer intbuffer) { ODBC32.RETCODE retcode; int cbActual; ODBC32.SQL_C sql_c_type; object value = GetParameterValue(); switch (Direction) { case ParameterDirection.Input: Marshal.WriteInt32(intbuffer.Ptr, 0); break; case ParameterDirection.Output: case ParameterDirection.ReturnValue: Marshal.WriteInt32(intbuffer.Ptr, ODBC32.SQL_NULL_DATA); break; case ParameterDirection.InputOutput: Marshal.WriteInt32(intbuffer.Ptr, 0); break; default: throw ADP.InvalidParameterDirection((int)value, ParameterName); } // before we can do anything we need to verify if there is support // for certain data types // switch (_bindtype._sql_type) { case ODBC32.SQL_TYPE.DECIMAL: case ODBC32.SQL_TYPE.NUMERIC: Debug.Assert((null == value) || Convert.IsDBNull(value) || (value is Decimal), "value not decimal"); if ((_parent.Connection.OdbcMajorVersion < 3) || !((OdbcParameterCollection)_parent).Connection.TestTypeSupport(ODBC32.SQL_TYPE.NUMERIC)) { // No support for NUMERIC // Change the type _bindtype = TypeMap._VarChar; if ((null != value) && !Convert.IsDBNull(value)) { value = ((Decimal)value).ToString(); } } break; case ODBC32.SQL_TYPE.BIGINT: Debug.Assert((null == value) || Convert.IsDBNull(value) || (value is Int64), "value not Int64"); if (_parent.Connection.OdbcMajorVersion < 3) { // No support for BIGINT // Change the type _bindtype = TypeMap._VarChar; if ((null != value) && !Convert.IsDBNull(value)) { value = ((Int64)value).ToString(); } } break; case ODBC32.SQL_TYPE.WCHAR: // MDAC 68993 case ODBC32.SQL_TYPE.WVARCHAR: case ODBC32.SQL_TYPE.WLONGVARCHAR: Debug.Assert((null == value) || Convert.IsDBNull(value) || (value is String), "value not string"); if (!((OdbcParameterCollection)_parent).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 // WARNING: this is very UGLY code but an internal compilererror forces me to do so // (MDAC BUG 72163) // // 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 = (_parent.Connection.OdbcMajorVersion >= 3) ? _bindtype._sql_c : _bindtype._param_sql_c; if ((_parent.Connection.OdbcMajorVersion < 3) && (_bindtype._param_sql_c == ODBC32.SQL_C.CHAR)) { if ((value is String) && (null != value) && !Convert.IsDBNull(value)) { 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()); } } int cbParameterSize = GetParameterSize(value); // count of bytes for the data, for SQLBindParameter int cbValueSize = GetValueSize(value); // count of bytes for the data int cchSize = GetColumnSize(value); // count of bytes for the data, used to allocate the buffer length // 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; } // end switch //Allocate a our buffer to hold the input/output data //Note: cbValueSize is used in the SetInputValue to indicate how many bytes of variable //length data (which doesn't include the null terminator as spec'd), however our raw //buffer needs extra room for this buffer.EnsureAlloc(cbParameterSize); byte precision = GetParameterPrecision(value); byte scale = GetParameterScale(value); // 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 < this.scale) { while (scale < this.scale) { value = ((decimal)value) * 10; scale++; } } } SetInputValue(cbValueSize, value, precision, buffer, intbuffer); // 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) { Marshal.WriteByte(buffer.Ptr, 0, (byte)precision); Marshal.WriteByte(buffer.Ptr, 1, (byte)scale); } } else { SetInputValue(cbValueSize, value, precision, buffer, intbuffer); } // Try to reuse existing bindings // if (_parent.BindingIsValid && _parent.CollectionIsBound) { return; } //SQLBindParameter retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLBindParameter( hstmt, // StatementHandle ordinal, // Parameter Number (short)this._sqldirection, // InputOutputType (short)sql_c_type, // ValueType (short)_bindtype._sql_type, // ParameterType (IntPtr)cchSize, // ColumnSize (IntPtr)scale, // DecimalDigits buffer, // ParameterValuePtr (IntPtr)buffer.Length, // BufferLength intbuffer.Ptr); // StrLen_or_IndPtr if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } if (ODBC32.SQL_C.NUMERIC == sql_c_type) { HandleRef hdesc = parent.GetDescriptorHandle(); // Set descriptor Type // //SQLSetDescField(hdesc, i+1, SQL_DESC_TYPE, (void *)SQL_C_NUMERIC, 0); retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLSetDescFieldW( hdesc, ordinal, (short)ODBC32.SQL_DESC.TYPE, new HandleRef(null, (IntPtr)ODBC32.SQL_C.NUMERIC), 0); if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } // Set precision // cbActual = (int)precision; //SQLSetDescField(hdesc, i+1, SQL_DESC_PRECISION, (void *)precision, 0); retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLSetDescFieldW( hdesc, ordinal, (short)ODBC32.SQL_DESC.PRECISION, new HandleRef(this, (IntPtr)cbActual), 0); if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } // Set scale // // SQLSetDescField(hdesc, i+1, SQL_DESC_SCALE, (void *)llen, 0); cbActual = (int)scale; retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLSetDescFieldW( hdesc, ordinal, (short)ODBC32.SQL_DESC.SCALE, new HandleRef(this, (IntPtr)cbActual), 0); if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } // Set data pointer // // SQLSetDescField(hdesc, i+1, SQL_DESC_DATA_PTR, (void *)&numeric, 0); retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLSetDescFieldW( hdesc, ordinal, (short)ODBC32.SQL_DESC.DATA_PTR, buffer, 0); if (ODBC32.RETCODE.SUCCESS != retcode) { ((OdbcParameterCollection)_parent).Connection.HandleError(hstmt, ODBC32.SQL_HANDLE.STMT, retcode); } // Don't free handle descriptors. They are not allocated. // retcode = (ODBC32.RETCODE) UnsafeNativeMethods.Odbc32.SQLFreeHandle( (short)ODBC32.SQL_HANDLE.DESC, hdesc); } }