Exemplo n.º 1
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);
                }
            }
        }
Exemplo n.º 2
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);
                    }
                }
            }
        }